사내망(또는 VPN)이 없으면 진행 불가. 개발 DB 192.168.252.229:3306 ·
개발 EAI 192.168.252.216:8951 에 도달해야 합니다. 안 붙으면 로그인이
ReadTimeout 으로 죽고 모든 장표가 빈 페이지로 나옵니다.
nc -z -w2 192.168.252.229 3306 && nc -z -w2 192.168.252.216 8951브랜치 체크아웃
FE·BE 둘 다 feat/pdf-output 에서 진행합니다.
aplus-bojangplus-nextjs-frontend
cd aplus-bojangplus-nextjs-frontend
git checkout feat/pdf-output
pnpm install # 브랜치 전환 시 필수 — ag-grid-enterprise 등 누락 방지
rm -rf .next # 다른 브랜치의 스테일 .next 정리npm·yarn 금지. preinstall 가드가 설치를 중단합니다.
React 19 ↔ next-auth peer 충돌로 npm 은 애초에 설치가 안 됩니다.
aplus-bojangplus-python-backend
cd ../aplus-bojangplus-python-backend
git checkout feat/pdf-output
uv venv && source .venv/bin/activate # .venv 이미 있으면 source 만
uv pip install -e ".[dev]"로컬 서버 기동
터미널 2개를 씁니다. BE 를 먼저 띄우세요.
BE — 포트 8000
cd aplus-bojangplus-python-backend
APLUS_ENV=local .venv/bin/uvicorn app.main:app --reload --port 8000Application startup complete. Swagger 는
http://localhost:8000/docsFE — 포트 3000 (고정)
cd aplus-bojangplus-nextjs-frontend
NEXTAUTH_URL=http://localhost:3000/web-user/api/auth pnpm dev --port 3000Ready in ... · 접속 http://localhost:3000/web-user/login포트 3000 을 꼭 지켜주세요. BE .env.local 의
APLUS_CORS_ORIGINS=http://localhost:3000 이라 3434 등으로 띄우면
클라이언트 조회가 CORS 로 막힙니다. FE .env.local(팀 공용, 3434)은
수정하지 말고 위처럼 환경변수로만 덮으면 됩니다.
FE .env.local 이 NEXT_PUBLIC_MOCK=0 ·
API_BASE=http://localhost:8000 인지 확인하세요. mock↔live 전환은 HMR 로
반영되지 않으니 값을 바꿨으면 pnpm dev 를 완전히 재시작합니다.
기동 확인 (선택)
curl -s -o /dev/null -w "BE:%{http_code}\n" http://localhost:8000/docs
curl -s -o /dev/null -w "FE:%{http_code}\n" http://localhost:3000/web-user/login둘 다 200 이면 진행합니다.
http://localhost:3000/ 가 404 인 건 정상 — basePath 가 /web-user 입니다.
수동 E2E 6단계
계정 80032273 / __dev__ · 검증 고객 2602089632(이천구, 39페이지)
로그인
http://localhost:3000/web-user/login →
ID 80032273 · PW __dev__
/web-user/main 리다이렉트 + BE 터미널에
POST /auth/dev-login ... 200결과 출력 진입
http://localhost:3000/web-user/analysis/2602089632/report-output13/39 · 페이저 1 / 39첫 진입 12~13초는 정상입니다. 네트워크 탭에서 proposal 응답 헤더
X-Manifest-Cache: miss 를 확인하세요. 같은 고객으로 재진입하면
hit 이고 2.2초로 떨어집니다.
전후비교 5행이 번호 — · “출력 불가” 로 뜨는 것도 정상입니다
(이 고객은 전=후).
썸네일 클릭 → 우측 뷰어
좌측 목록에서 썸네일 아이콘을 클릭합니다.
1 / 2 페이지 배지로 구분페이지 선택 → “선택 완료”
그래프 1장을 체크해 카운터가 13 → 14 로 오르는지 본 뒤
선택 완료 를 누릅니다.
7→N 전환은 없어졌습니다)300px 단위로 천천히 스크롤하세요. 크게 점프하면
IntersectionObserver(rootMargin 300px)가 스쳐 간 카드를 그리지 않아
빈 카드로 오판하게 됩니다 — 앱 버그가 아닙니다.
다운로드
보장분석리포트_2602089632.pdf 저장 · 페이지 수가 카운터와 동일
(약 4.87MB)콘솔 확인
/web-user/api/v2/rpa/status404 는 이 화면과 무관한 기존 잡음입니다.- dev 에서 PDF 가 2회 요청되는 건 React StrictMode 때문이고,
AbortController가 첫 요청을 실제로 끊습니다 (운영 빌드는 1회).
판정 기준
여기가 가장 자주 어긋나는 부분입니다.
바이트로 판정하지 않습니다. 표시본 캐시가 프로세스 로컬이라, BE 를 재기동하면
크기는 같아도(5,059,069 bytes) 바이트가 달라지고 renderId 도 바뀝니다.
배포 형태에 따라 의미가 달라지는 값은 회귀 판정에 쓸 수 없습니다.
| 판정 항목 | 보는 법 | 기대 |
|---|---|---|
| 페이지 수 | manifest totalPages vs pdf.js numPages (usePdfDocument) | 39 / 39 |
| 장표 매핑 | page ↔ chk 키가 밀리지 않았는지 | 일치 |
| 텍스트 멀티셋 | 미리보기 vs 다운로드 토큰 비교 | 차이 0 |
renderId 대조 | — | 판정에 쓰지 않음 |
| 바이트 / sha256 | — | 판정에 쓰지 않음 |
실질 가드는 totalPages vs numPages 입니다 —
우리가 실제로 두려워하는 실패(page↔장표 매핑이 밀림)를 직접 검출하기 때문입니다.
전후비교까지 볼 경우
▼감소 · 무변동 · ▲증가 델타 확인
02 의 고객(이천구)은 countConsulting=0 이라 전=후 degenerate 입니다.
델타를 보려면 계정부터 바꿔야 합니다.
| 쓸 곳 | 로그인 TFA | 고객 insuredSeq | 근거 |
|---|---|---|---|
| 결과 출력 E2E (기본) | 80032273 | 2602089632 이천구 | 39페이지, chk11 정상 |
| 전후비교 델타 | 80002888 | 1809216008 이길자 | 계약수 6→4, 보장률 17.78→28.48, 월납 +50,500 |
| 전후비교 차선 | 80002888 | 2308223840 서수현 | 월납 +27,251, 보장률 34.46→38.14 |
__dev__ 는 fixture 에 있는 설계사만 열립니다.
실측: 80032273 · 80002888 · 99999052 = 200 /
80009991 · 99999032 = 404.
fixture 밖 계정의 고객을 보려면 브라우저 대신 05 의 스크립트를 씁니다.
전후비교 게이트가 열린 (TFA, 고객) 조합은 개발계에 11건뿐입니다.
로그인 없이 PDF 만 뽑기
브라우저·로그인 없이 BE 렌더 서비스를 직접 호출합니다. 가장 빠른 경로.
cd aplus-bojangplus-python-backend
APLUS_ENV=local APLUS_READONLY=1 .venv/bin/python scripts/render_one.py "이천구" 80032273 chk03,chk04,chk07
# → scripts/out/보장분석Report_2602089632.pdf- 1번 인자가 이름이면
WORLD_CUST_ID를 자동 조회하고, 숫자면insuredSeq를 직접 지정합니다(동명이인 회피). APLUS_READONLY=1그대로 안전합니다 — SELECT-only, DB 쓰기 없음.
insuredSeq 는 tb_trd_cust.CUST_SEQ 가 아니라
WORLD_CUST_ID 입니다. 잘못 넘기면 조회가 0행이 되어 장표가 전부
빈 페이지로 렌더됩니다. 개발계에는 이 값이 NULL·빈값인 고객이 2,774명 있습니다.
자주 걸리는 것
증상 → 원인·해결
| 증상 | 원인 · 해결 |
|---|---|
http://localhost:3000/ 가 404 | basePath /web-user 필요 — /web-user/login 으로 접속 |
__dev__ 로그인 404 | BE /auth/dev-login 미복원 — BE 패치 적용 필요 |
__dev__ 로그인 401 | 개발 EAI 가 해당 컨설턴트 미인지(get_user_list 빈 결과) — fixture 계정 사용 |
BE 가 ReadTimeout / 멈춤 | APLUS_EAI_DEST 누락 — 개발 EAI 는 EAI-Dest 헤더 필수 |
JWT_SESSION_ERROR: decryption failed | NEXTAUTH_SECRET 미설정·변동 + 스테일 쿠키 — 고정 시크릿 설정 후 사이트 데이터 클리어 |
| type-check·빌드에 ag-grid-enterprise 오류 | 다른 브랜치의 node_modules·.next 잔존 — pnpm install + rm -rf .next |
NEXT_PUBLIC_MOCK 바꿨는데 반영 안 됨 | dev 서버 완전 재시작 (HMR 미반영) |
| 첫 진입 스켈레톤이 10초 이상 | 정상 — BE manifest 캐시 miss(실측 12~13s). 헤더 X-Manifest-Cache 로 확인 |
| 미리보기 카드 일부가 빈 플레이스홀더 | 스크롤을 크게 점프한 경우 — 300px 단위로 천천히 스크롤하면 전부 렌더 |
| 다운로드가 미리보기와 바이트가 다름 | 그 사이 BE 재기동·다른 워커. 애초에 바이트로 판정하지 않음 (03 참조) |
| chk11 에 다른 계약자 데이터 | 운영 DB 한정 BE 데이터경로 블로커. 개발계에서는 재현되지 않습니다. FE 버그 아님 |
| Live 미리보기 빈 화면 / 404 | BE DB 에 해당 고객 데이터 없음, 또는 API_BASE 오설정 |