You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
운영 서비스(https://naelawnambul.today)가 어떤 구성으로 돌고, 코드가 어떻게 운영까지 가는지 한 문서로 정리한다.
세부 절차 · 명령은 각 상세 문서에 있다 — 이 문서는 지도이고, 바꿀 때는 상세 문서와 설정 파일을 먼저 고친다.
버전
날짜
내용
v1
2026-11-02
신설 (COMMON-71). 11/01 기준 아키텍처 그림을 저장소 설정(compose · nginx · workflows · .env.example)과 대조해 정리. Supabase 공용 DB 종료(COMMON-59) 반영. 서버 가동은 매일 09:00 ~ 18:00(주말 포함). 공유용 그림 docs/assets/architecture.png 추가
v2
2026-11-02
카카오 첫 가입 대기(Redis 토큰 DB 10분)와 카카오 가입 동의(M-12)의 요청 제한 반영 (BE-145)
v3
2026-11-03
사건 사진 전달 방식 정정 (COMMON-74) — Presigned URL이 아니라 case-photos/*만 버킷 정책으로 공개 읽기. 구현에 Presigned URL 발급이 없어 공개 화면 사진이 403이었다
상세 문서
알고 싶은 것
문서
서버 실행 · 배포 · HTTPS · 요청 제한 · Redis · 백업 · RDS · S3 · Swap · 파이프라인 · 모니터링 에이전트
발표 · 포트폴리오용 상세 그림은 docs/assets/architecture.png에 있다(2026-11 기준). 아래 Mermaid는 저장소에서 바로 고치는 간단한 구성도다. 구성이 바뀌면 두 그림을 함께 고친다.
그림 갱신 대기 (COMMON-74): PNG의 "Presigned URL" 표기 4곳(상단 점선 · S3 상자 · 외부 노출 경로 · 주요 흐름 6)은 옛 내용이다. 실제로는 case-photos/* 공개 읽기로 브라우저가 서명 없는 주소를 받는다. PNG를 다시 만들기 전까지는 아래 Mermaid와 본문이 기준이다.
flowchart LR
user["사용자 브라우저<br/>익명 쿠키 · 카카오 · 아이디 로그인"]
admin["관리자 브라우저<br/>세션 · CSRF"]
subgraph aws["AWS 서울 리전 (ap-northeast-2)"]
subgraph ec2["EC2 t3.small · Docker Compose (이미지는 GHCR main)"]
web["web · Nginx 1.28<br/>TLS 종료 · 요청 제한<br/>/ → SPA · /api → backend"]
backend["backend<br/>Spring Boot 4.1.1 · Java 17<br/>:8080 · Actuator :8081(내부)"]
redis["redis 7.4<br/>DB1 토큰 · OAuth state · 카카오 가입 대기<br/>(DB0 캐시는 아직 미사용)"]
pipeline["pipeline :8000<br/>AI 판결 생성 · 사건 등록<br/>(팀 합의 후 켬, COMMON-52)"]
agent["Alloy + node-exporter<br/>(모니터링 에이전트)"]
pg[("postgres 컨테이너<br/>외부 DB 모드라 기본 실행에서 제외")]
end
rds[("RDS PostgreSQL 17<br/>sslmode=require · 앱 계정")]
s3[("S3<br/>사건 사진")]
end
ext["외부 API<br/>Gemini · Anthropic · OpenAI · 카카오"]
cloud["Grafana Cloud<br/>지표 · 로그 · 경보 → Slack"]
ghcr["GHCR<br/>web · backend · pipeline 이미지"]
user -- "HTTPS 443" --> web
admin -- "HTTPS 443" --> web
user -. "사진: 공개 읽기 (case-photos/*)" .-> s3
web --> backend
backend --> redis
backend -- "JDBC 5432 TLS" --> rds
backend -- "업로드" --> s3
backend -- "사건 등록 (내부망)" --> pipeline
backend --> ext
pipeline --> ext
agent -- "push" --> cloud
ec2 -. "cd-agent: 2분마다 main 확인" .-> ghcr
Loading
점선 박스(postgres)는 정의 · 볼륨만 남긴 되돌리기용이다. pipeline은 오버레이(PIPELINE_SERVICE=1)를 켠 서버에서만 뜬다.
운영 서버
항목
내용
상세
서버
EC2 t3.small(2GB) 한 대, 탄력적 IP. 스테이징 없음 — main이 곧 운영
deploy/README.md
운영 시간
매일 09:00 ~ 18:00에만 켜져 있다(처음엔 평일만이었고, 주말 가동으로 바뀌었다). 그 밖 시간에는 EC2 서비스와 서버 cron 백업(backup-db.sh)이 멈추고, 경보는 음소거 운영시간외로 울리지 않는다. RDS 자동 백업은 운영 시간과 무관하게 매일 1회 따로 돈다. 저녁에 서버를 켜고 작업하면 장애 알림도 오지 않는다.
deploy/README.md "운영 DB 백업" · monitoring/README.md "알림 경로 · 음소거"
관리자가 올린 사건 사진(DB에 주소가 저장된 것)은 브라우저가 S3에서 서명 없는 주소로 직접 받는다(case-photos/* 공개 읽기, CSP img-src에 S3 주소 허용). 저장된 주소가 없는 사진은 프론트 정적 파일 규칙 주소(/images/cases/case-{id}-*.webp, BE-141)를 쓰고, 그 파일도 없으면 화면이 공용 컷으로 바꾼다.
외부 서비스
서비스
누가
용도
카카오 OAuth2
backend
소셜 로그인(BE-62). KAKAO_CLIENT_ID가 없으면 경로가 꺼진다
Google Gemini
backend
RAG 유사 판례 검색 임베딩 · 신문 지면 생성(BE-92) · 사진 프롬프트 추천(BE-89). 키가 없으면 그 기능만 꺼진다
운영 확인 필요: 운영 .env의 PIPELINE_MODELS · PIPELINE_EXTRACT_MODEL 실제 값, 그리고 pipeline · postgres 컨테이너가 지금 떠 있는지(위 그림은 저장소 설정 기준이다).
배포 흐름 (CI/CD)
PR → develop backend CI · frontend CI · deploy images(build: 이미지 3개 빌드 → 운영 구성으로 스모크 테스트) · CodeRabbit · 팀 리뷰
develop 머지 deploy images publish → GHCR develop 태그 (운영 배포 없음)
develop → main deploy images publish → GHCR main 태그
→ 서버 cd-agent(2분마다)가 새 main 이미지를 보고 저장소 사본을 그 커밋으로 맞춘 뒤 deploy.sh
→ backend 교체 → healthy 확인 → web 교체 → smoke-test.sh → 실패하면 직전 이미지로 되돌림
→ Actions verify-deploy가 운영 /version.json = 이 커밋인지 확인 → 운영 주소로 스모크 테스트
Actions는 서버에 들어가지 않는다(SSH · AWS 권한 없음). 서버가 밖으로 나가 GHCR을 확인한다(BE-60).
마이그레이션은 backend가 뜰 때 Flyway가 적용한다. 되돌림은 이미지만 되돌리고 스키마는 되돌리지 않으므로, 마이그레이션은 이전 앱과 호환되게(추가만) 쓴다(BE-60).