웹툰 작가를 위한 포트폴리오 서비스 라이트의 백엔드를 2023년 11월부터 단독으로 설계·개발·운영하며 마주친 문제들을 정리한 문서입니다.
원본 저장소(pack-in/laiteu-be)는 운영 중인 서비스라 비공개입니다. 이 저장소는 그중
문제 → 원인 → 해결 → 결과가 수치로 남은 사례만 골라 공개한 기록입니다.
코드가 아니라 판단 근거를 남기는 것이 목적입니다. 각 문서는 "무엇을 고쳤다"가 아니라 "무엇을 측정했고, 왜 그 원인이라고 판단했으며, 개선을 어떻게 검증했는가" 순서로 씁니다.
| 항목 | 내용 |
|---|---|
| 기간 | 2023.11 ~ 현재 |
| 역할 | 백엔드 단독 담당 (API · 인증/인가 · 이미지 처리 · 배포 · 로그 모니터링) |
| 규모 | 일평균 사용자 약 1,000명, peak TPS 10, 도메인 모듈 18개 |
| 커밋 / PR | 914 / 129 (100% 단독 작성) |
기술 스택 Java 17 · Spring Boot 3.0.9 · Spring Security · Spring Data MongoDB · Redis · MapStruct · JJWT · Docker · Nginx · AWS EC2(Graviton/ARM64) · Cloudflare R2 · Grafana Loki · k6
flowchart LR
C[클라이언트] --> N[Nginx<br/>리버스 프록시]
N -->|Blue :8080| B[Spring Boot<br/>Blue]
N -->|Green :8081| G[Spring Boot<br/>Green]
B --> M[(MongoDB)]
G --> M
B --> R[(Redis)]
G --> R
B --> S[Cloudflare R2<br/>썸네일 CDN]
B -.로그.-> L[Grafana Loki]
G -.로그.-> L
GA[GitHub Actions] -->|ARM64 이미지 빌드<br/>헬스체크 후 전환| N
단일 EC2 인스턴스에서 Blue/Green 두 컨테이너를 띄우고 Nginx가 트래픽을 전환합니다. 서버가 한 대뿐이라 롤링 업데이트 대신 포트 전환 방식을 택했습니다 — 자세한 배경은 03. 무중단 배포에 있습니다.
| # | 문제 | 결과 |
|---|---|---|
| 01 | 북마크 폴더 조회 API가 7초 걸린다 | 7,031ms → 138ms (3단계 개선, covered query 달성) |
| 02 | 커뮤니티 피드 p95가 7초, 인메모리 정렬 발생 | 인덱스 스캔 문서 1,777건 → 30건 (98% 감소) |
| 03 | 배포할 때마다 20~25초 다운타임 (월 최대 8분) | 다운타임 0초, 헬스체크 실패 시 자동 롤백 |
| 04 | 동시 로그인 요청으로 계정이 중복 생성된다 | 추가 인프라 없이 JVM 락으로 직렬화, 중복 0건 |
- 감이 아니라 계측으로 판단한다. 모든 개선은
StopWatch, MongoDBexplain(), k6 중 하나 이상의 측정값을 근거로 합니다. "느린 것 같다"로 시작한 작업은 문서에 넣지 않았습니다. - 개선 전 수치와 개선 후 수치를 같은 조건에서 잰다. 데이터 건수, 인스턴스 타입, 측정 도구를 각 문서에 명시했습니다.
- 실패하거나 되돌린 시도도 남긴다. 한 번에 맞춘 것처럼 쓰지 않았습니다.