From eb7c9bcb331134d5bd258a5fe300a9120ca7978a Mon Sep 17 00:00:00 2001 From: hyoseok Date: Tue, 21 Jul 2026 16:23:50 +0900 Subject: [PATCH 1/2] =?UTF-8?q?chore:=20=EB=A1=9C=EC=BB=AC=20=EB=8F=84?= =?UTF-8?q?=EC=BB=A4(api+db)=20=EA=B5=AC=EC=84=B1=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=95=98=EA=B3=A0=20=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98?= =?UTF-8?q?=EB=A5=BC=20=ED=8C=8C=EC=9D=BC=20=EA=B8=B0=EB=B0=98=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docker-compose.local.yml 추가: local 프로파일로 api+db만 기동(모니터링 제외) - application-local.yml에서 LOCAL_ 접두사 제거해 prod와 변수명 통일, ddl-auto update로 로컬 스키마 생성 - 환경 구분을 변수명 접두사 대신 .env.local 파일로 전환하고 .env.local.example 템플릿 추가 - .gitignore에 .env.* 무시 규칙 추가(.env*.example 예외) - DEVELOPMENT.md 로컬 도커 실행법과 환경변수 정정 --- .env.local.example | 21 ++++++++ .gitignore | 2 + docker-compose.local.yml | 62 ++++++++++++++++++++++++ docs/DEVELOPMENT.md | 17 +++++-- src/main/resources/application-local.yml | 18 ++++--- 5 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 .env.local.example create mode 100644 docker-compose.local.yml diff --git a/.env.local.example b/.env.local.example new file mode 100644 index 0000000..faf0b1d --- /dev/null +++ b/.env.local.example @@ -0,0 +1,21 @@ +# git-ranker 로컬 도커 실행용 환경변수 템플릿 (SPRING_PROFILES_ACTIVE=local) +# 사용법: cp .env.local.example .env.local 후 값 채우기 (.env.local 은 gitignore 대상) +# 실행: docker compose --env-file .env.local -f docker-compose.local.yml up -d --build + +# --- Database (local) --- +DB_NAME=git_ranker +DB_USERNAME=root +DB_PASSWORD=root + +# --- GitHub OAuth App (local): 본인 OAuth App 값 --- +GITHUB_CLIENT_ID= +GITHUB_CLIENT_SECRET= +GITHUB_REDIRECT_URI=http://localhost:8080/login/oauth2/code/github + +# --- JWT: JWT_SECRET 은 32바이트 이상 랜덤 시크릿 --- +JWT_SECRET= +JWT_ACCESS_TOKEN_EXPIRATION=900000 +JWT_REFRESH_TOKEN_EXPIRATION=86400000 + +# --- GitHub GraphQL API tokens (comma-separated, 토큰 풀 로테이션) --- +GITHUB_API_TOKENS= diff --git a/.gitignore b/.gitignore index 4226467..16dc9f2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ build/** !**/src/main/**/build/ !**/src/test/**/build/ .env +.env.* +!.env*.example ### STS ### .apt_generated diff --git a/docker-compose.local.yml b/docker-compose.local.yml new file mode 100644 index 0000000..f1c1f14 --- /dev/null +++ b/docker-compose.local.yml @@ -0,0 +1,62 @@ +# 로컬 개발용 (SPRING_PROFILES_ACTIVE=local): API + MySQL 두 컨테이너만. +# 운영 스택(docker-compose.yml)과 분리 — 모니터링(Prometheus/Loki/Grafana) 없음. +# 실행: docker compose --env-file .env.local -f docker-compose.local.yml up -d --build +# 검증: curl http://localhost:9090/actuator/health +services: + git-ranker-api: + build: . + container_name: git-ranker-api-local + ports: + - "8080:8080" + - "127.0.0.1:9090:9090" + environment: + SPRING_PROFILES_ACTIVE: local + # application-local.yml이 ${DB_URL}을 읽음 → 컨테이너에선 localhost가 아니라 DB 서비스명으로 구성 + DB_URL: jdbc:mysql://git-ranker-db:3306/${DB_NAME}?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul + DB_USERNAME: ${DB_USERNAME} + DB_PASSWORD: ${DB_PASSWORD} + GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID} + GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET} + GITHUB_REDIRECT_URI: ${GITHUB_REDIRECT_URI} + GITHUB_API_TOKENS: ${GITHUB_API_TOKENS} + JWT_SECRET: ${JWT_SECRET} + JWT_ACCESS_TOKEN_EXPIRATION: ${JWT_ACCESS_TOKEN_EXPIRATION} + JWT_REFRESH_TOKEN_EXPIRATION: ${JWT_REFRESH_TOKEN_EXPIRATION} + TZ: Asia/Seoul + depends_on: + git-ranker-db: + condition: service_healthy + healthcheck: + test: ["CMD", "wget", "-q", "--spider", "http://localhost:9090/actuator/health"] + interval: 10s + timeout: 5s + retries: 10 + networks: + - git-ranker-local-net + + git-ranker-db: + image: mysql:8.0 + container_name: git-ranker-db-local + restart: unless-stopped + environment: + MYSQL_DATABASE: ${DB_NAME} + MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} # 앱이 root로 접속 (DB_USERNAME=root). MySQL 이미지는 MYSQL_USER=root를 거부하므로 root 계정 사용. + TZ: Asia/Seoul + ports: + - "127.0.0.1:3306:3306" + volumes: + - mysql_data_local:/var/lib/mysql + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 10s + timeout: 5s + retries: 10 + networks: + - git-ranker-local-net + +networks: + git-ranker-local-net: + driver: bridge + +volumes: + mysql_data_local: diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index db4b583..378dba6 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -14,16 +14,16 @@ | 프로파일 | 용도 | 특징 | |---|---|---| -| `local` | 로컬 개발 | localhost MySQL, `LOCAL_*` OAuth env, CORS localhost:3000, 쿠키 non-secure | +| `local` | 로컬 개발 | MySQL, OAuth·DB env(`.env.local`), CORS localhost:3000, 쿠키 non-secure | | `prod` | 운영 | `DB_URL` 등 운영 env, git-ranker.com CORS, secure 쿠키, actuator 노출 축소 | ## 필요 환경 변수 (local) -`spring-dotenv`가 루트 `.env`를 읽는다. +`local`·`prod`가 같은 변수명을 쓰고, 값은 환경별 파일로 구분한다. 로컬 도커는 `--env-file .env.local`로 주입한다(템플릿 `.env.local.example`). ``` -LOCAL_DB_USERNAME, LOCAL_DB_PASSWORD -LOCAL_GITHUB_CLIENT_ID, LOCAL_GITHUB_CLIENT_SECRET, LOCAL_GITHUB_REDIRECT_URI +DB_NAME, DB_USERNAME, DB_PASSWORD +GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, GITHUB_REDIRECT_URI JWT_SECRET, JWT_ACCESS_TOKEN_EXPIRATION, JWT_REFRESH_TOKEN_EXPIRATION GITHUB_API_TOKENS # GitHub GraphQL 토큰 (콤마 구분, 토큰 풀 로테이션) ``` @@ -36,7 +36,14 @@ SPRING_PROFILES_ACTIVE=local ./gradlew bootRun # 앱 실행 (8080) ./gradlew build # 패키징 (CI는 build -x test) ``` -docker-compose 전체 스택(api + db + 모니터링)은 `docker compose up -d`. 서비스: `git-ranker-api`(8080, mgmt 9090), `git-ranker-db`(MySQL 8.0), `prometheus`, `loki`, `promtail`, `grafana`(3001). +로컬 도커(api + db만, `local` 프로파일): + +```bash +docker compose --env-file .env.local -f docker-compose.local.yml up -d --build # 기동 +docker compose --env-file .env.local -f docker-compose.local.yml down # 정지(-v 추가 시 DB 볼륨 삭제) +``` + +운영 전체 스택(api + db + 모니터링)은 `docker compose up -d`. 서비스: `git-ranker-api`(8080, mgmt 9090), `git-ranker-db`(MySQL 8.0), `prometheus`, `loki`, `promtail`, `grafana`(3001). ## 주요 엔드포인트 diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index cbfb6ee..f60a68d 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -4,22 +4,26 @@ spring: on-profile: local datasource: - url: jdbc:mysql://localhost:3306/git_ranker?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul - username: ${LOCAL_DB_USERNAME} - password: ${LOCAL_DB_PASSWORD} + url: ${DB_URL} + username: ${DB_USERNAME} + password: ${DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver + jpa: + hibernate: + ddl-auto: update + security: oauth2: client: registration: github: - client-id: ${LOCAL_GITHUB_CLIENT_ID} - client-secret: ${LOCAL_GITHUB_CLIENT_SECRET} + client-id: ${GITHUB_CLIENT_ID} + client-secret: ${GITHUB_CLIENT_SECRET} scope: - read:user - user:email - redirect-uri: ${LOCAL_GITHUB_REDIRECT_URI} + redirect-uri: ${GITHUB_REDIRECT_URI} jwt: secret: ${JWT_SECRET} @@ -39,4 +43,4 @@ app: authorized-redirect-uri: http://localhost:3000/auth/callback cookie: domain: localhost - secure: false \ No newline at end of file + secure: false From f512eede65c8e73191de5676a97952b8beb9a172 Mon Sep 17 00:00:00 2001 From: hyoseok Date: Tue, 21 Jul 2026 16:48:04 +0900 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=EB=A1=9C=EC=BB=AC=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C=20=EB=AC=B8=EC=84=9C=20=EC=BD=94=EB=93=9C=EB=B8=94?= =?UTF-8?q?=EB=A1=9D=20=EC=96=B8=EC=96=B4=20=EB=AA=85=EC=8B=9C=ED=95=98?= =?UTF-8?q?=EA=B3=A0=20bootRun=EC=9D=98=20.env=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 환경변수 목록 코드블록에 text 언어 지정(MD040 해결) - 호스트 bootRun은 spring-dotenv가 읽는 .env(로컬 변수 전체)가 필요함을 주석으로 명시 --- docs/DEVELOPMENT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 378dba6..a90f5f8 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -21,7 +21,7 @@ `local`·`prod`가 같은 변수명을 쓰고, 값은 환경별 파일로 구분한다. 로컬 도커는 `--env-file .env.local`로 주입한다(템플릿 `.env.local.example`). -``` +```text DB_NAME, DB_USERNAME, DB_PASSWORD GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, GITHUB_REDIRECT_URI JWT_SECRET, JWT_ACCESS_TOKEN_EXPIRATION, JWT_REFRESH_TOKEN_EXPIRATION @@ -31,7 +31,7 @@ GITHUB_API_TOKENS # GitHub GraphQL 토큰 (콤마 구분, 토큰 풀 로테이 ## 실행 ```bash -SPRING_PROFILES_ACTIVE=local ./gradlew bootRun # 앱 실행 (8080) +SPRING_PROFILES_ACTIVE=local ./gradlew bootRun # 호스트 직접 실행: 아래 도커 권장. 이 경로는 spring-dotenv가 읽는 .env(로컬 변수 전체)가 필요 ./gradlew test # 단위 테스트 ./gradlew build # 패키징 (CI는 build -x test) ```