신규 프로젝트 킥오프. 개발 리드가 화면에 스택을 띄웁니다. "프론트는 Next.js, 백엔드는 Spring Boot, DB는 PostgreSQL, 캐시는 Redis, 이벤트는 Kafka, 배포는 Docker + Kubernetes입니다." PM인 당신은 이 목록에서 일정·리스크를, 인프라 담당인 당신은 프로비저닝할 자원을 읽어내야 합니다. 그런데 어디까지가 언어고 어디가 인프라인지 뒤섞여 보입니다. 스택 나열을 '층위'로 분해하는 법을 익히면, 이 한 장의 슬라이드에서 준비물 목록이 자동으로 떨어집니다.
- 1기술스택 항목을 층위(프론트/백/DB/캐시/메시징/컨테이너/오케스트레이션)로 분류할 수 있다
- 2PostgreSQL·Redis·Kafka 같은 저장소/미들웨어의 역할을 한 줄로 구분할 수 있다
- 3스택 목록에서 인프라 준비물(런타임·저장소·외부연동·배포)을 체크리스트로 뽑을 수 있다
- 4모르는 기술이 나와도 "어느 층위인가"를 먼저 물어 빠르게 자리매김할 수 있다
스택을 층위로 분해하기
모든 스택 항목은 어느 한 층위에 속한다
기술 이름이 낯설어도 당황할 필요 없습니다. 거의 모든 항목은 아래 층위 중 하나입니다. "이건 어느 층위?"만 물으면 자리매김됩니다.
| 층위 | 역할 | 대표 예 |
|---|---|---|
| 언어 | 코드를 쓰는 문법 | Java, Python, TypeScript, Go |
| 런타임 | 코드를 실행하는 환경 | JVM, Node.js, CPython |
| 프론트엔드 | 사용자 화면 | React, Next.js, Vue |
| 백엔드 프레임워크 | 서버 로직 구조 | Spring Boot, Django, Express |
| 관계형 DB | 영구 데이터(정합성) | PostgreSQL, MySQL |
| NoSQL/캐시 | 빠른/유연한 데이터 | Redis, MongoDB |
| 메시징 | 비동기·이벤트 전달 | Kafka, RabbitMQ, SQS |
| 컨테이너 | 실행 패키징 | Docker |
| 오케스트레이션 | 컨테이너 운영 자동화 | Kubernetes |
| 관측성 | 로그·메트릭·추적 | Prometheus, Grafana, Loki |
핵심 습관: 모르는 이름이 나오면 "그건 어느 층위예요?"라고 묻습니다. 층위만 알면 일정·인프라 영향이 즉시 가늠됩니다.
확대
위 그림처럼 스택 항목은 프론트엔드·백엔드·DB·캐시·메시징·컨테이너·오케스트레이션 7개 층위 중 하나에 속합니다.
저장소·미들웨어의 역할 구분
PostgreSQL vs Redis vs Kafka — 같은 '데이터'라도 역할이 다르다
스택에 데이터 관련 항목이 여러 개면 각자 다른 일을 합니다. 이걸 뭉뚱그리면 인프라 준비가 어긋납니다.
- PostgreSQL/MySQL(관계형 DB): 주(主) 데이터의 영구 보관과 정합성(트랜잭션). 주문·회원·결제 기록.
- Redis(인메모리): 빠른 임시 데이터 — 캐시, 세션, 실시간 랭킹, 가벼운 큐. 메모리 기반이라 빠르지만 용도가 다름.
- Kafka/RabbitMQ(메시징): 비동기 이벤트 전달 — 생산자와 소비자를 분리해 스파이크 완충·장애 격리. "주문 생성 이벤트"를 여러 소비자가 나눠 처리.
PM 관점: 이 셋이 모두 있다는 건 "영구 데이터 + 캐싱 + 비동기 처리"를 의도한 설계입니다. 각각 별도의 프로비저닝·모니터링·백업 대상이 됩니다.
확대
위 그림처럼 PostgreSQL은 영구 보관, Redis는 빠른 임시 데이터, Kafka는 비동기 이벤트 전달로 각자 역할이 분리돼 있어 하나로 대체할 수 없습니다.
확대
위 그림처럼 스택 항목마다 런타임 버전·볼륨·방화벽·이미지 등 인프라 준비물이 1:1로 도출됩니다.
스택에서 인프라 준비물 뽑기 — 직접 해보기
스택 한 줄을 받아 층위로 분류하고, 각 층위가 요구하는 인프라 준비물을 표로 뽑습니다. 코드를 몰라도 할 수 있는 PM·인프라의 핵심 작업입니다.
입력 스택: Next.js / Spring Boot(Java 17) / PostgreSQL / Redis / Kafka / Docker / K8s
층위 분해 → 준비물:
Next.js(SSR?) → 렌더링 방식 확인 → SSR이면 Node 런타임 서버 / 정적이면 CDN
Spring Boot/Java17 → 베이스 이미지 temurin:17, JAR 산출물, 헬스체크 엔드포인트
PostgreSQL → 관리형 DB 인스턴스, 백업/복제, 접속 계정·시크릿
Redis → 캐시 인스턴스(메모리 크기), 영속화 여부 결정
Kafka → 브로커 클러스터(or 관리형), 토픽 설계, 디스크/보존기간
Docker → 이미지 레지스트리, 빌드 파이프라인
Kubernetes → 클러스터, 매니페스트/Helm, 인그레스·시크릿·오토스케일
echo '스택을 층위로 분류 → 준비물 도출'- 관계형 DB(PostgreSQL)가 있으면 → 백업·복제·접속 시크릿이 필수 준비물. 빠졌으면 데이터 유실/유출 리스크로 표시
- 캐시/메시징(Redis/Kafka)이 있으면 → 각각 별도 인스턴스·모니터링·용량 산정 필요. "DB 하나로 되겠지"는 오판
- Kubernetes가 보이면 → 단순 서버 배포가 아니라 매니페스트·레지스트리·인그레스까지 파이프라인 전체가 필요 → 일정·러닝커브를 크게 반영
- 모르는 항목이 있으면 "어느 층위?"를 먼저 확정한다 — 층위만 알면 비슷한 준비물 패턴(저장소면 백업, 런타임이면 버전)으로 추론 가능
상황: 기획·인프라가 스택의 Kafka를 "또 하나의 서버" 정도로 가볍게 보고 일정·자원을 잡았다가, 운영 직전 브로커 이중화·토픽 파티션·메시지 보존기간(retention)·디스크 용량이 전혀 준비되지 않은 것을 발견합니다.
원인: Kafka는 '메시징 층위'로, 단일 인스턴스가 아니라 보통 다중 브로커 클러스터로 운영되며 디스크에 메시지를 보존합니다. 층위를 오인하면 준비물 규모를 통째로 과소평가합니다.
진단 — 스택 검토 체크:
□ Kafka는 단일/클러스터? (운영은 보통 3 브로커+)
□ 토픽·파티션 설계 주체는? (개발팀 협의)
□ 메시지 보존기간 × 처리량 = 필요 디스크 용량 산정했나?
□ 관리형(MSK/Confluent) vs 자체 운영 결정했나?
해결: 스택을 받는 즉시 각 항목을 층위로 분류하고, 메시징/DB/캐시처럼 '상태를 가진' 항목은 용량·이중화·백업·보존을 별도 산정합니다. 관리형 서비스로 가면 운영 부담을 줄이는 대신 비용을 본다 — 이 트레이드오프를 초기에 결정합니다.
심화 — 스택 한 단어가 숨기는 것들
심화: 이름 뒤의 부속 스택, 그리고 버전·EOL·라이선스
층위 분류로 준비물을 뽑는 법을 익혔다면, 다음은 스택 문서에 적히지 않은 것을 읽는 단계입니다. 스택 한 단어는 그 뒤에 부속 시스템과 수명(라이프사이클)을 숨기고 있고, 규모와 시간이 갈수록 이 숨은 부분이 진짜 비용이 됩니다.
- 한 단어가 끌고 오는 부속 스택: Kafka라고 적히면 실제로는 브로커 클러스터 + 메타데이터 코디네이터(구버전은 ZooKeeper, 신버전은 KRaft) + 전용 모니터링까지가 한 세트입니다. Kubernetes 한 단어는 etcd·네트워크 플러그인(CNI)·인그레스 컨트롤러·레지스트리를 함께 데려옵니다. 준비물 체크리스트는 표면 항목 수가 아니라, 항목마다의 부속 스택까지 펼쳐야 실제 규모가 나옵니다.
- 이름이 아니라 버전이 리스크를 정합니다: 같은 Java라도 8과 17은 베이스 이미지·지원 상태가 다르고(컴파일·인터프리터·빌드·런타임), EOL(지원 종료)이 지난 버전은 보안 패치가 더는 나오지 않아 그 자체로 보안 감사의 지적 사항입니다. 스택을 읽을 때 '무엇'과 함께 '몇 버전, 지원 종료일 언제'까지 물어야, 인수인계받는 순간 함께 물려받을 부채가 보입니다.
- 라이선스도 움직입니다: 오픈소스라 믿고 쌓은 항목이 라이선스를 바꾸는 일은 실제로 반복됩니다 — Redis·Elasticsearch·Terraform이 상용 라이선스로 전환하며 각각 커뮤니티 포크(Valkey·OpenSearch·OpenTofu)가 생겼습니다. 관리형 서비스로 감쌌다면 영향이 완충되지만, 자체 운영이라면 '이 항목의 라이선스가 바뀌면 우리는?'이 스택 선정 때 짚어야 할 리스크입니다.
정리하면 스택 읽기의 완성형은 '항목 → 층위 → 준비물'에 '부속 스택 → 버전·EOL → 라이선스' 세 겹을 더한 것입니다. 앞이 오늘의 준비물을, 뒤가 3년 뒤의 청구서를 알려줍니다.
상황: 스택 문서의 Redis를 층위표대로 '캐시'로 분류해, 메모리가 차면 오래 안 쓴 키부터 자동으로 지우는 eviction 정책(allkeys-lru)을 설정하고 백업 없이 운영했습니다. 몇 주 뒤 '간헐적으로 처리되지 않는 주문이 있다'는 신고가 들어옵니다. 에러 로그는 어디에도 없습니다.
원인: 개발팀은 같은 Redis 인스턴스를 캐시뿐 아니라 비동기 작업 큐로도 쓰고 있었습니다. 메모리가 찰 때마다 eviction이 캐시 키와 큐 데이터를 구분하지 않고 지웠고, 지워진 작업은 에러 없이 그냥 사라졌습니다. 층위 분류는 맞았지만 용도 확인이 빠진 것입니다 — 같은 이름의 시스템도 용도(캐시=지워져도 됨 vs 큐·세션=지우면 사고)에 따라 설정·백업·모니터링이 정반대가 됩니다.
진단: Redis 상태 정보(INFO)에서 evicted_keys 수치가 누적되는지 확인하고, 그 증가 시각과 유실 신고 시각을 대조합니다. 키 목록을 훑어(SCAN) 캐시가 아닌 성격의 키(queue:*, session:* 등)가 섞여 있는지 봅니다. 지워지면 안 되는 키가 나오면 확정입니다.
해결: 지워지면 안 되는 데이터(큐·세션)는 eviction 없는 별도 인스턴스로 분리하고 영속화·백업을 켭니다. 그리고 스택 검토 절차에 한 줄을 추가합니다 — 저장소 항목마다 '여기엔 지워져도 되는 데이터만 담기나?'를 개발팀에 확인. 층위는 준비물의 종류를 알려주지만, 용도가 준비물의 설정을 결정합니다.
PM·인프라가 RFP나 아키텍처 리뷰에서 가장 먼저 하는 일이 "스택을 층위로 분해해 준비물·리스크를 도출"하는 것입니다. 개발팀이 코드를 짜는 동안, 인프라는 이 분해표를 근거로 DB 인스턴스·캐시·메시지 브로커·레지스트리·클러스터를 프로비저닝하고, PM은 각 층위의 러닝커브와 외부 의존(관리형 서비스 계약, 키 발급)을 일정에 박습니다. 스택을 "코딩 대상"이 아니라 "준비물 명세"로 읽는 능력이, 코드를 짜지 않는 사람의 핵심 무기입니다.
이것으로 Phase 0(개발자의 언어)을 마칩니다. 다음 모듈부터는 이 용어들이 실제로 쓰이는 무대 — 소프트웨어가 기획에서 운영까지 흘러가는 개발 생애주기(SDLC)를 다룹니다.
실전 랩으로 손에 익히기: 기술스택 해독 실습 — 채용공고·아키텍처 문서의 스택을 층위로 해독하고 학습 우선순위를 판단합니다.
관련 모듈로 더 깊이:
- 컴파일·인터프리터·빌드·런타임 — 스택의 언어·런타임·빌드 층위를 깊이 있게
- 프론트엔드·백엔드·렌더링 — 스택을 프론트/백엔드/렌더링으로 분해
- 모놀리식 vs 마이크로서비스 — 분해한 스택이 모놀리식·MSA로 배치되는 구조