infra
Platform

모듈 맵

[SW Eng] 12-Factor App — 환경에 흔들리지 않는 앱의 원칙

0 / 38 완료

펼치기
0 / 38 완료0%

Sw-engineering · 20 / 38

[SW Eng] 12-Factor App — 환경에 흔들리지 않는 앱의 원칙

설정 분리·무상태·로그 스트림·일회성 프로세스 등 클라우드 네이티브 앱의 12가지 원칙을 PM·인프라 관점에서 핵심만 정리합니다

🚨INCIDENT ALERT
HIGH

새 서비스를 K8s에 올렸더니 문제가 줄줄이 터집니다. 인스턴스를 2개로 늘렸더니 로그인이 자꾸 풀립니다(세션이 한 인스턴스에만). 설정을 바꾸려면 코드를 다시 빌드해야 하고, 로그는 컨테이너 안 파일에 쌓여 사라집니다. 옆 팀의 서비스는 같은 환경에서 인스턴스를 10개로 늘려도 멀쩡하고, 설정은 환경변수로 즉시 바뀝니다. 차이는 '12-Factor 원칙'을 따랐는가입니다. 이 원칙은 '클라우드·컨테이너에서 잘 굴러가는 앱'의 체크리스트입니다.

이번 챕터에서 배울 것
  • 1설정을 코드에서 분리해 환경에 두는 원칙과 그 이유를 설명할 수 있다
  • 2무상태 프로세스가 수평 확장·무중단 배포를 가능케 함을 설명할 수 있다
  • 3로그를 stdout 스트림으로 흘리는 원칙이 컨테이너와 맞는 이유를 설명할 수 있다
  • 412-Factor를 새 서비스의 클라우드 준비도 체크리스트로 활용할 수 있다

핵심 원칙 — 환경 의존을 끊는다

💡개념

12-Factor 중 인프라가 가장 챙기는 4가지

12-Factor는 클라우드 네이티브 앱의 12가지 원칙입니다. PM·인프라에게 가장 중요한 핵심부터 봅니다.

원칙한 줄안 지키면중요도
Config(설정)환경마다 다른 값은 코드가 아니라 환경(env)에환경별 빌드·비밀 유출 → [[glossary-config-env]]★★★
Stateless(무상태)프로세스는 로컬에 상태를 안 둠(외부 저장소로)수평 확장 불가·세션 풀림★★★
Logs(로그)stdout 스트림으로 흘리고 수집은 플랫폼이컨테이너에서 로그 소실 → [[glossary-observability]]★★
Disposability(일회성)빠른 기동·우아한 종료(graceful shutdown)배포·스케일 시 요청 유실★★
Backing servicesDB·캐시·큐를 교체 가능한 '연결된 자원'으로환경 이전 어려움★★
Build/Release/Run빌드·릴리스·실행 단계 분리롤백·추적 어려움 → [[cicd-pipeline]]★★

나머지(Codebase, Dependencies, Processes, Port binding, Concurrency, Dev/prod parity)도 같은 정신 — "환경에 흔들리지 않고, 교체·확장·재현이 쉬운 앱" 을 지향합니다.

무상태 — 확장의 전제

💡개념

상태를 밖으로 빼야 인스턴스를 자유롭게 늘린다

오프닝의 "인스턴스 늘렸더니 로그인 풀림"은 상태(세션)를 프로세스 로컬에 둔 탓입니다.

TEXT
상태를 로컬에 둠(나쁨):
  요청1 → 인스턴스A (세션 저장)
  요청2 → 인스턴스B (A의 세션 모름!) → 로그인 풀림
  → 어쩔 수 없이 sticky session(같은 사람=같은 인스턴스) 강제 → 확장 경직

무상태(좋음):
  세션을 Redis 등 외부에 저장
  요청1 → 인스턴스A → Redis
  요청2 → 인스턴스B → Redis(같은 세션 조회) → OK
  → 어느 인스턴스가 받든 동일 → 자유롭게 scale-out, 무중단 배포

무상태는 [[architecture-patterns]]의 확장성과 [[release-strategy]]의 롤링/블루그린 배포의 전제입니다. 상태(세션·캐시·업로드 파일)를 외부 저장소(Redis·DB·오브젝트 스토리지)로 빼는 것이 클라우드 앱의 기본입니다.

클라우드 준비도 점검 — 직접 확인

112-Factor 체크리스트로 새 서비스 준비도 점검

새 서비스를 컨테이너/K8s에 올리기 전, 인프라가 이 체크리스트로 '클라우드에서 잘 굴러갈지'를 미리 판단합니다.

TEXT
□ 설정: DB접속·키가 코드/이미지에 하드코딩됐나, 환경변수/Secret으로 빠졌나?
   → grep -r "password\|api_key" src/  로 하드코딩 흔적 확인
□ 무상태: 세션·캐시·업로드를 로컬 메모리/디스크에 두나, 외부(Redis/S3)에 두나?
   → 인스턴스 2개로 늘려 로그인·업로드가 유지되는지 테스트
□ 로그: 파일에 직접 쓰나, stdout으로 흘리나?
   → 컨테이너 docker logs로 앱 로그가 보이는지 확인
□ 종료: SIGTERM 받으면 처리 중 요청을 마치고 우아하게 종료하나?
   → graceful shutdown 구현 여부([[glossary-server-was-linux]])
OUTPUT
점검 결과 예:
  설정  ✗ application.yml에 운영 DB 비밀번호 하드코딩 → Secret으로 분리 필요
  무상태 ✗ 세션을 톰캣 로컬에 저장 → Redis 세션으로 외부화 필요
  로그  ✓ stdout 출력
  종료  ✗ SIGTERM 즉시 종료(처리 중 요청 유실) → graceful shutdown 추가
→ 3개 미흡. 이대로 scale-out하면 세션 풀림·비밀 유출·배포 시 요청 유실
echo '설정·상태·로그·종료 4축 점검'
🔍실행 후 확인할 것
  • 설정 점검: 코드/이미지에 비밀번호·키가 박혀 있으면 즉시 위험(유출 + 환경별 빌드) → Secret/환경변수로 분리. grep으로 하드코딩 흔적부터 찾는다
  • 무상태 점검: 인스턴스를 2개로 늘렸을 때 로그인·장바구니·업로드가 유지되면 무상태(OK). 풀리면 로컬 상태 보유 → 외부 저장소로 빼기 전엔 scale-out 금지
  • 로그 점검: docker logs로 앱 로그가 보이면 stdout(OK). 컨테이너 안 파일에만 쌓이면 컨테이너 재시작 시 소실 → 수집 불가([[glossary-observability]])
  • 종료 점검: 배포(롤링) 중 처리 중이던 요청이 에러로 끊기면 graceful shutdown 미구현 → SIGTERM 후 유예시간 동안 마무리하도록 수정

상황: 개발 편의로 application.yml에 운영 DB 비밀번호·API 키를 넣어 이미지에 빌드했습니다. 그 결과 dev/stg/prod마다 다른 이미지를 빌드해야 하고, 더 심각하게는 운영 비밀이 git 저장소와 이미지 레이어에 그대로 남아 유출됩니다.

원인: 12-Factor의 Config 원칙 위반 — 환경마다 다른 값(설정)을 코드/이미지에 박았습니다. "같은 산출물을 모든 환경에 배포"하는 재현성([[semantic-versioning]])과 보안이 함께 깨집니다.

진단:

로컬 터미널
grep -rnE "password|secret|api[_-]?key" src/ config/ | grep -v "ENV\|getenv\|\\${"
# 실제 값이 박혀 있으면(환경변수 참조가 아니라) 하드코딩 확정
git log -p -- application.yml | grep -i password   # 이력에도 남았는지

해결: (1) 설정을 환경변수/Secret Manager(Vault·K8s Secret)로 분리하고 코드는 동일 유지. (2) 이미 노출된 비밀은 즉시 교체(rotate) — 저장소에서 지워도 git 이력에 남으므로 키 자체를 갱신해야 함. (3) CI에 시크릿 스캐너를 넣어 하드코딩을 머지 게이트에서 차단([[cicd-pipeline]]). 설정 분리는 편의가 아니라 보안·재현성의 기본입니다. 환경별 설정 운영은 [[glossary-config-env]]에서 더 다룹니다.

💼
실무 맥락
현업 패턴

인프라/SRE로서 12-Factor는 설계 리뷰의 체크리스트입니다 — 새 서비스가 컨테이너/K8s에 올라오기 전, 설정 분리·무상태·stdout 로그·graceful shutdown이 됐는지 점검해 "이대로 올리면 scale-out에서 세션 풀리고, 배포 때 요청 유실되고, 로그가 사라진다"를 미리 경고합니다. 이 점검 한 번이 출시 후의 반복 장애를 막습니다. PM은 12-Factor를 '클라우드 준비도'의 공통 언어로 삼아, 비기능 요구([[requirements-prd]])에 "무상태·설정 외부화·관측성"을 명시하고 인프라와 개발이 같은 기준으로 설계하도록 정렬합니다.

다음 모듈에서는 서비스 간 통신을 느슨하게 만드는 또 하나의 핵심 — 동기 vs 비동기와 메시지 큐를 다룹니다.

지식 확인

퀴즈 — 4문제

Q1

12-Factor의 '설정(Config)은 환경에 저장' 원칙이 막으려는 문제는?

Q2

'무상태(Stateless) 프로세스' 원칙이 수평 확장(scale-out)에 중요한 이유는?

Q3

12-Factor의 '로그는 이벤트 스트림으로' 원칙이 권장하는 것은?

Q4

PM·인프라가 12-Factor를 '체크리스트'로 쓰면 좋은 점은?

0 / 4 답변

이것도 배워보세요