Spring Boot 기반 백엔드 프로젝트입니다.
게시판/인증/기업 데이터/리포트 기능을 제공하며, 배포는 AWS CodeBuild + CodeDeploy 기반으로 운영합니다.
BackBackBack은 기업 재무/뉴스/리포트 데이터를 통합해 투자 판단을 돕는 분석형 백엔드입니다.
단순 게시판 서비스가 아니라, 기업 코드(종목코드) 기준으로 다음을 한 흐름으로 제공합니다.
- 기업 기본 정보/분기별 지표 조회
- AI 리포트 생성 및 PDF 연계 조회
- 워치리스트 기반 모니터링
- 인증/권한 기반 사용자 기능 분리(USER/ADMIN)
즉, 이 프로젝트의 핵심 목적은 여러 데이터 소스(정형 재무 데이터 + 뉴스/AI 결과)를 API로 표준화해, 프론트엔드/운영 배치에서 재사용 가능한 분석 플랫폼을 만드는 것입니다.
- 일반 사용자: 관심 기업을 워치리스트에 등록하고 최신 지표/인사이트를 조회
- 관리자: 기업 데이터 동기화, 리포트 적재/발행, 운영성 배치 관리
- 개발/운영자: CodeBuild/CodeDeploy 파이프라인으로 일관된 배포 및 롤백 수행
- 프로젝트 개요
- 기술 스택
- 디렉터리 구조
- 빠른 시작 (로컬 JVM)
- 빠른 시작 (로컬 Docker)
- 환경변수 가이드
- 테스트 및 검증
- 배포 파이프라인
- 롤백 가이드
- 트러블슈팅
- 협업 규칙 및 문서
- ERD / DB 스키마
- API 서버: Spring Boot 3.5.9, Java 21
- 저장소: MySQL, Redis
- 마이그레이션: Flyway
- 인증: JWT, Spring Security
- 운영 배포: CodeBuild -> ECR -> CodeDeploy -> EC2
- Language: Java 21
- Framework: Spring Boot 3.5.9
- Build: Gradle 8.14.3
- DB: MySQL 8, H2(test/perf)
- Cache: Redis 7
- Infra: AWS ECR, CodeBuild, CodeDeploy, EC2
.
├── src/
│ ├── main/resources/
│ │ ├── application*.yaml
│ │ └── db/migration/
│ └── test/
├── scripts/ # CodeDeploy 훅 스크립트
│ ├── lib/deploy-runtime.sh # 런타임 분기 공통 로직
│ └── tests/deploy-runtime-test.sh
├── docker-compose.app.yml # 운영 기준 compose
├── docker-compose.local.yml # 로컬 오버라이드 compose
├── buildspec.yml # CodeBuild
├── appspec.yml # CodeDeploy
└── README.MD
- Java 21
- 로컬 MySQL/Redis 실행
.env.example참고해 환경변수 주입
export SPRING_PROFILES_ACTIVE=dev
export SPRING_DATASOURCE_URL=jdbc:mysql://localhost:3306/bigprj?serverTimezone=Asia/Seoul&useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=UTF-8
export SPRING_DATASOURCE_USERNAME=bigprj
export SPRING_DATASOURCE_PASSWORD=bigprj
export REDIS_HOST=localhost
export REDIS_PORT=6379
export LOG_PATH=./logs
export LOG_FILE=./logs/project.log
./gradlew bootRun- Health:
http://localhost:8080/actuator/health - Swagger:
http://localhost:8080/swagger-ui.html
운영용 compose(docker-compose.app.yml)에 로컬 오버라이드(docker-compose.local.yml)를 합쳐 실행합니다.
cp .env.example .env
mkdir -p secrets/jwt logs upload/filesJWT 키 파일을 secrets/jwt/private.pem, secrets/jwt/public.pem 경로에 준비하세요.
./gradlew bootJar
docker build -t local-backbackback:dev .APP_IMAGE=local-backbackback:dev \
APP_ENV_FILE=.env \
LOCAL_ENV_FILE=.env \
docker compose -f docker-compose.app.yml -f docker-compose.local.yml up -dAPP_ENV_FILE=.env \
LOCAL_ENV_FILE=.env \
docker compose -f docker-compose.app.yml -f docker-compose.local.yml downSPRING_PROFILES_ACTIVE(dev또는prod)SPRING_DATASOURCE_URLSPRING_DATASOURCE_USERNAMESPRING_DATASOURCE_PASSWORDJWT_ISSUERJWT_PRIVATE_KEY_PATHJWT_PUBLIC_KEY_PATHJWT_CURRENT_KIDAPP_TOKEN_HASH_PEPPER_B64(Base64 인코딩된 pepper, 토큰 해시 필수값)APP_BASE_URLAPI_BASE_URL
REDIS_HOST,REDIS_PORT,REDIS_PASSWORDSPRING_THREADS_VIRTUAL_ENABLED(JDK virtual thread 토글)APP_VIRTUAL_THREAD_ENABLED(앱 비동기 실행기 전체 virtual thread 토글)APP_VIRTUAL_THREAD_INSIGHT_ENABLED(insightExecutor만 virtual thread 토글)APP_VIRTUAL_THREAD_EMAIL_ENABLED(emailExecutor만 virtual thread 토글)APP_AI_JOB_KAFKA_ENABLED(Kafka 기반 AI job 경로 토글)TURNSTILE_SECRET_KEY,TURNSTILE_SITE_KEYEMAIL_USERNAME,EMAIL_PASSWORDAWS_S3_BUCKET,AWS_REGION,AWS_S3_PREFIXLOG_PATH,LOG_FILE
DEPLOY_RUNTIME:systemd또는dockerCOMPOSE_FILE_PATH: 기본/opt/project/docker-compose.app.ymlIMAGE_ENV_FILE: 기본/opt/project/image-uri.envAPP_ENV_FILE: compose가 읽을 env 파일 경로REDIS_HOST_DOCKER: docker 네트워크 redis 서비스명(권장redis)SPRING_THREADS_VIRTUAL_ENABLED: 기본falseAPP_VIRTUAL_THREAD_ENABLED: 기본false(운영에서 비Kafka 비동기를 virtual thread로 쓰려면true권장)APP_VIRTUAL_THREAD_INSIGHT_ENABLED: 기본falseAPP_VIRTUAL_THREAD_EMAIL_ENABLED: 기본falseAPP_AI_JOB_KAFKA_ENABLED: 기본true
- 로컬 템플릿:
.env.example - 서버 템플릿:
scripts/systemd/backbackback.env.example
./gradlew testbash -n scripts/*.sh scripts/lib/*.sh scripts/tests/*.sh
bash scripts/tests/deploy-runtime-test.shscripts/health-check.sh가/actuator/health200을 반환해야 합니다.
현재 배포 경로:
- CodeBuild: 테스트 -> Docker build -> ECR push
- 아티팩트 생성:
image-uri.env,docker-compose.app.yml,scripts/**/*,appspec.yml - CodeDeploy: 훅 실행으로 서버 기동/검증
주요 파일:
buildspec.ymlappspec.ymlscripts/setup-server.shscripts/install-app.shscripts/start-server.shscripts/stop-server.shscripts/health-check.sh
ECR:
160885260227.dkr.ecr.ap-northeast-2.amazonaws.com/aivle-back-app
DEPLOY_RUNTIME=systemd로 전환하면 기존 systemd(JAR) 경로로 복귀할 수 있습니다.
- 이전 정상 태그로
APP_IMAGE를 지정해 재배포합니다. - 배포 후
scripts/health-check.sh로 성공 여부를 확인합니다.
- 원인: EC2 IAM Role 미부착 또는 권한 부족
- 해결: Instance Profile 부착 및 ECR/CodeDeploy 권한 점검
- 원인: 해당 Role에
ecr:CreateRepository없음 - 해결: 콘솔에서 ECR 선생성 또는 권한 추가
- 원인:
APP_ENV_FILE또는LOCAL_ENV_FILE경로 불일치 - 해결: 실행 시 env 파일 경로를 명시
- 원인:
JWT_PRIVATE_KEY_PATH,JWT_PUBLIC_KEY_PATH와 실제 마운트 경로 불일치 - 해결: 컨테이너 내부 경로(
/secrets/jwt/*.pem)와 env 일치
- 원인: Docker 환경에서
REDIS_HOST=localhost사용 - 해결: Docker에서는
REDIS_HOST_DOCKER=redis사용
- Codex 작업 규칙의 기준 문서입니다.
- 언어/브랜치/커밋/컨텍스트 규칙을 따릅니다.
- PR 작성 기본 템플릿입니다.
- 작업 컨텍스트 기록 파일입니다.
- ERD 요약:
ERD.md - Flyway DDL 원본:
src/main/resources/db/migration/V1__init.sql