10 KiB
| kind | title | description | owner | stability | last_reviewed |
|---|---|---|---|---|---|
| usage | 로컬 개발환경 온보딩 | bibimbap 을 로컬에서 기동하는 두 경로(Docker / 직접 실행) 와 DB 스키마 초기화·트러블슈팅을 실행 검증 근거와 함께 정리한 가이드. | art | living | 2026-06-17 |
로컬 개발환경 온보딩
이 문서는 bibimbap 을 처음 받는 개발자가 로컬에서 앱을 띄우기까지의 전 과정을 정리한다. 모든 명령·출력은 실제 실행으로 검증된 것만 싣는다.
권장 경로는 A: Docker 다. 호스트에 직접 띄우려면 B: 직접 실행 을 따른다. 두 경로 모두 전 과정 실행 검증을 통과했다.
docs-first: 이 문서를 읽기 전
../index.md→./index.md순으로 카테고리 위치를 확인했다고 가정한다. 기술부채 맥락은../analysis/2026-06-16-project-analysis.md참조.
1. 사전 요구사항
| 항목 | 버전/사실 | 비고 |
|---|---|---|
| Java | 21 (검증: Temurin/OpenJDK 21.0.11) | pom.xml:25 java.version=21 |
| Maven | mvnw wrapper 3.9.14 | 별도 mvn 설치 불요. ./mvnw 사용 |
| Docker | 29.3.1 | 경로 A 권장 |
| Docker Compose | v5.1.1 | docker compose 서브커맨드 |
| PostgreSQL | 16 (컨테이너) | docker-compose.yml db 서비스 |
온라인 빌드 전제: 이 프로젝트는 spring-boot 3.5.14-SNAPSHOT 에 고정돼 있다(pom.xml:29, dependencyManagement import 는 pom.xml:200-219). SNAPSHOT 의존성은 repo.spring.io/snapshot 에서 온라인으로 받아야 하므로 오프라인 빌드는 불가하다. 회사 TLS 인터셉션 프록시 환경에서는 §6 트러블슈팅을 먼저 확인한다.
2. 경로 A: Docker (compose 기반) — 권장
전 과정 실행 검증됨.
단계
# 1. 환경파일 준비 (이미 있으면 생략). 비밀값은 .env 에 두며 gitignore 된다.
cp .env.example .env
# 2. (회사 TLS 프록시 환경만) certs/ 에 프록시 CA 배치 — §6 참조
# 3. 빌드 + 기동
docker compose up --build # 또는 -d 로 백그라운드
# 4. 홈 접속
open http://localhost:8080/ # HTTP 200
구성요소
docker-compose.yml: db(postgres:16, 최초 기동 시db/schema.sql자동 주입) + app(멀티스테이지 JDK21 빌드, 임베디드 Tomcat 실행).- 비밀값 주입: app 은
SPRING_DATASOURCE_URL/SPRING_DATASOURCE_USERNAME/SPRING_DATASOURCE_PASSWORD환경변수(.env)로 db 에 접속한다. 이미지·git 에 비밀값을 포함하지 않는다. - SNAPSHOT 네트워크 의존: Dockerfile 빌드 스테이지가 온라인으로 의존성을 받는다. TLS 인터셉션 프록시 환경에선 CA 주입이 필요하다(§6).
- 업로드 경로:
APP_UPLOAD_GAME_STORAGE_PATH=/app/uploads/game+ named volumeuploads로 영속한다. - 호스트 DB 포트:
.env의DB_PORT(기본 5432, 충돌 시 변경). 앱→db 통신은 컨테이너 내부db:5432라 호스트 포트 변경의 영향을 받지 않는다.
검증 증거
$ docker compose build app
[INFO] BUILD SUCCESS
# image bibimbap-app 생성
$ docker compose ps
# db Up (healthy)
# app Up 0.0.0.0:8080->8080
$ curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/
200 # 홈 35143 bytes 렌더
$ curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/recruit
200
- DB:
dev스키마에 6테이블 생성 확인.games/users/recruit_posts조회 0행 무에러. - 라운드트립 증거:
dev.games에 행을 삽입 → 홈에 해당 게임명이 1회 노출됨을 확인 → DB → MyBatis → JSP 전체 경로 동작 확인.
3. 경로 B: 직접 실행 (호스트)
전 과정 실행 검증됨 (macOS Apple Silicon 기준).
단계
# 1. JDK21 설치 (검증한 방법). keg-only 라 sudo 불요.
brew install openjdk@21
export JAVA_HOME=/opt/homebrew/opt/openjdk@21
# 2. wrapper 실행권한 (최초 1회 필요했음)
chmod +x mvnw
# 3. (회사 TLS 프록시 환경만) 프록시 CA 를 호스트 JDK cacerts 에 import — §6 참조
keytool -importcert -noprompt -trustcacerts -cacerts -storepass changeit \
-alias proxy -file certs/corporate-proxy-ca.crt
# 중요: curl 이 성공해도 JDK 는 자체 truststore 를 쓰므로 별도 import 가 필요하다.
# 4. DB 준비 — Docker DB 단독 사용 (권장) 또는 로컬 PostgreSQL
docker compose up -d db # localhost:5433 (.env DB_PORT 기준)
# 로컬 PG 를 쓰면: PostgreSQL 16 설치 후 db/schema.sql 적용
# 5. dev datasource 설정 파일 작성 (gitignore)
cp src/main/resources/dev/db.properties.example src/main/resources/dev/db.properties
# 편집: url=jdbc:postgresql://localhost:5433/bibimbap?currentSchema=dev , user/pass 실값
# 6. 빌드 / 테스트 / 실행 (JAVA_HOME 지정 상태)
./mvnw -P dev test
./mvnw -P dev clean package spring-boot:repackage -DskipTests
./mvnw -P dev spring-boot:run
# 7. 홈 접속
open http://localhost:8080/ # HTTP 200
검증 증거
$ ./mvnw -P dev test
Tests run: 6, Failures: 0, Errors: 0 # UserControllerCsrfTest 5 + BibimbapApplicationTests 1
[INFO] BUILD SUCCESS
$ ./mvnw -P dev clean package spring-boot:repackage -DskipTests
# WAR: target/bibimbap-0.0.1-SNAPSHOT.war (30MB, 실행형)
$ ./mvnw -P dev spring-boot:run
# Tomcat started on port 8080
# Started BibimbapApplication
# 홈 / -> 200 (provided tomcat 으로 정상 run)
중요 주의: -P dev 는 필수
이 pom 은 spring-boot-starter-parent 를 쓰지 않고 dependencyManagement import 만 한다(pom.xml:200-219). 그 결과:
- (a) profile 을 지정하지 않으면
application.properties의@app.profile@필터링이 동작하지 않아spring.profiles.active가 깨진다. - (b)
spring-boot:repackagegoal 이package단계에 자동 바인딩되지 않는다. 명시 호출하지 않으면 비실행 WAR 가 나오고no main manifest attribute로 실패한다.
4. DB 스키마 초기화 절차
핵심 사실: flyway / liquibase 가 없다. 마이그레이션 자동화가 없으며, 작업 시작 시점에 전체 스키마 SQL 도 부재였다. 6테이블 중 recruit_posts 만 권위 DDL(docs/recruit-posts-ddl.sql)이 존재했다.
본 작업에서 db/schema.sql 을 복원했다:
recruit_posts— 권위 DDL 그대로.user_auth_identities— security-hardening 의 active-unique index 포함.users/games/game_comments/game_likes— 비권위 복원본. 매퍼@Insert/@Select컬럼과 data POJO Java 타입에서 역추출했다. 컬럼명·유무는 매퍼와 일치 확인했으나, 타입·길이·제약은 추론값이다.
적용 방법:
- Docker: db 컨테이너 최초 기동 시
db/schema.sql이docker-entrypoint-initdb.d로 자동 1회 실행된다(dev스키마를 채우고,live는 빈 스키마만 생성). 스키마 변경을 재적용하려면docker compose down -v후 재기동한다. - 호스트 로컬 PG:
psql -f db/schema.sql로 수동 적용한다.
경고:
db/schema.sql의 5개 비권위 테이블(users / games / game_comments / game_likes 및 user_auth_identities 의 추론 부분)은 운영 DBpg_dump와 대조하기 전까지 타입을 신뢰하지 말 것. §7 미해결 항목 참조.
5. 검증 체크리스트
실제 통과한 항목은 [x] 다.
- A: 빈 상태 → 의존성 수신 → 컴파일 (BUILD SUCCESS)
- A: 앱 기동 후 홈
/HTTP 200 + 게임목록 렌더 - A: DB 연결 정상 (6테이블, 빈 조회 무에러, 삽입 → 홈노출 라운드트립)
- B:
./mvnw -P dev testgreen (6 tests, 0 fail) - B:
./mvnw -P dev packageWAR 산출 - B:
./mvnw -P dev spring-boot:run홈 200 (provided tomcat) - 신규 환경파일 비밀값 비커밋 (
.env/db.properties/certs/*.crtgitignore 확인) - (수동) 실제 사용자 환경에서 회원가입/로그인/게임등록 등 기능 스모크는 미수행 — 사용자 환경 검증 권장.
6. 트러블슈팅
TLS 인터셉션 프록시로 SNAPSHOT 빌드 실패
- 증상:
PKIX path building failed: unable to find valid certification path to requested target+Non-resolvable import POM: spring-boot-dependencies:3.5.14-SNAPSHOT. - 원인:
repo.spring.io인증서를 회사 프록시(예: Cloudflare Gateway / Zero Trust)가 재서명하는데, JDK truststore 에 그 CA 가 없다.curl은 시스템 키체인을 쓰므로 성공해도 JDK 는 자체 cacerts 를 쓰기 때문에 별도 import 가 필요하다. - 해결:
- Docker —
certs/*.crt를 Dockerfile 이 자동 주입한다. - 호스트 — §3 단계 3 의
keytoolimport 를 수행한다.
- Docker —
- CA 추출 예시 (macOS):
security find-certificate -a -c "Gateway CA - Cloudflare Managed" -p \
~/Library/Keychains/login.keychain-db /Library/Keychains/System.keychain \
> certs/corporate-proxy-ca.crt
자세한 내용은 certs/README.md 참조.
db.properties 누락
spring.config.import 가 optional: 이라 컨텍스트는 뜨지만 datasource 가 구성되지 않아 DB 사용 페이지에서 실패한다. .example 을 복사하고 실값을 입력한다(§3 단계 5).
포트 충돌
- 호스트 5432 가 다른 postgres 에 점유되면
.env의DB_PORT를 변경한다(예 5433). 실제로 본 환경에서는 기존kord-postgres가 5432 를 점유해 5433 으로 회피했다. - 8080 이 점유되면
APP_PORT를 변경한다.
Java 미설치
Unable to locate a Java Runtime → §3 단계 1 의 brew install openjdk@21.
"no main manifest attribute"
§3 주의 참조 — spring-boot:repackage 를 명시 호출해야 실행형 WAR 가 나온다.
7. 알려진 미해결
- DDL 전체본 부재:
db/schema.sql5테이블은 비권위 복원본(타입 추론)이다. 운영 DBpg_dump대조가 필요하다. (open_question) - spring-boot 3.5.14-SNAPSHOT 고정 결정 대기: SNAPSHOT 은 비재현·온라인 의존이다. 안정 릴리스 고정 여부가 미결이다 —
../analysis/2026-06-16-project-analysis.mdopen_question #4. - 기능 스모크 미수행: 비권위
db/schema.sql타입으로 인해 가입/업로드 등 기능 스모크는 수행하지 않았다.
참고: 본 가이드가 참조하는 생성 파일
- 루트:
docker-compose.yml,Dockerfile,.env.example,.dockerignore,db/schema.sql,certs/README.md. - gitignore 대상(비밀):
.env,src/main/resources/dev/db.properties,certs/*.crt.