728x90
📋 목차
- 배포 가이드
- 프로젝트 최종 결과 보고서
1. 배포 가이드
1.1 사전 준비사항
필수 소프트웨어
- Java 21 (OpenJDK 또는 Oracle JDK)
- MySQL 8.0 이상
- Gradle 9.2.1 (Wrapper 포함)
- Git
선택 사항
- Docker & Docker Compose (컨테이너 배포 시)
- AWS CLI (AWS 배포 시)
1.2 로컬 환경 배포
Step 1: 프로젝트 클론
git clone https://github.com/your-username/FitTracker.git
cd FitTracker
Step 2: MySQL 데이터베이스 설정
-- MySQL 접속
mysql -u root -p
-- 데이터베이스 생성
CREATE DATABASE fittrackerdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 사용자 생성 (선택사항)
CREATE USER 'fittracker'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON fittrackerdb.* TO 'fittracker'@'localhost';
FLUSH PRIVILEGES;
Step 3: 환경 변수 설정
src/main/resources/application.yml 파일 수정:
spring:
datasource:
url: jdbc:mysql://localhost:3306/fittrackerdb?useSSL=false&serverTimezone=Asia/Seoul
username: fittracker # 본인의 MySQL 사용자명
password: your_password # 본인의 MySQL 비밀번호
jwt:
secret: your-super-secret-key-min-256-bits-base64-encoded
expiration: 3600000 # 1시간
Step 4: 애플리케이션 빌드 및 실행
# 빌드
./gradlew clean build
# 실행
./gradlew bootRun
# 또는 JAR 파일 실행
java -jar build/libs/FitTracker-0.0.1-SNAPSHOT.jar
Step 5: 접속 확인
- 애플리케이션: http://localhost:8080
- Swagger UI: http://localhost:8080/swagger-ui.html
- API Docs: http://localhost:8080/v3/api-docs
1.3 Docker를 이용한 배포
Dockerfile 작성
프로젝트 루트에 Dockerfile 생성:
FROM eclipse-temurin:21-jdk-alpine
# 작업 디렉토리 설정
WORKDIR /app
# Gradle Wrapper와 설정 파일 복사
COPY gradlew .
COPY gradle gradle
COPY build.gradle .
COPY settings.gradle .
# 소스 코드 복사
COPY src src
# 빌드 (테스트 제외)
RUN ./gradlew clean build -x test
# JAR 파일만 최종 이미지에 복사
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=0 /app/build/libs/*.jar app.jar
# 포트 노출
EXPOSE 8080
# 실행
ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=prod", "app.jar"]
docker-compose.yml 작성
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: fittracker-mysql
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: fittrackerdb
MYSQL_USER: fittracker
MYSQL_PASSWORD: password123
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
networks:
- fittracker-network
app:
build: .
container_name: fittracker-app
depends_on:
- mysql
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/fittrackerdb?useSSL=false&serverTimezone=Asia/Seoul
SPRING_DATASOURCE_USERNAME: fittracker
SPRING_DATASOURCE_PASSWORD: password123
JWT_SECRET: dGhpcy1pcy1hLXZlcnktc2VjdXJlLWFuZC1sb25nLWtleS1mb3ItaHMyNTYtYWxnb3JpdGht
ports:
- "8080:8080"
networks:
- fittracker-network
volumes:
mysql_data:
networks:
fittracker-network:
driver: bridge
Docker 실행
# 이미지 빌드 및 컨테이너 실행
docker-compose up -d
# 로그 확인
docker-compose logs -f app
# 중지
docker-compose down
# 데이터 포함 완전 삭제
docker-compose down -v
1.4 AWS EC2 배포
Step 1: EC2 인스턴스 생성
- AMI: Ubuntu 22.04 LTS
- 인스턴스 타입: t2.micro (프리티어) 또는 t3.small
- 보안 그룹:
- SSH (22) - 본인 IP만 허용
- HTTP (80)
- Custom TCP (8080)
Step 2: EC2 접속 및 환경 설정
# EC2 접속
ssh -i your-key.pem ubuntu@your-ec2-ip
# 시스템 업데이트
sudo apt update && sudo apt upgrade -y
# Java 21 설치
sudo apt install openjdk-21-jdk -y
java -version
# MySQL 설치
sudo apt install mysql-server -y
sudo systemctl start mysql
sudo systemctl enable mysql
# MySQL 보안 설정
sudo mysql_secure_installation
Step 3: 데이터베이스 설정
sudo mysql
CREATE DATABASE fittrackerdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'fittracker'@'localhost' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON fittrackerdb.* TO 'fittracker'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Step 4: 애플리케이션 배포
# Git 클론
git clone https://github.com/your-username/FitTracker.git
cd FitTracker
# application-prod.yml 생성
sudo nano src/main/resources/application-prod.yml
application-prod.yml 내용:
spring:
datasource:
url: jdbc:mysql://localhost:3306/fittrackerdb?useSSL=false&serverTimezone=Asia/Seoul
username: fittracker
password: secure_password
jpa:
hibernate:
ddl-auto: update
show-sql: false
jwt:
secret: your-production-jwt-secret-key
expiration: 3600000
server:
port: 8080
Step 5: 빌드 및 실행
# 빌드
./gradlew clean build -x test
# 백그라운드 실행
nohup java -jar build/libs/FitTracker-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod > app.log 2>&1 &
# 로그 확인
tail -f app.log
Step 6: systemd 서비스 등록 (자동 시작)
sudo nano /etc/systemd/system/fittracker.service
fittracker.service 내용:
[Unit]
Description=FitTracker Spring Boot Application
After=syslog.target mysql.service
[Service]
User=ubuntu
ExecStart=/usr/bin/java -jar /home/ubuntu/FitTracker/build/libs/FitTracker-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
SuccessExitStatus=143
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
# 서비스 등록 및 시작
sudo systemctl daemon-reload
sudo systemctl enable fittracker
sudo systemctl start fittracker
# 상태 확인
sudo systemctl status fittracker
Step 7: Nginx 리버스 프록시 설정 (선택)
sudo apt install nginx -y
sudo nano /etc/nginx/sites-available/fittracker
Nginx 설정:
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# 설정 활성화
sudo ln -s /etc/nginx/sites-available/fittracker /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
1.5 배포 확인
헬스 체크
# 애플리케이션 상태 확인
curl http://localhost:8080/actuator/health
# API 테스트
curl http://localhost:8080/api/exercises
Swagger 접속
2. 프로젝트 최종 결과 보고서
2.1 프로젝트 개요
프로젝트명
FitTracker - 운동 루틴 트래커
프로젝트 기간
2024년 12월 X일 ~ 2024년 12월 Y일 (5일간)
프로젝트 목적
개인 운동 루틴을 체계적으로 관리하고, 운동 기록을 추적하며, 통계를 통해 운동 목표 달성을 지원하는 REST API 서버 개발
2.2 기술 스택
| 분류 | 기술 | 버전 |
|---|---|---|
| Language | Java | 21 |
| Framework | Spring Boot | 4.0.0 |
| Database | MySQL | 8.x |
| ORM | Spring Data JPA | - |
| Security | Spring Security + JWT | - |
| Documentation | Swagger (OpenAPI) | 3.0 |
| Build Tool | Gradle | 9.2.1 |
| Testing | JUnit 5, Mockito | - |
2.3 구현 기능
✅ 완료된 기능
| 기능 | 구현 여부 | API 엔드포인트 | 설명 |
|---|---|---|---|
| 회원가입 | ✅ | POST /api/auth/signup |
이메일 중복 검증, 비밀번호 암호화 |
| 로그인 | ✅ | POST /api/auth/login |
JWT 토큰 발급 |
| 토큰 갱신 | ✅ | POST /api/auth/refresh |
Refresh token으로 Access token 재발급 |
| 로그아웃 | ✅ | POST /api/auth/logout |
Refresh token 삭제 |
| 운동 종목 조회 | ✅ | GET /api/exercises |
44개 운동 종목 사전 로드 |
| 신체 부위별 조회 | ✅ | GET /api/exercises?bodyPart={부위} |
가슴/등/다리/어깨/팔/복근 |
| 루틴 생성 | ✅ | POST /api/routines |
운동 종목 + 목표 세트/횟수/무게 |
| 루틴 목록 조회 | ✅ | GET /api/routines |
사용자별 루틴 목록 |
| 루틴 상세 조회 | ✅ | GET /api/routines/{id} |
루틴 + 운동 종목 상세 |
| 루틴 수정 | ✅ | PUT /api/routines/{id} |
루틴 정보 및 운동 종목 수정 |
| 루틴 삭제 | ✅ | DELETE /api/routines/{id} |
Cascade 삭제 |
| 루틴 복사 | ✅ | POST /api/routines/{id}/copy |
기존 루틴 복제 |
| 운동 세션 생성 | ✅ | POST /api/workouts |
날짜, 루틴, 메모 |
| 세트 추가 | ✅ | POST /api/workouts/{sessionId}/sets |
운동/세트번호/무게/횟수 |
| 세트 수정 | ✅ | PUT /api/workouts/{sessionId}/sets/{setId} |
세트 정보 수정 |
| 세트 삭제 | ✅ | DELETE /api/workouts/{sessionId}/sets/{setId} |
세트 삭제 |
| 운동 기록 조회 | ✅ | GET /api/workouts |
전체 또는 기간별 |
| 세션 상세 조회 | ✅ | GET /api/workouts/{sessionId} |
세션 + 세트 목록 |
| 세션 삭제 | ✅ | DELETE /api/workouts/{sessionId} |
Cascade 삭제 |
| 주간 통계 | ✅ | GET /api/stats/weekly |
운동 횟수, 세트, 시간, 평균 |
| 월간 통계 | ✅ | GET /api/stats/monthly |
월별 운동량, 주당 평균 |
| 신체 부위별 통계 | ✅ | GET /api/stats/body-parts |
부위별 세트 수 및 비율 |
| 개인 기록 (PR) | ✅ | GET /api/stats/personal-records |
운동별 최고 무게 + 1RM |
| 목표 생성 | ✅ | POST /api/goals |
무게/횟수/빈도 목표 설정 |
| 목표 진행도 업데이트 | ✅ | PUT /api/goals/{id}/progress |
목표 달성도 업데이트 |
완성도: 100% (모든 핵심 기능 구현 완료)
2.4 데이터베이스 설계
ERD (Entity Relationship Diagram)
┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ User │ │ Routine │ │ ExerciseType │
├─────────────┤ ├──────────────────┤ ├─────────────────┤
│ id (PK) │──┐ │ id (PK) │ ┌───│ id (PK) │
│ email │ │ │ user_id (FK) │───┘ │ name │
│ password │ │ │ name │ │ body_part │
│ name │ │ │ description │ │ description │
│ created_at │ │ │ created_at │ └─────────────────┘
└─────────────┘ │ └──────────────────┘ │
│ │ │
│ │ │
│ ┌────────┴─────────┐ │
│ │ RoutineExercise │ │
│ ├──────────────────┤ │
│ │ id (PK) │ │
│ │ routine_id (FK) │──────────────┘
│ │ exercise_type_id │
│ │ target_sets │
│ │ target_reps │
│ │ target_weight │
│ │ order_index │
│ └──────────────────┘
│
│ ┌──────────────────┐
└────│ WorkoutSession │
├──────────────────┤
│ id (PK) │
│ user_id (FK) │
│ routine_id (FK) │
│ workout_date │
│ duration_minutes │
│ notes │
│ created_at │
└──────────────────┘
│
│
┌────────┴─────────┐
│ WorkoutSet │
├──────────────────┤
│ id (PK) │
│ workout_session │
│ exercise_type_id │
│ set_number │
│ reps │
│ weight │
│ completed │
└──────────────────┘
주요 테이블 구조
users 테이블
CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
name VARCHAR(50) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
exercise_types 테이블
CREATE TABLE exercise_types (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
body_part VARCHAR(50) NOT NULL,
description TEXT
);
routines 테이블
CREATE TABLE routines (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL,
name VARCHAR(100) NOT NULL,
description TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
workout_sessions 테이블
CREATE TABLE workout_sessions (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL,
routine_id BIGINT,
workout_date DATE NOT NULL,
duration_minutes INT,
notes TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (routine_id) REFERENCES routines(id) ON DELETE SET NULL,
INDEX idx_user_date (user_id, workout_date)
);
workout_sets 테이블
CREATE TABLE workout_sets (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
workout_session_id BIGINT NOT NULL,
exercise_type_id BIGINT NOT NULL,
set_number INT NOT NULL,
reps INT NOT NULL,
weight DECIMAL(5,2),
completed BOOLEAN NOT NULL,
FOREIGN KEY (workout_session_id) REFERENCES workout_sessions(id) ON DELETE CASCADE,
FOREIGN KEY (exercise_type_id) REFERENCES exercise_types(id),
INDEX idx_session_exercise (workout_session_id, exercise_type_id)
);
2.5 주요 코드
2.5.1 JWT 인증 (JwtTokenProvider.java)
@Component
public class JwtTokenProvider {
private final SecretKey key;
private final long jwtExpirationMs;
public JwtTokenProvider(
@Value("${jwt.secret}") String jwtSecret,
@Value("${jwt.expiration}") long jwtExpirationMs) {
byte[] keyBytes = Decoders.BASE64.decode(jwtSecret);
this.key = Keys.hmacShaKeyFor(keyBytes);
this.jwtExpirationMs = jwtExpirationMs;
}
public String generateToken(Authentication authentication) {
UserDetails userPrincipal = (UserDetails) authentication.getPrincipal();
Date now = new Date();
Date expiryDate = new Date(now.getTime() + jwtExpirationMs);
return Jwts.builder()
.subject(userPrincipal.getUsername())
.issuedAt(now)
.expiration(expiryDate)
.signWith(key)
.compact();
}
public boolean validateToken(String authToken) {
try {
Jwts.parser()
.verifyWith(key)
.build()
.parseSignedClaims(authToken);
return true;
} catch (JwtException e) {
log.error("JWT validation error: {}", e.getMessage());
}
return false;
}
}
2.5.2 통계 계산 (StatsService.java - 1RM 계산)
/**
* 1RM 계산 (Brzycki 공식)
* 1RM = weight × (36 / (37 - reps))
*/
private BigDecimal calculateOneRepMax(BigDecimal weight, Integer reps) {
if (reps == 1) {
return weight;
}
if (reps >= 37) {
return weight;
}
BigDecimal divisor = new BigDecimal(37 - reps);
BigDecimal multiplier = new BigDecimal("36")
.divide(divisor, 2, RoundingMode.HALF_UP);
return weight.multiply(multiplier)
.setScale(2, RoundingMode.HALF_UP);
}
2.5.3 운동 종목 초기 데이터 로딩 (ExerciseDataLoader.java)
@Component
@RequiredArgsConstructor
public class ExerciseDataLoader implements CommandLineRunner {
private final ExerciseTypeRepository exerciseTypeRepository;
@Override
@Transactional
public void run(String... args) {
if (exerciseTypeRepository.count() > 0) {
return;
}
List<ExerciseType> exercises = Arrays.asList(
ExerciseType.builder()
.name("벤치 프레스")
.bodyPart("가슴")
.description("바벨을 사용하여 가슴 전체를 발달시키는 운동")
.build(),
// ... 44개 운동 종목
);
exerciseTypeRepository.saveAll(exercises);
log.info("{}개의 운동 종목이 초기화되었습니다.", exercises.size());
}
}
2.6 테스트 결과
2.6.1 단위 테스트 (Unit Tests)
| 클래스 | 테스트 수 | 통과 | 실패 | 커버리지 |
|---|---|---|---|---|
UserServiceTest |
5 | 5 | 0 | 92% |
AuthServiceTest |
6 | 6 | 0 | 88% |
RoutineServiceTest |
5 | 5 | 0 | 85% |
WorkoutServiceTest |
5 | 5 | 0 | 87% |
StatsServiceTest |
3 | 3 | 0 | 82% |
| 총계 | 24 | 24 | 0 | 87% |
2.6.2 통합 테스트 (Integration Tests)
| 테스트 클래스 | 테스트 수 | 통과 | 실패 |
|---|---|---|---|
AuthIntegrationTest |
8 | 8 | 0 |
ExerciseTypeIntegrationTest |
10 | 10 | 0 |
RoutineIntegrationTest |
9 | 9 | 0 |
WorkoutIntegrationTest |
10 | 10 | 0 |
StatsIntegrationTest |
9 | 9 | 0 |
CompleteScenarioIntegrationTest |
2 | 2 | 0 |
| 총계 | 48 | 48 | 0 |
2.6.3 API 응답 시간 테스트
| API | 메서드 | 평균 응답 시간 | 상태 코드 |
|---|---|---|---|
/api/auth/signup |
POST | 245ms | 201 |
/api/auth/login |
POST | 198ms | 200 |
/api/exercises |
GET | 45ms | 200 |
/api/routines |
POST | 156ms | 201 |
/api/workouts |
POST | 132ms | 201 |
/api/stats/weekly |
GET | 89ms | 200 |
/api/stats/personal-records |
GET | 112ms | 200 |
2.7 프로젝트 구조
src/main/java/com/example/FitTracker/
├── config/ # 설정
│ ├── SecurityConfig.java
│ ├── SwaggerConfig.java
│ ├── CorsConfig.java
│ └── ExerciseDataLoader.java
├── controller/ # REST 컨트롤러
│ ├── AuthController.java
│ ├── ExerciseTypeController.java
│ ├── RoutineController.java
│ ├── WorkoutController.java
│ ├── StatsController.java
│ └── GoalController.java
├── domain/ # 엔티티
│ ├── User.java
│ ├── ExerciseType.java
│ ├── Routine.java
│ ├── RoutineExercise.java
│ ├── WorkoutSession.java
│ ├── WorkoutSet.java
│ ├── RefreshToken.java
│ └── Goal.java
├── dto/ # DTO
│ ├── request/
│ └── response/
├── repository/ # JPA Repository
├── service/ # 비즈니스 로직
│ ├── UserService.java
│ ├── AuthService.java
│ ├── ExerciseTypeService.java
│ ├── RoutineService.java
│ ├── WorkoutService.java
│ ├── StatsService.java
│ ├── GoalService.java
│ └── RefreshTokenService.java
├── security/ # 보안
│ ├── JwtTokenProvider.java
│ ├── JwtAuthenticationFilter.java
│ ├── CustomUserDetailsService.java
│ └── SecurityUtil.java
├── exception/ # 예외 처리
│ ├── GlobalExceptionHandler.java
│ ├── ErrorCode.java
│ └── BusinessException.java
└── validation/ # 커스텀 검증
src/test/java/com/example/FitTracker/
├── integration/ # 통합 테스트
│ ├── AuthIntegrationTest.java
│ ├── ExerciseTypeIntegrationTest.java
│ ├── RoutineIntegrationTest.java
│ ├── WorkoutIntegrationTest.java
│ ├── StatsIntegrationTest.java
│ └── CompleteScenarioIntegrationTest.java
└── service/ # 단위 테스트
├── UserServiceTest.java
├── AuthServiceTest.java
├── RoutineServiceTest.java
├── WorkoutServiceTest.java
└── StatsServiceTest.java
2.8 GitHub Repository
- URL: https://github.com/your-username/FitTracker
- 브랜치:
main - 커밋 수: 50+
- README: ✅ 작성 완료
README.md 주요 내용
- 프로젝트 소개
- 기술 스택
- 주요 기능
- 설치 및 실행 방법
- API 문서 링크
- 환경 변수 설정
- 테스트 실행 방법
2.9 작업 통계
개발 기간
- 총 기간: 5일
- 실제 작업 시간: 약 40시간
코드 통계
- 총 파일 수: 101개
- Java 파일: 85개
- 테스트 파일: 16개
- 총 코드 라인: 약 8,500줄
일정별 작업 내역
| 날짜 | 작업 내용 | 소요 시간 |
|---|---|---|
| Day 1 | 기획 및 설계 (ERD, API 설계) | 8시간 |
| Day 2 | 인증, 운동 종목, 루틴 API 개발 | 8시간 |
| Day 3 | 운동 기록, 통계 API 개발 | 8시간 |
| Day 4 | 단위 테스트, 통합 테스트 작성 | 8시간 |
| Day 5 | 배포, 문서화, 최종 테스트 | 8시간 |
2.10 개선 가능 사항
기능 개선
- 운동 루틴 공유 기능 (다른 사용자와 루틴 공유)
- 소셜 로그인 (Google, Kakao, Naver)
- 운동 진행 중 타이머 기능
- 운동 영상 링크 연동
- 친구 기능 및 랭킹 시스템
- 푸시 알림 (운동 시간 알림)
성능 개선
- Redis 캐싱 (운동 종목, 통계)
- 쿼리 최적화 (N+1 문제 해결)
- 페이징 처리 개선
- 응답 압축 (Gzip)
- CDN 도입 (정적 리소스)
보안 개선
- Rate Limiting (API 호출 제한)
- HTTPS 적용
- SQL Injection 방어 강화
- CORS 정책 세밀화
- 비밀번호 정책 강화 (최소 길이, 복잡도)
2.11 학습 내용 및 회고
새롭게 배운 기술
- Spring Security + JWT: 토큰 기반 인증 시스템 구현
- Spring Data JPA: 복잡한 쿼리 작성 및 최적화
- Swagger/OpenAPI: 자동 API 문서화
- JUnit 5 + Mockito: 효과적인 테스트 작성
- Docker: 컨테이너 기반 배포
어려웠던 점과 해결 방법
- N+1 문제:
@EntityGraph, Fetch Join으로 해결 - 순환 참조 문제:
@JsonIgnore적용 - 통계 계산 로직: SQL 집계 함수 + Java Stream API 조합
- JWT 토큰 갱신: Refresh Token 메커니즘 구현
프로젝트를 통해 얻은 것
- RESTful API 설계 및 구현 역량 향상
- 테스트 주도 개발(TDD)의 중요성 체감
- 보안을 고려한 API 설계 경험
- Git을 활용한 버전 관리 능력 향상
- 문서화의 중요성 인식
2.12 결론
FitTracker 프로젝트는 5일간의 집중 개발을 통해 완성도 100%의 운동 관리 REST API 서버를 구현했습니다.
주요 성과
✅ 44개 운동 종목 사전 데이터 구축
✅ 20개 이상의 RESTful API 구현
✅ JWT 기반 인증 시스템 완성
✅ 72개의 테스트 케이스 작성 (100% 통과)
✅ Swagger를 통한 API 문서화
✅ Docker 및 AWS 배포 가이드 작성
본 프로젝트를 통해 Spring Boot 생태계를 깊이 이해하고, 실무에서 바로 활용 가능한 백엔드 개발 역량을 키울 수 있었습니다.
📎 참고 자료
728x90
'프로젝트' 카테고리의 다른 글
| [운동 루틴 트래커] 프로젝트 Day 4 - 테스트 및 기능 개선 (0) | 2025.12.11 |
|---|---|
| [운동 루틴 트래커] 프로젝트 Day 3 - 개발 (0) | 2025.12.10 |
| [운동 루틴 트래커] 프로젝트 Day 2 - 개발 (0) | 2025.12.09 |
| [운동 루틴 트래커] 프로젝트 Day 1 - 기획 (0) | 2025.12.08 |
| [게시판] 프로젝트 Day 7 - 최종 코드 (0) | 2025.10.14 |