---
schema_version: 2
session_id: 20260617-110836
resumed_from: null
started_at: 2026-06-17T11:08:36+09:00
ended_at: 2026-06-17T11:48:00+09:00
user_request: |
  bibimbap 로컬 개발환경 셋업 분석 → 검증 → 온보딩 문서화.
  두 경로(A: Docker / B: 호스트 직접) 모두 실제 실행으로 검증, DDL 갭 해결,
  docs/usage/local-setup.md 산출. 추측 금지, 명령어·출력·근거 기록.
  비밀값 비커밋, src/pom 최소수정, git status 보호.
---

# Summary

두 셋업 경로를 모두 **실제 실행으로 검증 완료**. 핵심 산출: 복원 `db/schema.sql`(6테이블), Docker 스택(compose+Dockerfile+.env.example+.dockerignore), 온보딩 문서.

검증 결과:
- **Path A (Docker)**: `docker compose build` BUILD SUCCESS → `up -d` db healthy + app 기동 → 홈 `/` HTTP 200(35KB 렌더) + `/recruit` 200 + dev 스키마 6테이블 + 삽입→홈노출 라운드트립으로 DB→MyBatis→JSP 전체 동작 확정.
- **Path B (호스트)**: brew openjdk@21 설치 → chmod +x mvnw → `./mvnw -P dev test` **6 tests 0 fail** → `package` WAR 30MB → `spring-boot:run` 홈 200(provided tomcat 동작).

검증 중 드러난 실제 블로커 3건(모두 해결):
1. **TLS 인터셉션(Cloudflare Gateway CA)** 으로 SNAPSHOT 의존 PKIX 실패 — 컨테이너/호스트 JDK truststore 둘 다. `curl` 200(시스템 키체인) ≠ JDK(자체 cacerts). → Docker 는 certs/*.crt 자동 주입, 호스트는 keytool import 로 해결.
2. **비실행 WAR** — pom 이 spring-boot-starter-parent 미사용이라 repackage goal 미바인딩 → `spring-boot:repackage` 명시로 해결.
3. **포트 5432 충돌**(기존 kord-postgres) → .env DB_PORT=5433 회피.

DDL 갭: recruit_posts 만 권위 DDL. 나머지 5테이블은 매퍼+POJO 역추출 비권위 복원본(타입 추론). schema.sql 에 명시.

src/, pom.xml 무수정. mvnw 는 실행권한 부여(mode change)만. 비밀값(.env/db.properties/certs/*.crt) gitignore 확인.

# Advisor Invocation Decision Log
- advisor: requirements-advisor
  decision: skip
  rationale: '요청이 망라적·확정적. 모호점은 사실(빌드 동작·DDL 복구)이며 실행으로만 해소.'
  checked_at: 2026-06-17T11:09:00+09:00
- advisor: research-advisor
  decision: skip
  rationale: '조사 대상이 전부 orchestrator 직접 실행/grep 으로 검증되는 execution-bound. 외부 자료 불요.'
  checked_at: 2026-06-17T11:09:00+09:00
- advisor: design-advisor
  decision: skip
  rationale: '인프라 설계(compose/Dockerfile/schema)가 검증 루프와 밀결합 — build→fail→fix 반복이 orchestrator 직접 수행에 적합. 옵션공간은 plan 게이트 AskUserQuestion 으로 사용자 확정.'
  checked_at: 2026-06-17T11:10:00+09:00
- advisor: implementation-advisor
  decision: skip
  rationale: '파일 영향맵 확정적(신규 인프라 파일 6개, src 무수정). 충돌 worker 불요. orchestrator 직접 작성 + 즉시 검증.'
  checked_at: 2026-06-17T11:10:00+09:00
- advisor: documentation-advisor
  decision: call
  rationale: '온보딩 문서는 docs 도메인 owner 책임 — 카테고리/index 링크/guidelines 준수 보장. 검증 증거 self-contained 브리프로 전달.'
  checked_at: 2026-06-17T11:40:00+09:00
- advisor: verification-advisor
  decision: call
  rationale: '코드/인프라 변경 존재 → AC 독립 검증 의무(skip 불가). 통합 스모크 재확인.'
  checked_at: 2026-06-17T11:40:00+09:00

# Invocations
- id: inv-001
  layer: orchestrator
  name: orchestrator
  parent_invocation_id: null
  input_digest: '로컬 셋업 분석/검증/문서화'
  output_digest: '정찰 + docs-first + DDL 증거 + plan 게이트 확정'
  artifacts: [.atp/work-session/20260617-110836/report.md]
  concerns: []
- id: inv-002
  layer: orchestrator
  name: orchestrator (infra build + dual verification)
  parent_invocation_id: inv-001
  input_digest: 'schema.sql + Docker infra 작성, A/B 실행 검증'
  output_digest: 'A/B 모두 홈 200 + DB 동작. 블로커 3건 해결.'
  artifacts:
    - db/schema.sql
    - docker-compose.yml
    - Dockerfile
    - .env.example
    - .dockerignore
    - certs/README.md
    - .atp/work-session/20260617-110836/artifacts/ (build/test/run 로그, home html)
  concerns: []
  model_choice:
    phase: validation-runtime
    dispatch_size: direct
    tier: large
    effort: medium
    resolved_model: inherit
    capped: false
    capped_from: null
    escalation_reason: '런타임·DB·인프라 회귀 판정 + 미지 블로커 root-cause 탐색'
    fallback_reason: null
    rationale: 'orchestrator 직접 수행(검증 루프 밀결합). 자기 모델(opus=large) 상속.'
- id: inv-003
  layer: advisor
  name: documentation-advisor
  parent_invocation_id: inv-001
  input_digest: '검증 증거 전량 + 7섹션 구조 브리프'
  output_digest: '(진행중)'
  artifacts: [docs/usage/local-setup.md, docs/usage/index.md, .atp/work-session/20260617-110836/documentation.md]
  concerns: []
  model_choice:
    phase: docs
    dispatch_size: s-batch
    tier: medium
    effort: low
    resolved_model: inherit
    capped: false
    capped_from: null
    escalation_reason: null
    fallback_reason: null
    rationale: '형식 위주 문서 작성. 증거는 브리프로 확정 제공 → medium 충분.'

# Decisions
- by: user
  at: 2026-06-17T11:12:00+09:00
  decision: 'DDL=전체 schema.sql 복원, Path B=Docker 후 Java 설치까지 진행, 인프라=루트 신규 생성'
  rationale: 'plan 게이트 AskUserQuestion 3문항 응답'
  related_invocations: [inv-001]
- by: orchestrator
  at: 2026-06-17T11:20:00+09:00
  decision: 'TLS 인터셉션 CA 를 빌드 truststore 에 주입(검증 유지) — TLS 무시(insecure) 대신'
  rationale: '보안 검증 끄지 않고 회사 프록시 환경 대응. 환경특화 CA 는 gitignore.'
  related_invocations: [inv-002]

# Conflicts

# Open Items
- db/schema.sql 의 5개 비권위 테이블 타입은 운영 DB pg_dump 대조 필요(미해결).
- spring-boot 3.5.14-SNAPSHOT 고정 결정 대기(analysis open_question #4).
- 미커밋 잔여(이번 작업 단위): .gitignore(M), mvnw(mode), .dockerignore/.env.example/Dockerfile/docker-compose.yml/db//certs/ (untracked), docs(작성중) → 종료 전 커밋 예정.
- 사용자 기존 변경(작업 무관, 보존): .serena/project.yml(M), .serena/memories/serena_tooling.md(??), .atp/work-session/20260617-094450/(??) → 커밋 범위 제외.

# Regression
- surfaced_at_stage: verification (docker build / host test)
  source_stage: implementation (Dockerfile run 명령 / 환경 가정)
  defect: 'SNAPSHOT PKIX 실패(TLS 인터셉션) + 비실행 WAR(repackage 미바인딩)'
  full_set_recheck: false
  downstream_rerun: [implementation(Dockerfile 수정), verification(재빌드/재실행)]
  resolved_at: 2026-06-17T11:31:00+09:00

# User Signals
user_signals:
  positive:
    - quote_or_paraphrase: '직접 java 설치까지 진행해 시간 더 써도 상관없[다]'
      about: 'Path B 완전 검증을 위한 추가 시간/설치 허용 — 철저한 실행검증 선호'
  negative: []

# Retrospective
Retrospective:
  signals:
    positive:
      - quote_or_paraphrase: '직접 java 설치까지 진행해 시간 더 써도 상관없다'
        about: 'plan 게이트 AskUserQuestion 응답 — Path B 를 .env.example/문서 추측이 아니라 실제 brew 설치 + mvnw test + spring-boot:run 까지 끝까지 실행검증하는 경로를 사용자가 명시 승인. 추가 시간 비용을 감수하더라도 "실행으로만 확정" 원칙을 사용자가 지지.'
      - quote_or_paraphrase: '(plan 게이트 3문항을 한 번에 확정) DDL=전체 schema.sql 복원 / Path B=Java 설치까지 / 인프라=루트 신규'
        about: 'orchestrator 가 비자명한 분기(부분 복원 vs 전체, Docker only vs 호스트까지, 루트 vs 하위디렉토리)를 추측하지 않고 단일 AskUserQuestion 으로 묶어 제시 → 재질의 없이 한 번에 수락. 분기 비용을 사용자에게 압축 전달한 판단이 검증됨.'
    negative: []
  what_went_well:
    - 'plan 게이트로 비자명한 3개 분기를 한 번에 확정받아 재작업 없이 직진 (positive 시그널). advisor 5개 중 4개 skip 결정의 rationale 이 "execution-bound — 외부조사/설계옵션 불요"로 명확했고 실제 검증으로 맞아떨어짐.'
    - '"실행으로만 확정" 원칙 관철: curl/HTTP 200, Tests 6/0, compose ps healthy, DB→MyBatis→JSP 삽입 라운드트립까지 추측 없이 산 증거로 기록. verification-advisor 가 AC 10건을 독립 재실행해 전 PASS.'
    - '미지 블로커 3건을 우회(insecure TLS)가 아닌 근본 해결(CA 를 truststore 에 주입해 검증 유지)로 처리. 보안 검증을 끄지 않으면서 회사 프록시 대응 — Decision 로그에 근거 남김.'
    - 'src/pom.xml 무수정 제약 준수(mvnw mode change 만), 비밀값(.env/db.properties/certs) gitignore 를 verification AC-4 에서 전수 확인. 사용자 기존 변경(.serena/*)을 커밋 범위에서 명시 제외해 사용자 변경 보호 원칙 지킴.'
    - 'DDL 갭을 "복원했다"로 뭉뚱그리지 않고 recruit_posts(권위) vs 5테이블(매퍼+POJO 역추출 비권위, 타입 추론)로 구분해 schema.sql 과 문서 §4·§7 에 명시. 신뢰 경계를 산출물에 박아 다운스트림 오신뢰 차단.'
  what_to_improve:
    - 'verification-strategies.md 가 placeholder 템플릿 상태 — 등록된 실행 전략 0개라 verification-advisor 가 orchestrator 전달 AC 를 직접 실행하는 방식으로 우회. 통합 검증 스크립트(make verify 류)와 전략 레지스트리가 비어 매 세션 AC 를 수기 전달해야 함 (구조적, observation).'
    - 'docs/usage/index.md 가 참조하는 setup-checklist.md / faq.md 가 dangling link (실제 파일 부재). documentation-advisor 가 concern 으로 보고했으나 범위 밖이라 미수정 — 인덱스 무결성 보강 필요.'
    - 'TLS 인터셉션 / repackage 미바인딩 / 포트충돌 3건이 implementation 단계 가정(Dockerfile run 명령·환경 전제)에서 비롯돼 verification 단계에서야 표면화. full_set_recheck=false 로 국소 회복했으나, "온라인 SNAPSHOT + 회사 프록시 + parent 미사용 pom" 환경 전제를 implementation 진입 전 체크리스트로 선점검했다면 회귀 비용 절감 가능.'
  memory_candidates:
    - name: jdk-cacerts-separate-from-system-keychain
      type: feedback
      description: 'curl 200 ≠ JDK 신뢰. 회사 TLS 인터셉션 프록시 환경에서 JDK 빌드(Maven SNAPSHOT 등) PKIX 실패는 시스템 키체인이 아닌 JDK 자체 cacerts 에 프록시 CA 를 별도 import 해야 해결된다.'
      body_draft: |
        회사 TLS 인터셉션 프록시(예: Cloudflare Gateway/Zero Trust)가 `repo.spring.io` 등의 인증서를 재서명하면, JDK 기반 빌드(Maven 의존성 수신, SNAPSHOT POM import)가 `PKIX path building failed: unable to find valid certification path to requested target` 로 실패한다. 핵심: **`curl` 이 200 을 반환해도 JDK 는 신뢰하지 않는다** — curl 은 시스템 키체인을, JDK 는 자체 `cacerts` truststore 를 쓰기 때문이다.

        **Why:** 세션 20260617-110836 (bibimbap 로컬셋업)에서 Docker/호스트 양쪽 JDK 빌드가 PKIX 로 실패. curl 은 통과해 한때 네트워크 정상으로 오판할 뻔함. 해결은 TLS 무시(insecure)가 아니라 CA 주입으로 검증을 유지.

        **How to apply:**
        - 증상이 PKIX / `unable to find valid certification path` 면 먼저 "JDK truststore 에 프록시 CA 가 없다"를 의심. curl 성공을 근거로 네트워크 정상이라 결론짓지 말 것.
        - 호스트: `keytool -importcert -trustcacerts -cacerts -storepass changeit -alias proxy -file <ca>.crt`.
        - Docker: 빌드 스테이지에서 `<ca>.crt` 를 이미지 truststore 에 주입.
        - CA 추출(macOS): `security find-certificate -a -c "<CA 이름>" -p <keychain> > ca.crt`.
        - 환경특화 CA(`certs/*.crt`)는 gitignore. insecure(TLS 검증 off)로 우회 금지.
        - 형제 사례(다른 런타임 같은 원인): loa 프로젝트 `feedback_node22_use_system_ca_for_live_api_tests` (Node 22 는 `NODE_OPTIONS=--use-system-ca`). 런타임마다 truststore 가 시스템 키체인과 분리돼 있다는 같은 교훈의 변종.
      rationale_for_saving: '회사 macOS 개발 환경 전반에 재발하는 환경 제약(여러 프로젝트에서 이미 변종 발생). 코드/커밋으로 유도 불가, 관찰로만 드러남. bibimbap 메모리에 미존재.'
      signal_source: observation
      docs_sync_target: /Users/wemadeplay/workspace/stz/bibimbap/docs/usage/local-setup.md  # 이미 §6 트러블슈팅에 반영됨 — MEMORY 는 환경 일반화 보존용
    - name: pom-without-starter-parent-needs-explicit-repackage
      type: feedback
      description: 'spring-boot-starter-parent 미사용(dependencyManagement import 만) pom 은 spring-boot:repackage 가 package 단계에 자동 바인딩되지 않는다. 명시 호출 안 하면 비실행 WAR(no main manifest attribute).'
      body_draft: |
        Spring Boot 프로젝트가 `spring-boot-starter-parent` 를 부모로 쓰지 않고 `spring-boot-dependencies` 를 dependencyManagement 로 import 만 하는 경우, 두 가지가 자동으로 동작하지 않는다:
        - (a) `application.properties` 의 `@app.profile@` 같은 리소스 필터링 — profile 미지정 시 `spring.profiles.active` 가 깨진다.
        - (b) `spring-boot:repackage` goal 이 `package` 단계에 자동 바인딩되지 않는다 → 명시 호출 없이는 비실행 WAR 가 나와 `no main manifest attribute` 로 기동 실패.

        **Why:** 세션 20260617-110836 에서 `mvnw package` 산출 WAR 가 실행되지 않아 블로커. parent 미사용이 원인. `./mvnw -P dev clean package spring-boot:repackage` 로 해결.

        **How to apply:**
        - pom 에 `<parent>spring-boot-starter-parent</parent>` 가 없고 import-only 라면, 빌드/실행 명령에 `-P dev`(또는 해당 profile) + `spring-boot:repackage` 를 명시.
        - "no main manifest attribute" / profile 미적용 증상 보면 parent 미사용 pom 을 의심.
      rationale_for_saving: 'bibimbap pom 의 영속적 구조 특성(parent 미사용)에서 비롯 — 빌드 명령을 잘못 쓰면 반복 재발. 빌드 레시피 자체는 문서화됐지만 "왜 이 명령이어야 하는가"의 진단 단서는 관찰 지식.'
      signal_source: observation
      docs_sync_target: /Users/wemadeplay/workspace/stz/bibimbap/docs/usage/local-setup.md  # §3 주의·§6 에 반영됨
    - name: restored-ddl-mark-non-authoritative-types
      type: feedback
      description: '권위 DDL 부재로 매퍼+POJO 역추출로 스키마를 복원할 때, 컬럼 유무/이름은 검증해도 타입·길이·제약은 추론값이므로 산출물(schema.sql/문서)에 비권위 경계를 명시하고 pg_dump 대조를 open item 으로 남긴다.'
      body_draft: |
        flyway/liquibase 가 없고 전체 DDL 도 없는 프로젝트에서 스키마 SQL 을 복원할 때, 매퍼 `@Insert`/`@Select` 컬럼과 data POJO Java 타입에서 역추출한 부분은 **비권위**다. 컬럼명·유무는 매퍼와 대조해 확정할 수 있어도, SQL 타입·길이·NULL/제약은 추론값이라 운영 DB 와 다를 수 있다.

        **Why:** 세션 20260617-110836 에서 6테이블 중 recruit_posts 만 권위 DDL. 나머지 5테이블은 역추출 복원. "복원 완료"로 뭉뚱그리면 다운스트림이 타입을 신뢰해 마이그레이션/기능 스모크에서 데이터 무결성 사고로 번질 수 있음.

        **How to apply:**
        - 복원 SQL 에 테이블별로 권위/비권위 출처 주석을 박는다.
        - 문서에 신뢰 경계(타입 추론값, pg_dump 대조 전 신뢰 금지)와 영향(기능 스모크 보류 사유)을 명시.
        - 운영 DB `pg_dump` 대조를 open item 으로 인계.
      rationale_for_saving: '갭 복원 작업의 재현성 있는 규율(출처 등급 명시) — 일회성이 아니라 권위 DDL 부재 상황에서 반복 적용. signal_source positive(분기 확정 시 사용자가 전체복원을 승인) + observation 결합.'
      signal_source: observation
      docs_sync_target: /Users/wemadeplay/workspace/stz/bibimbap/docs/usage/local-setup.md  # §4·§7 에 반영됨. 운영 DB 권위 DDL 확정 시 contracts/ 또는 ADR 검토.
  protocol_feedback:
    - 'verification-strategies.md 가 placeholder 템플릿이면 verification-advisor 가 매번 orchestrator 전달 AC 를 수기 실행하게 됨. 인프라/온보딩 셋업 검증을 1회성으로 끝내지 말고, 통과한 AC 묶음(compose ps healthy / curl 200 / mvnw test green / check-ignore 비밀값)을 재사용 가능한 전략으로 verification-strategies.md 에 즉시 등록하는 단계를 검증 PASS 직후 권고로 추가하면, "검증 자산이 휘발"되는 패턴을 막을 수 있음 (구조적).'
    - 'implementation 진입 전 "환경 전제 체크리스트"(예: 온라인 의존성 여부 / 회사 TLS 프록시 / 빌드툴 parent 사용 여부 / 포트 점유)를 advisor decision 게이트와 별도로 점검하는 경량 단계가 있으면, 이번처럼 verification 에서야 표면화되는 환경발 회귀 3건을 implementation 단계에서 선점할 수 있음.'
  applied_changes: []

# Session Close

## verified_by_me
- L1: compile(BUILD SUCCESS, Docker+호스트) / unit+regression — `./mvnw -P dev test` Tests run 6, Failures 0, Errors 0.
- L2: contract — skipped (외부 API 계약 변경 아님).
- L3: 수동 스모크 — compose 런타임 홈 200 + /recruit 200 + dev 6테이블 + 삽입→홈노출 라운드트립(A,B 양쪽).
- 로그 스캔: clean (앱 로그 SQLException/ERROR 0; JDK21 Mockito self-attach 경고는 테스트 결과 무관).
- 비밀값 비커밋: verification AC-4 전수 PASS (.env/db.properties/certs/*.crt 모두 gitignore).
- AC 독립 검증(verification-advisor): 5/5 PASS.

## needs_user_verification
- 실제 사용자 환경 기능 스모크(회원가입/로그인/게임 zip 업로드/모집글 작성)는 미수행 — db/schema.sql 5테이블이 비권위 타입이라 권장.
- 운영 DB pg_dump 와 db/schema.sql 대조(타입 확정).
- (선택) Docker 스택 현재 가동 중(db:5433, app:8080). 정리: `docker compose down` (볼륨까지 `-v`).

## graph_refresh
- partial-stale → docs scope 재생성 완료(`/graphify docs/`, 92 노드/122 엣지/10 커뮤니티). docs/graph/docs/ 본체(gitignore) + docs/graph/index.md 메타 갱신(docs 행 8c41b22). src scope 는 이번 세션 변경 0건 — PR#1 발 별건 pre-stale 는 범위 밖.

## project_gate
- skip: no-project-gate — verification-strategies.md 가 미작성 템플릿(등록 전략 0). 추가 런타임/배포 게이트 정의 없음. L1/L2/L3 로 갈음.

## applied_changes
- MEMORY: `.serena/memories/local-dev-setup-gotchas.md` 신규(retro 3 candidate 수용 — JDK cacerts/repackage/비권위 DDL). docs_sync_target(local-setup.md)은 이미 트러블슈팅에 반영됨.

## protocol_feedback (retro 권고 — 본 세션 미적용, 이월)
- verification-strategies.md 에 통과 AC 를 재사용 전략으로 등록하는 단계 권고(구조적). 본 세션은 프로젝트 자산 범위 밖이라 미적용.
- implementation 진입 전 "환경 전제 체크리스트"(온라인 의존/TLS 프록시/parent 사용/포트 점유) 권고.

## commit
- pending: 사용자 승인 대기(main 브랜치 — 커밋 시 브랜치 분리 권장). 작업 단위 파일만 커밋, 사용자 기존 변경(.serena/*, 20260617-094450) 제외.
