DevOps
AWS 컨테이너 서비스 3-Tier w/테라폼 & CI/CD 구성하기 - (2) 데모 애플리케이션 개발
yingtao
2025. 6. 2. 21:08
본격적인 아키텍쳐 구축에 앞서 간단한 방문자 기록 애플리케이션을 개발할 것이다.
데모 애플리케이션 구조 개요
- 프론트엔드 : React (정적 페이지) → S3 + CloudFront에 배포
- 백엔드 : Springboot (REST API) → ECS / EKS 에 배포
백엔드 (Springboot) 애플리케이션 개발
- API
- /health : 헬스 체크
- /api/visit : POST 요청으로 이름 + 방문 시간 저장
- /api/visits : GET 요청으로 전체 방문기록 반환
Spring Initializer 설정하기
현재 로컬 환경에 Java 21 버전이 설치되어있어 21버전으로 맞춰서 생성해줬다.
코드 구조
- build.gradle
dependencies {
...
// JPA
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
// H2 DB (개발 및 테스트용 인메모리 DB)
runtimeOnly 'com.h2database:h2'
}
- Entity
DB 테이블과 매핑되는 클래스로 실제로 저장되는 데이터의 구조를 정의한다.
package com.example.demo_backend.domain;
import jakarta.persistence.*;
import java.time.LocalDateTime;
@Entity
public class Visit {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private LocalDateTime visitTime;
public Visit() {}
public Visit(String name, LocalDateTime visitTime) {
this.name = name;
this.visitTime = visitTime;
}
// Getter, Setter 생략 or Lombok(@Getter @Setter) 사용 가능
}
- Visit 객체가 DB의 visit 테이블과 매핑된다.
- 각 필드(id, name, visitTime)은 DB의 컬럼과 매칭된다.
- DTO
Entity를 직접 노출하지 않고 중간에서 데이터를 담아 클라이언트와 데이터를 주고받는다.
package com.example.demo_backend.dto;
public class VisitDTO {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 사용자가 방문 기록을 남길 때 이름만 전달하면 되므로 name 컬럼만 존재. (visitTime은 사용자가 직접 넣지 x)
- Repository
Entity에 대한 DB 접근 담당
package com.example.demo_backend.repository;
import com.example.demo_backend.domain.Visit;
import org.springframework.data.jpa.repository.JpaRepository;
public interface VisitRepository extends JpaRepository<Visit, Long> {
}
- Controller
HTTP 요청 받아 처리하는 API 진입 지점
package com.example.demo_backend.controller;
import com.example.demo_backend.domain.Visit;
import com.example.demo_backend.dto.VisitDTO;
import com.example.demo_backend.repository.VisitRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
@RestController
@RequestMapping("/api")
public class VisitController {
@Autowired
private VisitRepository visitRepo;
@PostMapping("/visit")
public ResponseEntity<?> addVisit(@RequestBody VisitDTO dto) {
visitRepo.save(new Visit(dto.getName(), LocalDateTime.now()));
return ResponseEntity.ok().build();
}
@GetMapping("/visits")
public List<Visit> getVisits() {
return visitRepo.findAll();
}
}
배포 테스트
로컬에서 애플리케이션이 정상적으로 동작하는지 확인한 후, docker 이미지로 패키징하며 테스트를 진행한다.
- 로컬 docker container 환경에서 jar 실행 테스트
Dockerfile 구성 (최상위 디렉토리에 위치해준다.)
# Build
FROM gradle:8.5-jdk21 AS builder
WORKDIR /app
# 전체 프로젝트 복사
COPY . .
# JAR 빌드
RUN gradle build --no-daemon
# Run
FROM openjdk:21
WORKDIR /app
# 위 단계에서 만든 JAR 복사
COPY --from=builder /app/build/libs/demo-backend-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
실행
docker build -t demo-backend:full .
docker run -d -p 8080:8080 demo-backend:full
테스트
다음에는 AWS 인프라 구성과 ECS 를 Terraform으로 구성한 뒤, ECS 환경에서 테스트를 진행할 예정이다.
DB역시 테스트용 H2가 아닌 실제 RDS와 연결할 예정이다.