bibimbap/docs/analysis/2026-09-22-release-readines...

74 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 2026-09-22 출시 준비 상태 검증
**판정: 현재 산출물 그대로 라이브 출시 보류(NO-GO).** 기본 동작과 빌드는 통과했으나 운영 설정 패키징 결함이 재현됐고, 신규 DB 초기화·운영 환경 검증이 남아 있다. 검증 대상은 `feat/v2`의 `184839434c94d500cdf6e74ae77b4b4c658dcc4c`이다. 코드 수정·운영 배포·원격 push는 수행하지 않았다.
ATP Tier B 순차 self-check로 수행했다. 독립 advisor 검토 또는 전체 보안 감사 결과가 아니다. [세션과 증거](../../.atp/work-session/20260922-114058/report.md).
## 실행 결과
| 검증 | 결과 | 실제 검증 범위 |
| --- | --- | --- |
| 전체 테스트 + 실행형 live WAR | PASS | JDK 21 컨테이너의 독립 HEAD 복사본에서 `mvn -o -B -P live test package spring-boot:repackage`; 362 tests, failure/error/skip 0 |
| live WAR 기동 | PASS | 독립 PostgreSQL 16 + `db/schema.sql`, live 프로필, DB search_path는 테스트용 dev; 운영 DB 검증 아님 |
| 공개 화면 브라우저 | PASS | 개발 인스턴스의 `/`, `/posts`, `/recruit`, `/jams`, `/login`, `/signup`, `/terms`, `/operation-policy` × 폭 1440/390 = 16회. 응답 200, JS 예외·실패 리소스·가로 넘침 0 |
| HTTP 기능 흐름 | PASS | 독립 live WAR에서 회원가입/로그인/로그아웃, 세션 ID 교체, 프로필, 모집글 생성·상세의 저장한 제목 출력 |
| 인증·CSRF 일부 계약 | PASS | 회원가입/로그인/모집글의 토큰 없는 POST 403, 토큰 있는 정상 요청 200, 일반 계정 `/posts/new` 403, 로그아웃 후 프로필 접근 리다이렉트 |
| DB 확인 | 부분 PASS | 기존 dev의 좋아요 UNIQUE 제약·카테고리 5종 확인. 신규 DB 카테고리는 아래 실패 |
| 의존성 스캔 | 제한적 PASS | `mvn -B dependency-check:check`: 50개(40 unique), 탐지 취약점 0. 캐시 갱신 꺼짐, 최신성 미검증, OSS Index 인증 없어 제외, provided scope 제외 |
| 실제 운영 배포 게이트 | 미수행 | 운영 URL·접근 환경·배포 절차·실제 Unity 빌드가 지정되지 않음 |
호스트 Java 미설치로 `./mvnw -o test`는 실행하지 못해 기존 Maven/JDK 컨테이너의 별도 디렉터리에서 실행했다. 개발 인스턴스의 컴파일 디렉터리는 변경하지 않았다. 의존성 플러그인은 Maven offline 모드를 거부하여 일반 실행으로 재검증했다. 위 테스트는 실 DB 매퍼 전체·전체 권한 조합·부하·장애복구를 보장하지 않는다.
## 수정 또는 배포 전 해소가 필요한 항목
### R1 — P1: live 설정 파일이 WAR에서 제외됨
- 근거: `pom.xml:278`에서 `application-*.properties`를 제외한다. dev에도 `pom.xml:241`의 같은 제외 규칙이 있다.
- `src/main/resources/application-live.properties:3`의 `server.servlet.session.cookie.secure=true`가 산출물에 포함되지 않는다.
- 실제 live WAR에는 `WEB-INF/classes/application.properties`만 있고 `application-live.properties`가 없다. 기본 파일의 active profile은 `live`임을 확인했다.
- 독립 WAR 런타임에서 익명 세션과 로그인 후 모두 `JSESSIONID; Path=/; HttpOnly; SameSite=Lax`이며 `Secure`가 없었다. HTTP 시험이므로 운영 TLS/프록시의 쿠키 정책을 추정하지 않는다. 확인된 결함은 명시한 Secure 강제 설정이 패키징에서 사라진다는 점이다.
- 조치: 프로필 설정 리소스를 포함하도록 빌드를 수정하고, 실제 배포 산출물과 운영 HTTPS 응답의 쿠키 속성을 함께 검증한다. WAR 엔트리/실행 프로필/쿠키 속성 회귀 검증이 필요하다.
### R2 — P1: 배포 이미지 경로가 dev 프로필로 고정됨
- 근거: `Dockerfile:30`은 `mvn -B -P dev ...`로 빌드한다. `docker-compose.yml`에는 live 프로필 강제 설정이 없다.
- 문서는 base compose를 배포 이미지 경로로 안내하지만, 현재 그 경로는 기본적으로 dev 프로필 산출물이다. 개발용 compose 자체는 결함이 아니며, 이를 그대로 라이브 배포 경로로 쓰는 것이 문제다.
- 조치: 운영 빌드/실행 프로필과 DB search_path를 명시한 별도 배포 구성을 확정하고, 그 실제 이미지로 재검증한다. 이번 live WAR 직접 실행은 Dockerfile 이미지 검증을 대체하지 않는다.
### R3 — P1: 새 DB 초기화에 기본 포스트 카테고리 시드가 빠짐
- 근거: `docker-compose.yml:22`는 `db/schema.sql`만 초기 적용한다. `db/apply-local-ddl.sh:46`의 기본 대상은 `docs/*-ddl.sql`이므로 `db/migrations/20260724-post-categories-seed.sql`이 포함되지 않는다.
- 실측: 기존 dev 카테고리는 `notice/devlog/showcase/resources/industry` 5종, 새 PostgreSQL에 schema.sql만 적용하면 0종이다. 새 환경에서는 카테고리 탭이 기존 결과물과 다르게 나온다.
- 조치: 신규 설치와 기존 DB 업그레이드 양쪽의 migration 목록·실행 순서·적용 확인 절차에 이 시드를 포함한다. 좋아요 UNIQUE도 운영 DB에서 별도 확인한다. 로컬 적용 사실을 운영 적용 증거로 사용하지 않는다.
### R4 — P2: 잘못된 입력/없는 정적 리소스를 500으로 처리함
- 근거: `src/main/java/com/pandoli365/bibimbap/controller/api/ApiExceptionControllerAdvice.java:38`의 전역 `Exception` 핸들러가 기본 예외를 500으로 변환한다.
- 독립 live WAR 재현: `/posts?categoryId=abc`, `/posts?categoryId=9223372036854775808`, `/css/readiness-missing.css`가 모두 500. 앞의 두 요청은 입력 오류, 마지막 요청은 리소스 부재다.
- 조치: 입력 변환 오류는 400, 없는 리소스는 404로 보존하도록 구체적인 예외 처리를 적용하고 회귀 테스트를 추가한다. 정상 브라우저 16회에서 실제 참조 리소스 실패는 없었다.
### R5 — P2: 모집글 작성의 CSRF 폴백 미완료
- 근거: `src/main/webapp/WEB-INF/views/recruit-form.jsp:403` 이후 JS helper 미존재 분기는 CSRF 헤더 없이 전송하며 hidden `_csrf`도 없다.
- 서버는 `RecruitController.java:65` 이후 검증으로 토큰 없는 요청을 403 처리한다. **CSRF 우회가 아니라 helper/JS 장애 시 정상 작성도 거부되는 폴백 가용성 문제**다. 정상 helper 경로의 모집글 저장·조회는 이번에 통과했다.
- 조치: hidden 토큰과 fetch 폴백을 보완하고 정상/폴백/토큰 누락의 동작을 각각 확인한다.
## 라이브 승인에 필요한 추가 증거
1. R1~R3 해소 후 **실제 배포 이미지**를 staging에서 실행해 프로필·운영 HTTPS 쿠키·DB migrations를 확인한다.
2. 실제 Unity WebGL 빌드 업로드 → 실행 → 교체 → 소유권 거부, 좋아요·리뷰·배지, 잼 참가·심사·투표·시상, 운영자 포스팅의 전체 시나리오를 검증한다. 이번 HTTP 검증은 이 흐름들을 포함하지 않는다.
3. [배포 후 체크리스트](../maintenance/post-deploy-verification-checklist.md)의 실 HTTPS 외부 fetch·피드 폴링·자산 경로·DNS TTL을 실제 환경에서 완료한다.
4. 의존성 DB를 갱신한 스캔 결과와 제외된 런타임 의존성 범위를 확인한다. 이번 0건 결과를 최신 CVE 안전 판정으로 쓰지 않는다.
5. DB/업로드 백업의 복구, 배포 rollback, 오류·디스크·업로드 제한 모니터링, 예상 트래픽의 부하 검증 결과를 확보한다. 저장소만으로 운영 준비 완료를 판정할 수 없다.
R4/R5는 함께 보완하는 것이 좋다. 우선순위는 운영 프로필과 설정 패키징 → DB 초기화/업그레이드 재현 → 핵심 사용자 E2E 및 운영 증거다. 현재는 staging 검증을 진행할 수 있는 상태이며 라이브 출시 승인 상태는 아니다.
## 증거와 한계
- [빌드 로그](../../.atp/work-session/20260922-114058/artifacts/build.log): 컴파일 WARNING 200줄(중복 포함, 주로 MockBean deprecation), ERROR 0. 테스트 실패 없음.
- [브라우저 결과](../../.atp/work-session/20260922-114058/artifacts/browser.json), [모바일 홈](../../.atp/work-session/20260922-114058/artifacts/home-390.png), [포스트 화면](../../.atp/work-session/20260922-114058/artifacts/posts-1440.png).
- [live WAR HTTP](../../.atp/work-session/20260922-114058/artifacts/live-http.json), [인증·작성 흐름](../../.atp/work-session/20260922-114058/artifacts/flow.json), [경계 입력](../../.atp/work-session/20260922-114058/artifacts/edge.json).
- `edge.json`의 없는 post/recruit/jam 항목 200은 목록 리다이렉트를 따라간 최종 응답이다. 해당 컨트롤러의 의도한 리다이렉트이며 새 결함으로 판정하지 않았다.
- [의존성 스캔 로그](../../.atp/work-session/20260922-114058/artifacts/dependencies.log), [검증 WAR 해시](../../.atp/work-session/20260922-114058/artifacts/war.sha256).
- 기존 graph는 7월 소스 기준이며 JSP가 누락되는 한계가 있다. 탐색 보조로만 사용하고 모든 발견은 현재 소스와 실행 결과로 대조했다.