🔑늘 하던 대로만 하면, 늘 얻던 것만 얻는다 - 토니 로빈스(Tony Robbins)
💡 초기세팅
📃 Spring Initializr를 통해 REST APISpring Boot 프로젝트를 생성했습니다. Java 버전은 21, 의존성은 Spring Web, Lombok, Spring Security, dynamodb 등을 추가합니다. 프로젝트 생성 후 Intellij 에서 열어줬습니다
💻의존성 목록
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/software.amazon.awssdk/dynamodb -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb</artifactId>
<version>2.30.35</version>
</dependency>
</dependencies>
⬆️ DynamoDB와 연결하기 위해 AWS SDK v2의 DynamoDB 의존성을 추가해야합니다
💡 IAM 생성
📃 DynamoDB, S3와 같은 AWS 서비스를 이용하기 위해서는 접근을 위한 IAM 사용자를 생성하고 AmazonDynamoDBFullAccess와 같은 적절한 권한을 부여한 뒤, ACCESS KEY, SECRET KEY를 발급받아야합니다.
💻AWS IAM 콘솔
⬆️ IAM 키는 DynamoDB에 접근할 수 있는 보안 권한을 설정합니다. 또한 SECRET KEY 처음 생성할 때만 확인이 가능하기 때문에, 적절한 곳에 보관해야합니다.
💡 KEY 보관 방법
📃 발급받은 AWS의 민감한 ACCESS_KEY와 SECRET_KEY는 절대로 코드에 직접 넣지 않고 환경변수로 관리합니다.
💻 application.KEY.yml
AWS_KEY:
AWS_REGION:
YOUR_REGION
AWS_ACCESS_KEY_ID:
YOUR_ACCESS_KEY
AWS_SECRET_ACCESS_KEY:
YOUR_SECRET_ACCESS_KEY
💻 application.yml
spring:
application:
name: healing-hub
profiles:
active: KEY
aws:
region: ${AWS_REGION}
accessKeyId: ${AWS_ACCESS_KEY_ID}
secretAccessKey: ${AWS_SECRET_ACCESS_KEY}
⬆️ 다음과 같이 변수명으로 키를 관리하는 방식은 보안성을 높여주고, 외부에 키가 노출되는 것을 방지할 수 있습니다
💡 DynamoDBConfig
📃 DynamoDbClient라는 객체를 Spring의 Bean으로 등록하는 과정입니다. Spring에서 Bean이란 애플리케이션이 실행될 때 미리 만들어 놓고, 필요할 때마다 꺼내 쓸 수 있도록 준비된 객체입니다. 이 Bean은 AWS DynamoDB와 연결하는 데 필요한 설정값을 포함하고 있습니다. 여기서 사용하는 값(region, accessKey, secretKey)은 AWS IAM 사용자를 생성하고 발급받은 액세스 키와 비밀 액세스 키이며, 애플리케이션 설정파일 또는 환경변수에 정의되어 있습니다
💻 DynamoDBConfig
@Configuration
public class DynamoDBConfig {
@Value("${aws.region}") // AWS 리전 정보
private String region;
@Value("${aws.accessKeyId}") // AWS 접근 키
private String accessKey;
@Value("${aws.secretAccessKey}") // AWS 비밀 접근 키
private String secretKey;
@Bean // DynamoDbClient를 빈으로 등록하여 언제든지 가져다 쓸 수 있게 합니다.
public DynamoDbClient dynamoDbClient() {
return DynamoDbClient.builder()
.region(Region.of(region)) // 리전 설정 (ex: ap-northeast-2)
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(accessKey, secretKey))) // AWS 자격증명 설정
.build();
}
}
⬆️ 이 설정이 완료되면, 애플리케이션 전역에서 DynamoDB와의 통신을 담당할 DynamoDbClient 객체를 편리하게 사용할 수 있습니다. 클라이언트는 Spring이 관리하는 객체로, 이후에 다른 서비스나 리포지토리에서 의존성을 주입하여 쉽게 사용할 수 있게 됩니다
💡 SecurityConfig
📃 이 클래스는 Spring Security를 설정하는 부분입니다. 보통 API를 만들 때는 보안 설정(로그인, 인증)을 사용합니다. 하지만 개발 초반이나 간단한 테스트 용도로 빠르게 API를 테스트할 때는 보안 인증 절차가 방해될 수 있습니다. 따라서 이 설정에서는 API 중 일부 경로(/, /products)를 인증 없이 누구나 접근할 수 있도록 허용하고 있습니다
💻 SecurityConfig
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // CSRF 공격 방어 기능 비활성화 (개발 편의성)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/products").permitAll() // "/", "/products"는 누구나 접근 가능
.anyRequest().authenticated() // 나머지 모든 요청은 인증 필요
);
return http.build();
}
}
⬆️ 이렇게 하면 /products URL 접근 시 별도의 로그인이나 인증절차 없이 간편하게 데이터를 조회하고 개발을 진행할 수 있습니다. 실제 서비스 운영 시에는 다시 인증 절차를 추가하는 것이 안전합니다
💡 Repository와 Controller 설명
📃 Spring Boot 애플리케이션은 주로 Controller와 Repository 구조로 이루어집니다.
- Repository: 데이터베이스와 통신하여 데이터를 가져오는 역할
- Controller: 가져온 데이터를 API 형태로 외부에 제공하는 역할
💻 CODE (Repository)
@Repository
public class ProductRepository {
private final DynamoDbClient dynamoDbClient; // DynamoDB와 통신하기 위한 클라이언트
private final String tableName = "products"; // DynamoDB의 테이블 이름
public ProductRepository(DynamoDbClient dynamoDbClient) {
this.dynamoDbClient = dynamoDbClient;
}
public List<Product> getAllProducts() {
ScanRequest scanRequest = ScanRequest.builder()
.tableName(tableName)
.build();
ScanResponse response = dynamoDbClient.scan(scanRequest);
// DynamoDB에서 가져온 데이터를 Product 객체로 변환
return response.items().stream()
.map(item -> new Product(
item.get("id") != null ? item.get("id").s() : "",
item.get("name") != null ? item.get("name").s() : "",
item.get("price") != null ? item.get("price").s() : "",
item.get("category") != null ? item.get("category").s() : "",
item.get("description") != null ? item.get("description").s() : "",
item.get("image") != null ? item.get("image").s() : "",
item.get("popularity") != null ? item.get("popularity").s() : "",
item.get("product_detail_url") != null ? item.get("product_detail_url").s() : ""
))
.collect(Collectors.toList());
}
}
💻 CODE (Controller)
@RestController
@RequestMapping("/products")
public class ProductController {
private final ProductRepository repository;
public ProductController(ProductRepository repository) {
this.repository = repository;
}
@GetMapping // GET 방식으로 "/products" URL 호출 시 데이터 제공
public List<Product> getProducts() {
return repository.getAllProducts();
}
}
⬆️ ProductRepository는 DynamoDB의 products 테이블에서 데이터를 가져와서 Product라는 자바 객체(일반적으로 DTO라 부릅니다)로 변환해주는 역할입니다. DynamoDB는 데이터 구조가 유연하여 일부 데이터 항목이 누락된 경우가 많기 때문에, null 체크를 통해 처리해줬습니다.
⬆️ ProductController는 HTTP 요청을 처리하여 클라이언트에게 JSON 형태로 데이터를 전달합니다. REST API 방식으로 데이터를 외부에 제공하므로 웹, 앱 등 다양한 클라이언트에서 쉽게 사용할 수 있습니다.
📝 Result
위 과정을 통해 Springboot활용해서 REST API로 DynamoDB에서 데이터를 가지고와 제공하는 간단한 웹 애플리케이션 구조를 완성했습니다