LEVEL 2실무 백엔드 · 교재 안내서 · 공통 랩 + 전 11단계 공개

실무 백엔드
세우고, 깨뜨리고, 되살린다

금융 서비스(모의 증권사 MiniTrade)를 이름·인증서·프록시·워커·브로커·배포·관측·보안이 있는 실제 운영 환경에 올리고, 일부러 깨뜨리고, 복구한 기록을 남기는 과정입니다. Level 1이 “요청 한 번이 DB에 무엇을 시키는가”를 숫자로 설명하게 했다면, Level 2는 DB 바깥의 계층을 같은 방식으로 채우고 둘을 하나의 서비스에서 잇습니다.

10
단계
도메인부터 팀 리드까지
3
종합 산출물
측정치로 완성 판정
1
공통 서비스
MiniTrade(모의 증권사)
3건+
단계마다 고의로
깨뜨리고 복구
요청 경로 실패 지도위 = 사용자 · 아래 = DB
  1. WEB 브라우저 · SPACORS·쿠키·CSRF, 재연결 뒤 조용히 틀어진 호가창 25
  2. DNS 이름 해석 · 리졸버 캐시TTL 86400인 채 IP 교체, 부정 캐싱 1
  3. EDGE TLS · Nginxreload 안 한 옛 인증서, 중간 인증서 누락, 무한 리다이렉트, 502 13
  4. WS 시세 게이트웨이재연결 폭주, 느린 소비자 OOM 5
  5. APP 앱 서버 · Django + gunicorn워커 소진, 이벤트 루프 블로킹, IDOR·SSRF 39
  6. MQ 브로커 · 워커커밋 전 발행, 중복 반영, 마감 배치 이중 반영 6
  7. DB 풀 · PostgreSQL 18데드락, 잠금 대기열, 이중 체결, 낡은 통계 4
78910 배포(되돌리는 속도) · 관측(질문 순서) · 보안(신뢰 경계) · 아키텍처(만들지 않을 것)는 모든 층을 가로지른다
그 층의 실패를 다루는 단계 — 누르면 단계 카드로 갑니다.
01 · Overview

통과는 읽은 분량이 아니라, 깨뜨리고 복구한 기록으로

로드맵이 8년차 백엔드 팀장에게 기대하는 능력은 프레임워크 API 목록이 아니라 세 가지입니다. 이 교재의 모든 단계는 이 셋을 내 손으로 재현한 기록을 남기는 것으로 끝납니다.

능력 1

경로를 계층별로 끊어 설명한다

요청이 브라우저에서 출발해 DB의 한 행에 닿았다가 돌아오는 경로를 계층별로 끊어 설명하고, 각 계층의 실패 모드를 안다.

능력 2

바꿔도 되는 것과 안 되는 것을 가른다

무엇이 구버전·신버전과 동시에 살아 있어도 되는지 구분해 무중단 배포 절차를 설계한다.

능력 3

가설을 좁히는 순서를 갖는다

장애 상황에서 원인 가설을 좁히는 순서가 있고, 그 순서가 로그·메트릭·트레이스로 뒷받침된다.

통과 판정의 세 원칙

Level 1의 “실측만”에 더하는 것

원칙 1

한 번은 고의로 깨뜨리고 복구한다

정상 동작만 확인한 것은 통과가 아니다. 단계마다 사고_재현.md에 최소 세 건 — 재현 → 사용자가 보는 증상 → 진단 명령 → 완화·복구 → 재발 방지.

원칙 2

기본값도 근거를 댄다

기본값을 썼더라도 그 값이 왜 안전한지 설계_기록.md에 적는다. 예: proxy_read_timeout이 왜 gunicorn timeout보다 길어야 하는가.

원칙 3

남는 산출물

저장소 · 실행 가능한 구성(compose) · 한 장짜리 설계 기록으로 남긴다. 화면 캡처나 기억은 산출물이 아니다.

프레임워크 수준의 답 vs 실무 수준의 답

원전 로드맵의 표 — 이 교재가 겨냥하는 차이

질문프레임워크 수준실무 수준
배포는 어떻게?git push하면 플랫폼이 빌드해서 올려 준다이미지 태그를 커밋 SHA로 고정하고, 스키마 마이그레이션을 배포와 분리된 선행 단계로 돌리며, readiness를 통과한 인스턴스만 로드밸런서에 편입하고, 실패 시 이전 태그로 되돌린다
CORS 에러가 난다CORS_ALLOW_ALL_ORIGINS = Truecredentials 요청에선 *를 못 쓰니 허용 목록에 있는 오리진만 그대로 반사하고, Vary: Origin으로 CDN이 다른 오리진의 응답을 재사용하지 않게 한다
왜 도메인을 사나주소가 보기 좋으니까인스턴스 교체·스케일아웃마다 IP가 바뀌고, TLS 인증서는 이름에 발급되며, 쿠키 스코프·CORS 오리진·OAuth 리디렉트 URI가 전부 호스트명 기준으로 판정된다
응답이 느리다캐시를 붙인다평균이 아니라 p99를 보고, 지연 구간이 DB인지 외부 API인지 이벤트 루프 대기인지 트레이스로 가른 뒤, 쿼리라면 실행계획으로 인덱스 선택과 스캔 행 수를 확인한다
서버가 죽었다재시작한다OOM인지 헬스체크 실패인지 배포 직후인지 먼저 가르고, 완화(롤백·트래픽 차단·스케일)를 복구보다 먼저 집행한 뒤 원인 분석은 정상화된 다음에 한다

Level 2의 모든 실습은 오른쪽 답을 내 손으로 재현한 기록을 남기는 것으로 끝납니다.

02 · From Level 1

Level 1의 DB 쪽 절반 위에, 나머지 절반을 채운다

Level 1은 세 능력의 “DB 쪽 절반”을 측정으로 익혔습니다. Level 2는 DB 바깥의 계층 — 이름·TLS·HTTP·브라우저·앱 서버·브로커·배포·관측·규제 — 을 같은 방식으로 채우고, 둘을 하나의 서비스에서 잇습니다.

LEVEL 1 · 기초 — 졸업생이 가진 것

원리를 측정으로 증명했다

측정 습관
요청당 발행 SQL·왕복 수·Buffers·SQL_ID·p95를 재고 전→후를 표로 남긴다
DB 내부
Oracle 실행계획, 잠금·데드락, MVCC(undo), 커넥션 = 세션, 하드 파싱과 바인드 변수
정합성
원장·금액, 잠금 순서, 멱등 키, 아웃박스, expand–contract를 한 프로세스·한 DB 안에서
도구
FastAPI와 Django, 두 ORM, 컨테이너 한두 개, 구조화 로그와 trace
LEVEL 2 · 실무 — 새로 채우는 것

운영하고, 깨뜨리고, 복구한다

계층
이름·인증서·프록시·앱 서버·브로커·실시간·배포·관측·보안 — DB 바깥 전부
DB
PostgreSQL 18 중심 + Level 1에서 Oracle로 배운 지점마다 대조 박스
무대
로컬 Docker 랩(*.test·Pebble·Nginx 캐시·시뮬레이터) + 실제 도메인으로 하는 실전 트랙
통과
정상 동작만으로는 부족 — 단계마다 고의로 깨뜨리고 복구한 기록, 산출물 3종

단계별 연결표

칩을 누르면 Level 1 안내서의 해당 퀘스트로

03 · 10 Stages

10단계 — 4단계까지는 선형, 5와 6은 병렬

모든 단계는 같은 네 부분 — 알아야 할 것, 사고가 나는 지점, 실습 과제, 통과 기준 — 을 갖습니다. 7단계 이후는 앞에서 만든 서비스가 실제로 배포되어 있어야 의미가 생깁니다.

카드를 누르면 펼쳐집니다 · L1 칩은 Level 1 안내서로 · 상태: 설계 / 집필 중 / 공개

단계 폴더 하나에 들어가는 것

Level 1의 문서 5종 + app/에 해당하는 Level 2의 구성

파일내용
가이드.md알아야 할 것(개념) · Level 1 연결 · Oracle 대조 박스 · 사고가 나는 지점 · 통과 기준
실습.md실습 과제별 명령과 실제 출력(실측)
사고_재현.md사고마다: 재현 → 증상 → 진단 명령 → 완화·복구 → 재발 방지
측정_기록.md전/후 표, 환경·버전·이미지 다이제스트
설계_기록.md이 단계에서 고른 설정값과 근거(기본값이 왜 안전한가) — 한 장짜리 ADR 형식
실전_트랙.md실제 도메인·VM·클라우드에서 할 일과 기록 양식
자가점검.md플립러닝 질문(①설명 ②근거 ③판단) + 우리의 답변 + 면접 “얕은 답 / 깊은 답”
lab/그 단계 시점의 실행 가능한 스냅샷(compose · 앱 코드 · 스크립트) — Level 1의 app/과 같은 방식
04 · MiniTrade

10단계 내내 키우는 서비스 하나 — MiniTrade

Level 1이 주문 백엔드 하나를 세 번 관통했듯, Level 2는 모의 증권사 백엔드 하나를 10단계 내내 키웁니다. 종합 산출물 3종이 이 서비스의 세 얼굴입니다.

계좌와 현금 원장

모든 자금 이동은 이중부기(차변·대변 쌍, 합 0). 잔고는 원장에서 파생한다.

주문 → 체결 → 포지션

주문은 멱등하게(거래 고유번호 UNIQUE), 체결은 외부 거래소가 통보, 포지션은 체결에서 파생.

시세

공개 거래소 웹소켓(실연결) + 시퀀스·구멍·속도를 조절할 수 있는 로컬 시세 시뮬레이터.

거래일(business date)

시각과 별개의 값으로 저장. 마감 배치와 대사는 거래일을 인자로 받는다.

외부 기관 시뮬레이터

거래소(주문 접수·체결 통보·지연·장애 주입), 은행/PG(입출금, mTLS 연계). 대사의 상대편.

세 얼굴 = 산출물 3종

실시간 시세·포트폴리오 서비스, 주문·정산 백오피스, 운영 증거 저장소.

이름(호스트) 계획

도메인은 RFC 6761이 예약한 *.test — 랩 DNS가 답한다

호스트용도
minitrade.testapex — CNAME 불가 실습, CAA·MX
app.minitrade.testSPA(정적)
api.minitrade.testDjango API
admin.minitrade.test백오피스(세션 분리·권한·감사)
ws.minitrade.test시세 게이트웨이
cdn.minitrade.testCDN 역할 Nginx(proxy_cache) — 캐시 오염·개인화 응답 사고
partner.test대외기관(거래소·은행 시뮬레이터) — mTLS
evil.test공격자 사이트 — CSRF·CSWSH 재현
05 · Lab

로컬에서 끝까지 재현하고, 실전 트랙으로 확인한다

모든 실습은 Docker로 재현하고 수치까지 직접 잽니다. 실제 인터넷이 있어야만 하는 부분은 절차로 남겨 학생이 자기 도메인으로 하고, 그 수치는 교재가 대신 재 주지 않습니다.

기본 · 로컬 재현

Docker 위의 랩 — 수치까지 실측

  • 도메인은 *.test, 이름 해석은 랩 DNS(권한 서버 + 재귀 리졸버)
  • 공개 CA 대신 Pebble — Let’s Encrypt가 만든 테스트용 ACME 서버 — 와 certbot
  • CDN은 Nginx proxy_cache, 외부 기관은 시뮬레이터, 장애는 주입 프록시로
  • 리눅스 셸 도구는 lab-shell 컨테이너 — 호스트 설정·인증서 저장소는 건드리지 않는다
과제 · 실전 트랙

실제 도메인·VM·GitHub에서

  • 도메인 구매와 NS 위임, 공개 리졸버 전환 측정
  • SSL Labs 등급, CT 로그 감시, CAA로 다른 CA의 발급 거부 확인
  • 실제 VM 배포와 GitHub Actions 파이프라인 실행
  • 단계마다 실전_트랙.md — 결과를 로컬 실측과 나란히 적는다

설계 단계에서 이 환경으로 실제로 확인한 것

2026-10-06 · 설계서 §4.1

항목결과
DockerDocker Desktop 29.8.1(linux/amd64), CPU 32 · 메모리 약 15.4GiB
리눅스 셸WSL 배포판 없음 → 실습용 리눅스 셸은 컨테이너(lab-shell: dig·ss·lsof·openssl·psql·redis-cli·curl·jq)로 제공
이미지 가용성postgres:18(19 없음) · redis:8 · nginx:1.29 · ghcr.io/letsencrypt/pebble · certbot/certbot · coredns/coredns · klutchell/unbound · grafana/k6 · grafana/otel-lgtm · rabbitmq:4-management · redpandadata/redpanda · python:3.13-slim/3.14-slim · edoburu/pgbouncer · zricethezav/gitleaks · aquasec/trivy · hashicorp/terraform · registry:2 · ubuntu:24.04 모두 확인
로컬 ACME 발급CoreDNS(minitrade.test 권한 존) + Nginx(webroot) + Pebble + certbot으로 HTTP-01 발급 성공. fullchain = 인증서 2장(리프+중간), 주체(Subject)는 비어 있고 이름은 SAN에만, 유효기간 6일(Pebble 기본 프로필), 리프에 AIA 필드 없음
함정(실측)Pebble 기본 HTTP-01 포트는 5002 → 설정에서 80으로. Pebble은 상태를 메모리에 두므로 재시작하면 certbot에 저장된 계정이 “not found”
공개 시세 웹소켓Upbit(trade, KRW-BTC·ETH) 5초에 67건(연결 63ms), Binance(btcusdt@trade) 5초에 355건(연결 114ms) — 실연결 실습 가능

결론: 1~10단계의 로컬 실습은 모두 Docker 위에서 성립한다. 단, “중간 인증서 누락을 브라우저가 AIA로 보완” 실습은 Pebble 인증서에 AIA가 없으므로 openssl로 만든 자체 CA(AIA 포함)로 따로 구성한다.

Oracle(Level 1) ↔ PostgreSQL(Level 2) — 대조 박스를 둘 지점 13곳
주제Oracle(Level 1)PostgreSQL(Level 2)
실행 통계DISPLAY_CURSOR(ALLSTATS LAST), BuffersEXPLAIN (ANALYZE, BUFFERS), shared hit/read
SQL 누적 지표v$sql, SQL_IDpg_stat_statements, queryid
MVCCundo로 과거 버전 재구성힙에 행 버전이 쌓임 → VACUUM·bloat
격리 수준SERIALIZABLE = 스냅샷REPEATABLE READ = 스냅샷, SERIALIZABLE = SSI(직렬화 실패 → 재시도)
데드락ORA-00060, 문장 하나 롤백deadlock_timeout(1s) 뒤 탐지, 트랜잭션 하나 중단
온라인 인덱스CREATE INDEX … ONLINECREATE INDEX CONCURRENTLY(실패하면 INVALID 인덱스가 남는다)
DDL 대기DDL_LOCK_TIMEOUTlock_timeout + 잠금 대기열(뒤의 모든 쿼리가 줄을 선다)
NOT NULL 무중단ENABLE NOVALIDATE → VALIDATECHECK … NOT VALID → VALIDATE CONSTRAINT
빈 문자열NULL로 저장빈 문자열 그대로
금액 타입NUMBER(p,s)NUMERIC(p,s)
커넥션세션 = 서버 프로세스, DRCP연결 = 백엔드 프로세스, pgbouncer
행 수준 접근통제VPDRow Level Security
감사Unified Auditingpgaudit / 앱 감사 테이블
열린 결정 — 집필 중 확정할 기본안
항목기본안바꿀 조건
실시간 게이트웨이FastAPI + websocketsDjango Channels 비교 실습을 추가할지
작업 큐Celery + RabbitMQ단순성을 우선하면 Arq + Redis
키 관리(KMS 대체)OpenBao(오픈소스 Vault 포크)의 transit 엔진원조 Vault를 쓰고 싶다면 hashicorp/vault(BUSL 라이선스)
GitHub Actions워크플로 파일 + 실전 트랙에서 실제 실행저장소를 GitHub에 올리면 교재가 직접 실행 결과를 싣는다
장애 주입Toxiproxy — 지연·끊김·대역 제한을 API로 주입—
권한 DNSBIND 9.20 — 위임·TSIG 동적 갱신(DNS-01)단순 존만 필요하면 CoreDNS
로컬 TLS 등급testssl.sh(SSL Labs 대체)—
컨테이너 안 브라우저chromedp/headless-shell 또는 zenika/alpine-chrome — 랩 루트 CA를 컨테이너 안에서만 신뢰—
06 · Outputs & Schedule

산출물 3종과 12개월 일정

기술 목록은 검증되지 않지만, 운영해 본 시스템 하나는 검증됩니다. 세 산출물이 각각 다른 종류의 능력을 증명합니다.

실시간 시세·포트폴리오 서비스

13458

공개 거래소 웹소켓을 정규화해 저장과 동시에 재배포하고, 보유 종목의 실시간 평가액과 목표가 알림을 준다.

완성 기준(측정치로)연속 운영 기록, 강제 단절 후 복구 시간, 동시 연결 1,000 이상에서 p99, 시퀀스 검사로 유실 0

주문·정산 백오피스

2469

주문을 멱등하게 받고, 체결을 반영하고, 이중부기 원장으로 기록하고, 마감 배치로 정산하고, 대사 리포트를 낸다. 관리자 화면엔 권한 분리와 감사 로그.

완성 기준(측정치로)중복 요청 1,000건 주입 후 원장 합계 일치, 마감 배치 3회 재실행 동일, 의도적 누락이 대사에서 자동 탐지

운영 증거 저장소

7810

두 서비스를 돌리는 인프라와 절차 — IaC, CI/CD, 대시보드, 런북, 포스트모템, ADR.

완성 기준(측정치로)롤백 1분 이내 측정 기록, 장애 훈련 포스트모템, ADR 5건, SLO·에러 버짓 대시보드

로드맵의 “24시간 연속 운영”은 로컬 랩에서 실제로 24시간 돌려 기록합니다. 기간을 줄여야 하면 줄인 값과 이유를 함께 적습니다.

12개월 실행 일정

주 10~15시간 기준 · 단계를 넘기는 기준은 기간이 아니라 통과 기준

월차단계끝날 때 남아 있어야 하는 것
11단계도메인 + HTTPS로 동작하는 서버 1대, TTL 전환 측정 기록
22단계별도 오리진 SPA + 쿠키 인증 API, CSRF 공격·방어 재현 기록
33단계워커 설정별 p99 비교표, 배포 중 요청 유실 0 검증
4–54단계주문·체결·원장 스키마, 1,000만 행 조회 튜닝 기록, 무중단 마이그레이션 리허설
6–75단계산출물 1(실시간 시세 서비스) 동작, 복구 시간과 부하 측정치
86단계멱등 파이프라인, DLQ 운영 절차, 재실행 가능한 마감 배치
97단계CI/CD 파이프라인과 롤백 1분 측정 기록
108단계트레이싱 적용, SLO 대시보드, 장애 훈련 1회와 포스트모템
119단계위협 모델 1장, 감사 로그, 산출물 2(주문·정산) 완성
1210단계ADR 5건, 용량·비용 산정서, 산출물 3(운영 증거), 글 3편

주당 시간 배분

로드맵의 기준 배분(합 11시간)

기록을 빼면 12개월 뒤에 말할 것이 남지 않습니다. 깨뜨리는 시간을 빼면 지식은 늘지만 경험은 늘지 않습니다.

집필 진행 상황

설계 → 집필 중(실측·사고 재현·학생 따라하기 검증) → 공개

07 · Fact check

로드맵의 날짜·수치는 1차 출처로 다시 확인한다

로드맵에 들어 있는 날짜·수치 주장은 그대로 옮기지 않습니다. 설계 단계(2026-10-06)에 먼저 확인한 것과 집필 때 확인할 것입니다.

주장판정확인 결과출처
공개 TLS 인증서 유효기간 단계 축소(398 → 47일)맞음Ballot SC081v3 채택(인증서 발급자 25표·브라우저 4표 찬성), 2026-03 시작 → 2029-03 종료, SAN 검증 재사용 398 → 10일. 단계별 날짜(200일 2026-03-15 · 100일 2027-03-15 · 47일 2029-03-15, 기준은 발급일)는 1단계 집필 때 BR 본문 2.3.1판으로 대조 완료CA/B Forum
Let’s Encrypt 90 → 45일맞음, 더 구체적2026-05-13 tlsserver 프로필 45일(선택), 2027-02-10 classic 64일·인가 재사용 10일, 2028-02-16 classic 45일·인가 재사용 7시간. ARI 사용과 유효기간의 약 2/3 지점 갱신 권고, DNS-PERSIST-01 예고Let’s Encrypt
PEP 779맞음Python 3.14에서 free-threaded가 Phase II(공식 지원·선택 빌드), 기본 빌드는 여전히 GILPEP 779
전자금융감독규정 시행세칙 개정(업무용 SaaS)맞음, 출처 보정로드맵이 단 금융위 링크는 2026-01-19 변경 예고 보도자료(조건: 침해사고 대응기관 평가, 단말 보호·안전한 인증·최소 권한·구간 암호화, 중요정보 모니터링, 반기 1회 이행 평가, 개인(신용)정보 처리 SaaS 제외). 2026-04-20 시행은 언론 보도로 확인 — 9단계에 두 날짜를 구분해 싣는다금융위 · ZDNet
Pebble이 CAA를 검사하는가검사 안 함Pebble은 caaIdentities를 디렉터리 메타에 광고만 하고 발급 검증(VA)에서 CAA를 조회하지 않는다 → CAA 거부 실습은 실전 트랙(Let’s Encrypt staging)으로Pebble 소스
6일 단기 인증서맞음Let’s Encrypt shortlived 프로필(160시간) 2026-01-15 정식 제공, IP 주소 인증서는 이 프로필로만. 로컬 Pebble 발급에서 6일 유효기간 실측Let’s Encrypt
PostgreSQL 11+ 기본값 있는 컬럼 추가의 재작성 없음집필 때4단계 집필 때 PG 18 문서와 실측으로 확인—