
생성 수정
IBM * 레드햇 AX 과정 · 30강
S3·IAM과 리버스 파이프라인 — 팀 프로젝트로 마무리하기
2026년 8월 3일(월) ~ 8월 25일(화)
6. S3와 IAM 역할 — 키를 서버에 심지 않는 법
6.1 먼저 만나는 함정 — ARN이냐 이름이냐
플러터 카메라로 찍은 이미지를 S3에 업로드합니다. 여기서 첫 번째 벽에 부딪힙니다.
- 버킷의 ARN:
arn:aws:s3:::example-bucket-10498 .env에 넣어야 할 값: 마지막 조각인 버킷 "이름"만
# ⭕ 올바름
VISION_S3_BUCKET=example-bucket-10498
# ❌ 틀림 — NoSuchBucket 에러
VISION_S3_BUCKET=arn:aws:s3:::example-bucket-10498
⚠️ ARN 전체를 넣으면
NoSuchBucket으로 실패합니다. 에러 메시지가 "그런 버킷 없음"이라 버킷이 안 만들어진 줄 알고 콘솔을 헤매게 되는 대표적 함정입니다. 버킷은 있습니다. 이름이 틀렸을 뿐입니다.
ARN(Amazon Resource Name) 은 AWS 안의 모든 자원을 유일하게 가리키는 주소 체계입니다.
arn : aws : s3 : : : example-bucket-10498
│ │ │ │ │ └── 리소스 (여기서는 버킷 이름)
│ │ │ │ └── 계정 ID (S3는 전역 고유라 비어 있음)
│ │ │ └── 리전 (S3는 전역이라 비어 있음)
│ │ └── 서비스
│ └── 파티션
└── 고정 접두어
DB의 주식별자(Primary Key) 와 같은 역할입니다(4주차). 전체 시스템에서 그 하나를 유일하게 지목합니다. 정책 문서에는 ARN을, 애플리케이션 설정에는 이름을 씁니다. 쓰이는 자리가 다릅니다.
6.2 환경변수 키 목록
.env 에 들어갈 S3 관련 키입니다.
VISION_S3_BUCKET=CHANGE_ME
AWS_REGION=ap-northeast-2
AWS_DEFAULT_REGION=ap-northeast-2
AWS_ACCESS_KEY_ID=CHANGE_ME
AWS_SECRET_ACCESS_KEY=CHANGE_ME
⭐ 그런데 이 마지막 두 줄이 이 절의 주제입니다. 로컬 개발에서는 액세스 키를 씁니다. 하지만 EC2 위에서 도는 서버에는 이 두 줄을 넣지 않는 것이 정답입니다. 왜 그런지, 대신 무엇을 쓰는지가 6.3절부터입니다.
6.3 버킷 정책 ↔ IAM 역할 — 어느 쪽에 권한을 붙이나
AWS에서 "이걸 해도 되는가"를 정하는 방식은 두 가지입니다.
| 버킷 정책 (리소스 기반) | IAM 역할·정책 (아이덴티티 기반) | |
|---|---|---|
| 어디에 붙는가 | 자원(버킷)에 붙음 | 주체(사용자·역할)에 붙음 |
| 문장의 주어 | "이 버킷은 누구에게 열려 있다" | "이 역할은 무엇을 할 수 있다" |
Principal 항목 | 필요함 (누구인지 적어야 함) | 없음 (역할 자체가 주체) |
| 주로 쓰는 때 | 외부 계정 · 익명 사용자에게 열어줄 때 | 내 계정 안의 리소스끼리 |
⭐ 같은 계정 안의 EC2에서만 쓸 거라면 버킷 정책은 아예 필요 없습니다. 버킷 정책은 외부 계정·익명 사용자에게 열어줄 때 쓰는 리소스 기반 정책입니다. 내 계정 EC2 → 내 버킷은 IAM 역할이 표준이고, 액세스 키를 서버에 심을 필요가 없어 훨씬 안전합니다.
액세스 키를 서버에 심는 것이 왜 위험한지는 이미 여러 번 겪었습니다.
- 키가
.env에 있고,.gitignore를 나중에 만들면 public 저장소에 그대로 올라갑니다. - 키가 유출되면 누구든 그 권한을 씁니다. 유출 사실도 늦게 압니다.
- 키를 바꾸려면 서버마다 들어가서 갈아야 합니다.
IAM 역할은 이 문제를 구조적으로 없앱니다. 키가 아예 존재하지 않습니다. EC2 인스턴스에 역할을 붙여두면, 인스턴스 메타데이터에서 짧은 수명의 임시 자격증명이 자동으로 발급·갱신됩니다.
6.4 IAM 역할 만들기 — 4단계
1단계. IAM 역할 생성
IAM 콘솔 → 역할(Roles) → 역할 만들기
→ 신뢰할 수 있는 엔터티 유형: AWS 서비스
→ 사용 사례: EC2
2단계. 권한 정책 (인라인 정책 생성)
역할 자체가 주체이므로 Principal 항목이 없습니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowImageBucketAccess",
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject"],
"Resource": "arn:aws:s3:::example-bucket-10498/*"
}
]
}
목록 조회가 필요하면 버킷 자체를 대상으로 하는 문장을 추가합니다.
{
"Sid": "AllowListBucket",
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": "arn:aws:s3:::example-bucket-10498"
}
⚠️ ⭐ 가장 실수하기 쉬운 포인트
GetObject/PutObject는 객체가 대상이라 ARN 끝에/*가 붙습니다.ListBucket은 버킷이 대상이라/*가 없습니다. 두 ARN이 다릅니다. 이걸 같게 쓰면 "권한을 줬는데 안 된다"가 됩니다.이 구분은 4주차의 개체(Entity) ↔ 그 개체들이 담긴 테이블 구분과 같은 층위 문제입니다. "행에 대한 권한이냐, 테이블에 대한 권한이냐." 층을 헷갈리면 정책이 안 먹습니다.
3단계. EC2에 역할 연결
EC2 콘솔 → 인스턴스 선택 → 작업 → 보안 → IAM 역할 수정
4단계. FastAPI 코드
boto3가 인스턴스 메타데이터에서 자격증명을 자동으로 취득하므로, 코드에 키를 명시할 필요가 없습니다.
import boto3
s3 = boto3.client("s3", region_name="ap-northeast-2")
s3.upload_file("local.png", "example-bucket-10498", "images/local.png")
세 줄입니다. 액세스 키가 한 글자도 없습니다.
💡 버킷은 "퍼블릭 액세스 차단"을 켠 그대로 둡니다. 흔한 오해가 "업로드가 안 되니 퍼블릭으로 열어보자" 입니다. 퍼블릭 차단은 인터넷 누구나 접근을 막는 설정이고, IAM 역할을 통한 접근과는 다른 통로입니다. 차단을 켜둔 채로 IAM 역할은 정상 동작합니다. 열지 마세요.
6.5 업로드 경로를 아키텍처로 그리면
[플러터 앱]
│ 사진 촬영
▼
[게이트웨이] ← 인증·라우팅 (퍼사드)
▼
[인바운드 라우터] ← FastAPI 라우터 (인바운드 어댑터)
▼
[앱 유스케이스] ← "영수증 이미지를 보관한다" (도메인)
▼
[아웃바운드 포트] ← ImageStoragePort (추상)
▼
[S3 어댑터] ← boto3 구현 (구상)
▼
[S3 버킷]
포트/어댑터 방식으로 구현합니다. 이렇게 짜두면 저장소를 S3에서 다른 것으로 바꿔도 유스케이스는 한 줄도 바뀌지 않습니다. 6주차에서 배운 그대로입니다.
| 계층 | 아는 것 | 모르는 것 |
|---|---|---|
| 유스케이스 | "이미지를 어딘가에 보관한다" | S3, boto3, ARN, 리전 |
| 아웃바운드 포트 | 메서드 이름과 인자 (계약) | 구현 기술 |
| S3 어댑터 | boto3, 버킷 이름, 리전 | 이 이미지가 왜 필요한지 |
7. 리버스 파이프라인 — 영수증 가계부
7.1 방향이 거꾸로인 파이프라인
지금까지 우리가 만든 흐름은 전부 정방향이었습니다. 사용자가 화면에서 입력 → 라우터 → 유스케이스 → 저장소 → DB. 바깥에서 안으로 들어갑니다.
8월 4일의 과제는 역방향입니다.
[플러터] 영수증 촬영
→ [S3] 이미지 저장
→ [웹 프론트] 가계부 화면 진입
→ S3의 이미지를 서버로 로드 ← 여기서부터 역방향
→ 서버에서 OCR로 텍스트 인식
→ 웹 화면에 표시
9주차에서 배운 스타 토폴로지 위에 그리면 이렇게 됩니다.
S3(아웃바운드) → 앱(OCR) → 인바운드 → 웹 으로 나가는 방향의 역순 흐름.
역방향이 까다로운 이유는 출발점이 사용자 요청이 아니라 저장소에 이미 있는 것이고, 데이터가 나가면서 줄어드는 게 아니라 늘어나기 때문입니다(이미지 → 텍스트 → 구조화된 항목).
⭐ 여기가 3주차 동기/비동기 축이 실무에서 꼭 필요해지는 자리입니다. OCR은 시간이 걸립니다. 화면에 들어올 때마다 동기로 돌리면 사용자가 몇 초를 기다립니다. 실무에서는 업로드 시점에 미리 OCR을 걸어 결과를 저장해두고, 화면은 결과만 읽습니다. "언제 계산할 것인가"를 옮기는 것 — 5주차에서 배운 CQRS(읽기 모델과 쓰기 모델 분리) 의 씨앗입니다.
7.2 OCR은 어느 축에 꽂히는가
OCR(Optical Character Recognition) — 이미지 속 글자를 텍스트로 바꾸는 기술입니다.
10주차의 구문론 ↔ 의미론 축으로 보면 OCR은 구문론 쪽입니다.
"이 픽셀 뭉치는 7이라는 글자다"까지만 합니다. 그것이 금액인지 날짜인지는 모릅니다.
의미를 붙이는 것은 그다음 층(LLM 또는 규칙)의 일입니다.
[이미지] --OCR(구문)--> ["2026-08-04 아메리카노 4,500"] --LLM(의미)--> {date, item, amount}
이 두 층을 한 덩어리로 뭉쳐서 "AI가 영수증을 읽는다"고 부르면, 정확도가 낮을 때 어디를 고쳐야 할지 알 수 없습니다. 하네스 엔지니어링에서 배운 원칙 그대로입니다 — 실패를 모델 탓으로 묶지 말고 먼저 분류하라. 글자를 잘못 읽었으면 OCR 문제, 글자는 맞는데 항목 분류가 틀렸으면 프롬프트·스킬 문제입니다.
8. 하네스 엔지니어링 심화 — 문서가 코드를 낳는다
8.1 DESIGN.md — 디자인도 하네스로
프론트엔드에서 스타일이 제각각이 되는 이유는 실력이 아니라 기준이 없어서입니다.
DESIGN.md 를 하네스로 삼아 이 문제를 해결합니다.
nextjs프로젝트에 적용하여 tailwindcss와 shadcn으로 스타일링 라이브러리를 통일- 색·간격·타이포·컴포넌트 규칙을 문서 한 장에 고정하고, 에이전트가 그 문서를 지키게 함
파울러의 분류로는 가이드(Guide) 입니다. 행동 전에 방향을 정하는 문서입니다.
8.2 CLAUDE.md, AGENTS.md — 팀의 하네스로 바꿔도 될까
8월 9일의 읽을거리 하나가 이 질문을 정면으로 던집니다(12절 참조). 개인이 쓰던 하네스 문서를 팀 표준으로 올릴 때 생기는 문제들입니다.
| 개인 하네스 | 팀 하네스 |
|---|---|
| 내 습관을 적음 | 합의된 규칙만 적음 |
| 틀리면 내가 고침 | 틀리면 모두가 영향 |
| 길어도 상관없음 | 길면 아무도 안 읽고 토큰만 먹음 |
| 근거 없이 적어도 됨 | 각 줄이 실제 나쁜 행동에서 나와야 함 |
⭐ 하시모토의 원칙을 다시 꺼냅니다 — "AGENTS.md의 각 줄은 실제로 있었던 나쁜 행동에서 나온 것이어야 한다." 미리 상상해서 규칙을 쌓으면 문서만 길어집니다. 사고가 나면 한 줄 추가한다. 이것이 하네스를 관리하는 유일하게 지속 가능한 방법입니다.
8.3 지킬(Jekyll) — 세션 사이를 잇는 장치
8월 20일, fin-taylor/CLAUDE.md 에 전략을 반영하면서 규칙 하나를 정합니다.
다음 세션에서도 동일한 결과가 이어지도록, 프로젝트 진행사항을 지킬에 기록한다.
지킬(Jekyll) 은 마크다운 파일을 정적 웹사이트로 만들어주는 도구입니다. GitHub Pages의 기본 엔진이기도 합니다. 여기서는 블로그가 아니라 개발 로그 겸 산출물 저장소로 씁니다. Ubuntu에서 세팅했습니다.
이 규칙이 왜 중요한가:
| 문제 | 지킬 기록이 해결하는 것 |
|---|---|
| 에이전트 세션이 끊기면 맥락이 사라짐 | 다음 세션이 읽을 인수인계 문서가 남음 |
| 같은 실패를 반복함 | 실패도 기록되므로 다시 밟지 않음 |
| 팀원이 뭘 했는지 모름 | 개발 로그가 곧 공유 |
| 산출물이 흩어짐 | 한 사이트에 모임 |
하네스 이론의 인수인계 5항목 — 목표 / 완료 / 실패 / 위험 / 다음 행동 — 을 기록할 자리가 바로 여기입니다.
⚠️ 파일이 늘어나면 구조부터 정합니다. 8월 24일에 지킬 md 파일이 계속 늘어나자,
jekyll을 지킬 폴더의 루트로 정하고 폴더 깊이를 2로 정리했습니다. 깊이 2 규칙은 사람에게도 에이전트에게도 좋습니다. 경로가 짧아 참조가 쉽고, 어디에 넣을지 고민이 줄어듭니다.
8.4 ⭐ RFP 하네스 4원칙
8월 21일, 공공 SW사업 RFP 가이드라인을 반영해 .claude/rfp-harness.md 를 만듭니다.
여기에 적힌 Claude Code 준수 규칙 4가지는 이 부트캠프의 하네스 논의가 도달한 가장 구체적인 형태입니다.
| # | 원칙 | 뜻 | 나쁜 예 → 좋은 예 |
|---|---|---|---|
| 1 | 명확성 | 모호한 표현 금지 | "빠르게 처리" → "Latency −40%, Stream 시작 1.5초 이내" |
| 2 | 원자성 | 요구사항 ID 단위로 모듈화 | "RAG 만들어줘" → SFR-002 하나만 |
| 3 | 추적성 | 모든 코드·테스트·설정 파일 상단에 요구사항 ID 주석 | 파일을 열면 어느 요구사항 때문에 존재하는지 즉시 보임 |
| 4 | 검증성 | 요구사항별 Acceptance Criteria 와 단위/통합 테스트를 동반 생성 | "잘 되면 됨" → "Recall@5 92% 이상" |
요구사항 예시
| ID | 요구사항 | 수용 기준 |
|---|---|---|
| SFR-001 | DART(XML/HTML)·SEC(10-K) 복합 표 파싱 | 구조 복원율 95% 이상 |
| SFR-002 | Dense + BM25 앙상블 및 Cross-Encoder Reranking | Recall@5 92% 이상 |
| SFR-003 | 근거 원문 자동 하이라이팅 | — |
| SFR-004 | 멀티턴 금융 QA | — |
실행 순서
Task 1 pnpm workspace 모노레포 템플릿 생성
Task 2 services/rag/retriever.py 에 RRF 기반 HybridRetriever + 테스트
Task 3 split-view UI
사용법은 이렇게 한 줄입니다.
claude "RFP_HARNESS.md를 읽고 [Task 1]을 먼저 수행해서 프로젝트 템플릿을 만들어줘."
⭐ 이 4원칙은 새로운 것이 아닙니다. 명확성은 "모호한 요청은 계획 세션과 실행 세션을 분리하라"의 문서판, 원자성은 "세션을 작고 명확한 단위로 쪼개라"의 문서판, 추적성은 관측성(Observability)의 문서판, 검증성은 "에이전트에게 스스로 검증할 수단을 주면 스스로 고친다"의 문서판입니다.
흥미로운 것은 이 네 단어가 공공 SW사업 RFP 가이드라인에서 왔다는 점입니다. AI 시대에 새로 발명된 것이 아니라, 발주와 검수라는 오래된 문제에서 이미 정립돼 있던 것입니다. 좋은 요구사항 문서의 조건과 좋은 하네스의 조건이 같습니다. 사람에게 시키든 에이전트에게 시키든 마찬가지이기 때문입니다.
8.5 이 부트캠프의 일관된 순서
① 하네스 md 작성 (코드 금지)
② md 검토 · 경계 확정
③ md를 참조시켜 코드 생성
④ 생성 코드를 클린 코드 관점에서 직접 검수 · 재편집
⑤ 결과와 실패를 지킬(개발 로그)에 기록
⑥ 그 기록이 다음 세션의 입력이 됨
④번을 빠뜨리면 안 됩니다. 7주차에서 확인했듯, 에이전트가 만든 DIP 코드가 절반만 DIP인 경우가 흔합니다. 생성은 자동화하되 검수는 자동화하지 않습니다. 그것이 지금 시점의 현실적인 경계선입니다.
9. 팀 프로젝트 — SI 산출물과 스크럼
9.1 가상 클라이언트 요구사항을 채용 공고에서 뽑는다
팀 프로젝트 주제를 정할 때 기준이 "만들고 싶은 것"이 아니라 "채용 공고의 키워드" 였습니다.
| 항목 | 내용 |
|---|---|
| 도메인 키워드 | 금융 도메인 + 에이전트/MCP + 생성형 미디어(음성·영상) + 차세대 인터페이스 |
| 자격요건 | AI 네이티브 빌더 역량(Claude Code · Cursor), MCP · Function Calling · RAG 감각, 문제 정의력과 Taste, Python · TypeScript · 클라우드 전제 |
⭐ 이 순서가 중요합니다. 포트폴리오를 만든 뒤 맞는 회사를 찾는 것이 아니라, 가고 싶은 자리의 요구사항을 먼저 읽고 그것을 만드는 순서입니다. 10절의 포트폴리오 리프레이밍 전략과 같은 사고방식입니다.
9.2 선정 주제
"멀티 에이전트 기반 금융 리포트 & 미디어 브리핑 자동화 플랫폼" 을 강사 데모 버전으로 구현하기로 결정했습니다.
| 층 | 기술 |
|---|---|
| 데이터 수집 | MCP / Function Calling 으로 금융 API 연동 (한국투자증권, Alpha Vantage) |
| 처리 | LangGraph 멀티에이전트 — 뉴스 수집 → 팩트체크 → 대본 작성 |
| 미디어 생성 | TTS(ElevenLabs) + MoviePy / Remotion 으로 차트 애니메이션 숏폼 MP4 자동 생성 |
| 인프라 | Docker 백엔드를 온프레미스 Ubuntu에 올리고 CI/CD로 Vercel · Cloudflare Pages 연동 |
| 저장소 | Vector DB(ChromaDB / Qdrant) + PostgreSQL |
💡 3단계 멀티에이전트가 왜 3단계인가 — 수집·검증·생성을 한 에이전트에게 맡기면 팩트체크 실패와 문장 품질 실패를 구분할 수 없습니다. 나누면 어느 단계에서 틀렸는지 알 수 있습니다. 하네스 이론의 "실패를 먼저 4분류하라(모델/하네스/컨텍스트/스킬)" 가 워크플로우 설계로 내려온 것입니다. 그리고 이것 역시 하나 ↔ 여럿 축입니다. 쪼갠 대가는 단계 간 전달 비용입니다.
9.3 SI 표준 산출물 작성 순서
① 프로젝트 개요 · 추진 단계
기획 → 아키텍처 → 미디어 파이프라인 PoC → 인프라/CI-CD → 테스트·QA
② 서비스 아키텍처 및 데이터 흐름도
③ 기능 요구사항 정의서 (표 형식)
기능 요구사항 정의서 예시
| ID | 기능 요구사항 |
|---|---|
| FR-01 | MCP 금융 데이터 수집 |
| FR-02 | 3단계 멀티에이전트 워크플로우 |
| FR-03 | 방송용 숏폼 자동 렌더링 |
PoC(Proof of Concept) — "이게 되긴 되는가"를 최소 규모로 먼저 확인하는 단계입니다. 미디어 파이프라인처럼 처음 해보는 것을 먼저 PoC로 세우는 순서가 스파이럴(나선형) 방법론의 핵심입니다. 가장 위험한 것을 가장 먼저 확인합니다.
9.4 공공 SI 가상 시나리오와 스크럼
| 항목 | 내용 |
|---|---|
| 사업명 | "국가 금융데이터 미디어 자동화 및 차세대 대민 서비스 플랫폼 구축" |
| 발주처 | 조달청 |
| 수행사 | 4인 팀, 애자일 스크럼 |
| 반영 절차 | RFP 하달부터 납품·검수까지의 통제 절차와 감리 과정 |
| 개발 기간 | 2026-08-20 ~ 10-27 |
지킬 개발제안서 구성
- 1페이지 — 사업명
- 2페이지 — 목차 (개발자 4명, 개발기간)
- "단계별 개발일정" 페이지 — 애자일 스크럼 칸반 차트
- 역할 분담: PM / 플러터(앱) / 파이프라인 / 에이전트
- "스프린트 1주차 작업"을 클릭하면 일자별 진행사항 테이블로 이동
⚠️ 여러 명이 같은 지킬을 쓰면 충돌합니다. 3인 팀에서 스크럼 백로그를 지킬에 기록할 때, 칸반을 추가해 사용자별로 스케줄러를 구분했습니다. 이것도 판별 축입니다. 하나의 문서에 뭉치면 충돌하고, 사람별로 쪼개면 관리 대상이 늘어납니다. Git 브랜치 전략과 정확히 같은 문제이고, 같은 해법입니다.
9.5 인프라 준비 — RDS와 .env 규칙
스파이럴 개발방법론에 따라, DB URL을 먼저 확보하기 위해 AWS RDS를 구성했습니다.
| 항목 | 값 |
|---|---|
| 엔진 | Aurora PostgreSQL (pgvector 사용) |
| 변경한 설정 | 용량 4, 백업기간 7 — 나머지는 기본값 |
| 복사할 엔드포인트 | writer (읽기 전용이 아닌 쓰기 엔드포인트) |
# .env — 실제 값은 절대 커밋하지 않습니다
RDS_HOST=<클러스터명>.cluster-<식별자>.<리전>.rds.amazonaws.com
RDS_READER_HOST=<클러스터명>.cluster-ro-<식별자>.<리전>.rds.amazonaws.com
RDS_PORT=5432
RDS_DB_NAME=CHANGE_ME
RDS_USER=CHANGE_ME
RDS_PASSWORD=CHANGE_ME # 운영에서는 IAM 인증 / Secrets Manager 권장
AWS_REGION=ap-northeast-2
AWS_ACCESS_KEY_ID= # EC2/ECS/Lambda 에서는 비우고 IAM 역할 사용
AWS_SECRET_ACCESS_KEY=
.env 취급 규칙 세 줄
.env.example에는 키 이름만 공유하고 실제 값은 금지합니다.- 받는 사람은
cp .env.example .env로 복사한 뒤 값을 채웁니다. .env·.env.local은.gitignore에 먼저 등록합니다.
⭐
RDS_HOST와RDS_READER_HOST가 왜 따로 있는가 Aurora는 쓰기용 writer 엔드포인트와 읽기 전용 reader 엔드포인트(cluster-ro-포함)를 따로 줍니다. 5주차의 읽기 ↔ 쓰기 분리(CQRS) 축이 클라우드 DB 제품에 그대로 구현돼 있는 것입니다. 읽기 부하가 커지면 reader만 늘립니다. 엔드포인트를 잘못 복사하면 쓰기가 실패하니 writer를 확인하세요.
9.6 예산과 진행 현황
| 항목 | 내용 |
|---|---|
| 팀 AWS 크레딧 | $400 (10/27 발표까지) |
| 개인 AWS 크레딧 | $120 (2개월) |
| 준비 완료 | RDS · EC2 · S3 |
| 다음 단계 | Harness까지 인프라 준비 후 FastAPI · Next 프레임워크 진행 |
⚠️ 크레딧은 유한합니다. 유휴 상태에서도 과금되는 것들 — Provisioned Throughput, 파인튜닝/커스텀 모델 호스팅, Knowledge Base + OpenSearch Serverless 벡터 스토어 — 은 생성 자체를 하지 않습니다. 만들어두고 안 쓰면 된다는 생각이 요금 폭탄의 시작입니다.
10. 커리어 — 정량화가 사람을 뽑히게 한다
10.1 이전 기수 취업생의 개인 프로젝트 해부
AI 회사에 취업한 이전 기수 수강생의 이력서 4페이지짜리 개인 프로젝트를 통째로 뜯어봅니다. "이 정도면 붙는다"의 실물 기준입니다.
프로젝트: HR Insight (Success DNA) — 2026.02 ~ 03
| 항목 | 내용 |
|---|---|
| 사용 기술 | EXAONE 3.5 7.8B · Llama 3.2 3B · Gemini · PyTorch · PEFT · QLoRA · Unsloth · LangChain · LangGraph · FastMCP · BGE-M3 · FAISS · pgvector · FastAPI · Spring Boot · PWA · AWS EC2 |
| 소개 | 비정형 업무 데이터(이력서·메일·회의록) 통합 HCM 플랫폼 / ISO 30414 기반 역량 정량화와 채용 이후 역량 발현·성장 추적 |
아키텍처 설계 — 이 교재에서 배운 이름들이 그대로 나옵니다.
| 설계 | 내용 | 배운 곳 |
|---|---|---|
| Polyglot | Spring Boot(인증 게이트웨이) + FastAPI(AI 연산)로 업무 API와 AI 로직 분리 | 5주차 폴리글랏 |
| Hexagonal(라이트) | domain · application · infrastructure 레이어 분리 | 5·6주차 |
| Hub-and-Spoke Star 토폴로지 | 중앙 허브는 라우팅만, 무거운 모델은 Spoke에서 실행 | 9주차 |
주요 기능
- 멀티 포맷 문서 파싱 → 텍스트 레이어 추출 + 스캔본 OCR → LLM 의미 분석 → 5대 핵심 역량 정량화(리더십·기술력·창의성·협업·적응력)
- 외부 메일 수신 → LLaMA LoRA 스팸 분류, 성과 데이터 통합 → 초기(이력서) 대비 현재 성장 추이 도출
- SSE 스트리밍 채팅형 인사 조회 — LangGraph 기반 RAG 에이전트, 12개 시나리오 Tool Calling 검증(평균 성공률 0.95)
- 역량 온톨로지 — 직무역량 원천(O*NET · NCS 등) 11.8만 건 → BGE-M3 임베딩 → FAISS K-Means · UMAP → 파인튜닝 EXAONE 자동 라벨링
10.2 문제해결 항목이 진짜 본체다
이력서에서 면접관이 실제로 파고드는 곳은 기술 나열이 아니라 "막혔던 것을 어떻게 뚫었는가" 입니다.
| 문제 | 해결 | 결과 |
|---|---|---|
| EXAONE 학습이 느림 | Transformers + PEFT + bitsandbytes 4bit 양자화 | 속도 약 2배 |
| LLaMA 학습 최적화 | Unsloth 적용 | 속도 2.5~3배, 메모리 개선 |
| GPU 파인튜닝 모델을 CPU 서버에 서빙 | llama.cpp — tokenizer 손상은 수동 패치, OOM은 n_ctx 축소 | 서빙 성공 |
| Neon 스토리지 한도로 11.8만 건 적재 불가 · SSL 타임아웃 | 검색 계층 이원화 — 정적·대용량은 FAISS 인메모리, 동적·트랜잭션은 HNSW-FlatIP | 인덱스 빌드 ~12초 |
⭐ 마지막 줄을 보세요. "Neon 용량이 부족해서 못 했다"로 끝나지 않았습니다. 데이터의 성격에 따라 저장소를 둘로 갈랐습니다. 정적이고 큰 것은 메모리에, 동적이고 트랜잭션이 필요한 것은 DB에. 3주차의 디스크 ↔ 메모리 축, 7주차의 정적(Dataset) ↔ 동적(Database) 축이 실무 제약 앞에서 설계 결정으로 쓰인 사례입니다. 이것이 "축을 배운다"의 실제 효용입니다.
10.3 면접 포인트 — 말이 아니라 숫자
두 가지 사례가 있습니다.
- "이거 누가 했냐" 는 질문을 받아 따로 면접 기회를 얻은 케이스.
- 비용 절약을 말로만 하지 않고, LangSmith로 초기 비용 · 개선 비용 · 지연시간 개선 등 추적 지표를 수치화·정량화한 경험이 별도 면접 기회로 이어진 케이스.
⭐ "비용을 줄였습니다"는 아무 정보도 아닙니다. "초기 호출당 $0.012 → 개선 후 $0.0077, 평균 지연 3.1초 → 1.8초, 측정은 LangSmith 트레이스 500건 기준" 이 한 줄이 면접을 만듭니다.
하네스 이론의 TRACE + FEEDBACK 이 여기서 회수됩니다. "Trace만으로는 학습이 안 된다. 무엇이 일어났는지(TRACE)와 결과가 좋았는지(FEEDBACK)가 연결돼야 다음 실행이 개선된다." 측정 도구를 붙여두지 않으면, 개선했다는 사실 자체를 증명할 수 없습니다.
10.4 채용 공고 하나를 끝까지 읽기
LLM & RAG 엔지니어 공고를 예로 전형과 우대사항을 분해합니다.
| 항목 | 내용 |
|---|---|
| 지원 방법 | 채용 메일 주소로 메일 지원 필수 (지원 경로를 안 지키면 서류를 보지도 않습니다) |
| 전형 | 서류 → 1차 화상 → 2차 기술면접 → 최종 |
| 우대사항 ① | RAG 서비스 운영 경험 |
| 우대사항 ② | 금융 공시(SEC / DART) 처리 경험 |
| 우대사항 ③ | 검색 품질 정량 지표(recall@k, mAP, nDCG) 개선 경험 |
| 우대사항 ④ | 표·각주·이미지 구조로 인한 RAG 오류를 데이터 설계로 해결한 경험 |
⚠️ 우대사항 ④를 다시 읽으세요. "RAG를 써봤다"가 아니라 "RAG가 틀리는 원인을 데이터 설계로 고쳤다" 입니다. 표가 들어간 PDF를 그냥 청킹하면 숫자와 헤더가 분리돼 완전히 틀린 답이 나옵니다. 모델을 바꾸는 게 아니라 데이터를 구조화해서 고칩니다. 이것이 하네스 이론의 "실패 원인을 모델/하네스/컨텍스트/스킬로 먼저 분류하라" 의 채용 공고 판본입니다.
검색 품질 지표 사전
| 지표 | 읽는 법 | 무엇을 재는가 |
|---|---|---|
| recall@k | 리콜 앳 케이 | 상위 k개 안에 정답이 들어 있었는가의 비율 |
| mAP | mean Average Precision | 정답들이 얼마나 앞쪽에 배치됐는지의 평균 |
| nDCG | Normalized Discounted Cumulative Gain | 순위가 뒤로 갈수록 점수를 깎아 랭킹 품질을 재는 지표 |
3주차에서 배운 정확도 · 정밀도 · 재현율 · F1 이 분류 문제의 지표라면, 이 셋은 검색·랭킹 문제의 지표입니다. 같은 자리에 꽂히는 형제 개념입니다.
10.5 포트폴리오 리프레이밍 — 제목부터 바꾼다
SI형 제목 대신 문제 해결형 제목으로.
| ❌ SI형 제목 | ⭕ 문제 해결형 제목 |
|---|---|
| "금융 문서 RAG 시스템 구축" | "금융 공시(DART/SEC) 복합 문서 구조화 및 Hybrid RAG 파이프라인 구축 (Latency −40%, Recall@5 92%)" |
제목이 바뀌면 본문 구성도 바뀝니다.
| 구성 | 내용 |
|---|---|
| 문제 | 비구조화 데이터 파싱 — Hierarchical Tree 로 문서 구조 복원 |
| 설계 | Document Structure-Aware Chunking · Parent-Document Retriever · Metadata Filtering |
| 검색 | Dense(Vector DB) + Sparse(BM25) 하이브리드 + Cross-Encoder Re-ranking |
| 평가 | Ragas / TruLens 기반 정량 Evaluation |
| 한계 | 한계점과 향후 최적화를 명시 |
⭐ 마지막 줄이 가장 중요합니다. 한계를 적으면 감점될 것 같지만 반대입니다. 한계를 아는 사람만이 다음에 무엇을 할지 압니다. 면접에서 가장 좋은 질문거리가 되기도 합니다. 하네스 이론의 인수인계 5항목(목표/완료/실패/위험/다음 행동) 을 포트폴리오에 적용하면 정확히 이 구성이 됩니다.
하이브리드 검색은 10주차 축 1의 회수입니다.
| 검색 방식 | 축 | 잘하는 것 |
|---|---|---|
| Sparse (BM25) | 구문론 | 정확한 단어·고유명사·종목코드 |
| Dense (Vector) | 의미론 | 다르게 표현된 같은 뜻 |
| 하이브리드 + RRF | 둘 다 | 한쪽이 놓친 것을 다른 쪽이 건짐 |
| Cross-Encoder Re-ranking | 의미론(정밀) | 후보를 다시 정독해 순서를 바로잡음 |
11. 실습 — 이번 달에 손으로 한 것
(S3 + IAM 역할 실습 절차는 6.4절에 순서대로 정리해 두었습니다. 그대로 따라 하세요.)
11.1 RDS(Aurora PostgreSQL) 생성과 연결 (8/21)
RDS 콘솔 → 데이터베이스 생성 → Aurora (PostgreSQL Compatible)
→ 용량: 4
→ 백업기간: 7
→ 나머지는 기본값
생성 후 → 연결 & 보안 탭 → 엔드포인트 중 [writer] 복사
cp .env.example .env # 값이 아니라 키 이름만 공유받아 채운다
echo ".env" >> .gitignore
echo ".env.local" >> .gitignore
11.2 지킬(Jekyll) 개발 로그 (8/20~8/24)
# Ubuntu
sudo apt update && sudo apt install -y ruby-full build-essential zlib1g-dev
gem install jekyll bundler
jekyll new jekyll # 폴더 루트를 'jekyll' 로 고정
cd jekyll
bundle exec jekyll serve # http://127.0.0.1:4000
정리 규칙
- 지킬 폴더 루트를
jekyll로 고정 - 폴더 깊이는 2까지만 — 그 이상 내려가지 않음
- 개발 로그에 남길 5항목: 목표 / 완료 / 실패 / 위험 / 다음 행동
11.3 RFP 하네스 사용 (8/21)
# .claude/rfp-harness.md 를 만든 뒤
claude "RFP_HARNESS.md를 읽고 [Task 1]을 먼저 수행해서 프로젝트 템플릿을 만들어줘."
Task 1 pnpm workspace 모노레포 템플릿
Task 2 services/rag/retriever.py — RRF 기반 HybridRetriever + 테스트
Task 3 split-view UI
11.4 컨테이너 정리와 Podman 대응
# 디스크가 찼을 때 (EC2)
docker rm -f $(docker ps -aq)
docker image prune -a -f
# Podman으로 같은 일
podman rm -f $(podman ps -aq)
podman image prune -a -f
# Podman으로 Pod 만들고 쿠버네티스 YAML 뽑기
podman pod create --name myapp -p 8000:8000
podman run -d --pod myapp --name api my-fastapi:latest
podman generate kube myapp > myapp-pod.yaml
11.5 CI 파이프라인 붙이기
mkdir -p .github/workflows
# 4.8절의 ci.yml 을 저장하고 push
git add .github/workflows/ci.yml
git commit -m "ci: 린트와 테스트 자동화"
git push
# → GitHub 저장소의 Actions 탭에서 실행 결과 확인
⚠️ 처음 붙이면 대부분 빨간 X가 뜹니다. 정상입니다. 로컬에만 있던 의존성, 하드코딩된 경로,
.env에 의존하던 코드가 한꺼번에 드러납니다. 그것이 CI의 존재 이유입니다. "내 컴퓨터에서는 되는데"를 없애는 것.
12. 이 달의 읽을거리와 그 맥락
| 자료 | 링크 | 왜 이 달에 나왔는가 |
|---|---|---|
| 플러터 카카오 로그인 공식 문서 | 🔗 https://developers.kakao.com/docs/ko/kakaologin/flutter | 웹에 붙였던 OAuth를 앱에도 붙이는 주간. 공식 문서가 유일하게 정확한 기준입니다 |
| 플러터 입문 교재 | 🔗 https://wikidocs.net/book/14188 | 새 언어(Dart)와 새 프레임워크를 짧게 훑기 위한 출발점 |
DESIGN.md 를 클로드에서 하네스로 쓰기 | 🔗 https://wikidocs.net/366539 | 스타일 통일(tailwindcss + shadcn)을 문서로 강제하는 방법. 파울러의 "가이드" |
| 우리 팀의 CLAUDE.md, AGENTS.md로 바꿔도 될까 | 🔗 https://yozm.wishket.com/magazine/detail/3874/ | 개인 하네스를 팀 표준으로 올릴 때의 문제. 팀 프로젝트 직전 주에 필요한 논의 |
| 면접·포트폴리오 참고 글 | 🔗 https://wikidocs.net/338723 | "정량화된 개선 경험"이 면접을 만든다는 사례의 근거 |
| 팀 프로젝트 샘플 저장소 | 🔗 https://github.com/langtailor/-1046-joo-stock | 지킬까지 처리 완료된 산출물 실물. 구조를 그대로 참고 |
| 지킬 테마 모음 | 🔗 https://jekyllthemes.io/ | 개발 로그 사이트의 외형을 빠르게 정하기 위해 |
| 해커톤 지킬 참고 사이트 | 🔗 https://dev.life-tutorial.com/ | 실제 팀이 만든 개발 로그의 완성 형태 |
| AI 챔피언십 | 🔗 https://event.wanted.co.kr/ai-championship/2026 | 팀 프로젝트 내용 그대로 지원 가능. 만든 것을 한 번 더 쓰는 경로 |
| 메타 디자인 레퍼런스 | 🔗 https://astryx.atmeta.com/ | 미디어 브리핑 UI의 시각 레퍼런스 |
| 와이어프레임 도구 | 🔗 https://balsamiq.com/ · 🔗 https://claude.ai/design | 코드 전에 화면을 먼저 그리기 위해 |
💡 읽을거리가 이 달에 유난히 "취업"으로 기울어 있는 이유 — 8월은 부트캠프의 마지막 구간이고, 팀 프로젝트가 곧 포트폴리오이며, 포트폴리오가 곧 지원서이기 때문입니다. 만드는 일과 파는 일이 같은 작업이 되는 시점입니다.
13. 전 과정 되돌아보기
여기서부터가 이 책의 마지막 절입니다.
1주차 0절에서 이렇게 썼습니다.
"새 용어를 만나면 비유를 찾기 전에 아래 축 중 어디에 꽂히는지부터 정하세요. 비유부터 잡으면 경계가 흐려집니다. 축을 먼저 잡으면 아직 안 배운 것도 추론됩니다."
열다섯 장 동안 같은 문장을 반복했습니다. 이제 그 약속을 정산합니다. 축을 먼저 잡았기 때문에 아직 안 배운 것이 추론되었는가? 표로 확인합니다.
13.1 판별 축 총정리
| 축 | 처음 나온 곳 | 이후 반복된 곳 | 이 장에서 |
|---|---|---|---|
| ① 디스크 ↔ 메모리 | 3주차 축 1 — 클래스 ↔ 인스턴스 / 4P(프로덕트·프로젝트·프로그램·프로세스) | 3주차 SAVE·LOAD(직렬화) · 메모리 3영역 / 7주차 Dataset(정적) ↔ Database(동적) / 8주차 축 2 이미지 ↔ 컨테이너 / 11~14주차 로컬 모델 파일 ↔ 로드된 모델 | 커널의 메모리 관리 · 가상메모리 · 스왑 (1.3) — 커널이 이 경계를 일부러 흐리는 유일한 지점 / 데몬 상주 ↔ Fork-Exec (2.3) / 캐싱 (3.2) |
| ② 추상 ↔ 구상 | 1주차 축 5 — 자연어(Soul) ↔ 기계어(Body) | 3주차 패턴(추상) ↔ 아키텍처(구상) · 전략 패턴 / 5주차 축 1 Port ↔ Adapter (이 축이 설계 원칙이 되는 지점) / 6주차 축 1 인터페이스 ↔ 구현체 / 7주차 LSP — 치환 가능성 / 8주차 축 4 0 ↔ null | 시스템 콜 = 커널이 공개한 추상 인터페이스 (1.5) / 가상 주소 ↔ 물리 주소 (1.3) / OCI 표준 ↔ Docker·Podman (2.1) / 아웃바운드 포트 ↔ S3 어댑터 (6.5) |
| ③ 속성 ↔ 기능 | 3주차 축 2 — 객체 = 속성 + 기능 / 개체 = 객체 − 기능 / 함수 = 객체 − 속성 | 3주차 필드 ↔ 메서드 / 4주차 축 3 괄호가 있는가(data.message ↔ alert()) / 4주차 D-M-V-C / 7주차 축 1 데이터 객체(LSP) ↔ 제어 컴포넌트(OCP) | .env.example(키 이름만) ↔ .env(값) (9.5) / PCB(속성) ↔ 스케줄러(기능) (1.3) / 가이드(규칙=속성) ↔ 센서(실행=기능) (4.7) |
| ④ 로컬 ↔ 원격 | 1주차 축 2 — Git ↔ GitHub / 내 폴더 ↔ 도메인 | 2주차 축 5 SAVE·LOAD ↔ 업로드·다운로드 / 9주차 토폴로지 / 11~14주차 WSL · SSH · EC2 · Cloudflare Tunnel · 온프레미스 ↔ 클라우드 | 플러터 앱 ↔ S3 (6) / 온프렘(개발) ↔ EC2(배포) (5.1) / 포워드 프록시 ↔ 리버스 프록시 (3.3) — 로컬·원격 축 위에 "누구를 대리하는가"가 얹힘 |
| ⑤ 하나 ↔ 여럿 (모놀리식 ↔ MSA) | 3주차 축 5 — 모놀리식 ↔ MSA / 모노레포 ↔ 멀티레포 | 5주차 축 3 읽기 ↔ 쓰기 분리(CQRS) / 6주차 축 5 퍼사드 ↔ 책임 연쇄 / 9주차 축 2·3·4 스타 ↔ 메시 · SPOF / 11~14주차 스케일아웃 · 컨테이너 분리 · 멀티에이전트 | 모놀리식 커널 ↔ 마이크로커널 (1.6) / dockerd ↔ Podman Fork-Exec (2.3) / Pod (2.5) / 3단계 멀티에이전트 (9.2) |
| ⑥ 동기 ↔ 비동기 | 3주차 축 4 — Sync ↔ Async ("속도가 아니라 기다림") | 3주차 async def + Neon 연동 / 6·7주차 CPU-bound는 def, I/O-bound만 async def / 8주차 큐·재시도 | 커널의 스케줄링 (1.3) — 시간 분할의 원형 / 시스템 콜 대기 구간이 곧 async가 효과를 내는 구간 (1.5) / OCR을 언제 계산할 것인가 (7.1) |
| ⑦ 무상태 ↔ 상태 | 4주차 축 1 — 함수 ↔ 클래스 / HTML ↔ State / 통신 구간 ↔ 양쪽 끝 | 8주차 축 1 무상태 ↔ 멱등성(다른 질문임) / 10주차 축 3 화살표 함수 ↔ 클로저 / 11~14주차 JWT · 세션 · 컨텍스트 윈도우 | Redis 모바일 토큰 컬럼 (5.2) — 서버는 무상태, 상태는 밖으로 / 데몬(상태 보유) ↔ Fork-Exec(무상태) (2.3) / GitOps — Git이 곧 상태의 진실 (4.5) |
| ⑧ 구문론 ↔ 의미론 | 10주차 축 1 — 키워드 검색 ↔ 벡터 검색 / <div style> ↔ <h1> | 10주차 축 2 규칙 ↔ 정책 / 10주차 축 4 벡터 DB ↔ 그래프 DB / 11~14주차 임베딩 · RAG · 온톨로지 | OCR(구문) → LLM(의미) (7.2) / BM25(Sparse·구문) + Dense(의미) 하이브리드 (10.5) / RFP 하네스의 명확성(구문) ↔ 검증성·Acceptance Criteria(의미) (8.4) |
⭐ 이 표의 오른쪽 끝 열을 세로로 읽어보세요. 여덟 축이 전부 이번 장에서 한 번 이상 다시 나왔습니다. 커널과 컨테이너 엔진과 프록시와 파이프라인은 이 교재에서 처음 배우는 주제였는데, 그것을 이해하는 데 필요한 축은 하나도 새로 만들지 않았습니다.
13.2 같은 축, 아홉 개의 배율 — 축 ⑤의 전체 지도
가장 자주 반복된 축 ⑤(하나 ↔ 여럿) 하나만 놓고, 이 교재가 다룬 모든 배율을 세로로 세워봅니다.
| 배율 | 하나로 뭉침 (0) | 여럿으로 쪼갬 (1) | 쪼갠 대가 | 배운 곳 |
|---|---|---|---|---|
| CPU 권한 | 전부 Ring 0에서 | 사용자·커널 공간 분리 | 시스템 콜 모드 전환 비용 | 15주차 1.4 |
| OS 커널 | 모놀리식 커널 (Linux) | 마이크로커널 (QNX·L4) | IPC 메시지 비용 | 15주차 1.6 |
| 컨테이너 엔진 | dockerd 데몬 | Podman Fork-Exec | 생태계·GUI 도구 부족 | 15주차 2.3 |
| 컨테이너 묶음 | 컨테이너 하나 | Pod (함께 살고 함께 죽음) | 경계 결정의 어려움 | 15주차 2.5 |
| 코드 내부 | 퍼사드 (창구 하나) | 책임 연쇄 (체인) | 흐름 추적 곤란 | 6주차 |
| 데이터 접근 | 하나의 모델 | CQRS (읽기·쓰기 분리) | 일관성 관리 | 5주차 · 15주차 9.5 |
| 애플리케이션 | 모놀리식 | MSA | 네트워크·분산 트랜잭션 | 3주차 |
| 저장소 | 모노레포 | 멀티레포 | 버전 정합·CI 중복 | 3주차 |
| 네트워크 | 스타 (허브) | 메시 | 허브는 SPOF / 연결 수 폭증 | 9주차 |
| 검색 | 단일 리트리버 | Dense + Sparse 하이브리드 + RRF | 튜닝 대상 증가 | 10주차 · 15주차 10.5 |
| AI 실행 | 단일 에이전트 | 멀티에이전트 (수집→팩트체크→대본) | 단계 간 전달 비용 | 15주차 9.2 |
| 팀 | 한 사람이 전부 | 스크럼 역할 분담 | 동기화·문서 비용 | 15주차 9.4 |
| 문서 | 지킬 하나에 전부 | 사용자별 칸반 분리 | 파일 수 증가 | 15주차 9.4 |
열세 줄이 전부 같은 한 문장입니다.
뭉치면 빠르지만 같이 죽고, 쪼개면 안전하지만 통신 비용을 낸다. 그리고 어느 쪽도 발전된 형태가 아닙니다. 규모와 실패 비용이 답을 정합니다.
13.3 프랙탈 — 3주차의 결론을 여기서 닫습니다
3주차 13.4절에서 프랙탈 이론을 소개하며 이렇게 적었습니다.
"객체지향의 근본 구조가 프랙탈이라는 이야기와 연결됩니다. 같은 구조가 크기만 바꿔 반복되기 때문에, 하나를 제대로 이해하면 아직 안 배운 것도 추론됩니다."
프랙탈(Fractal) — 같은 구조가 크기(배율)를 바꿔 반복되는 도형·구조입니다. 해안선을 1km 단위로 봐도, 1m 단위로 봐도, 1cm 단위로 봐도 비슷하게 들쭉날쭉합니다.
13.2절의 표가 정확히 그 모양입니다.
배율 ↑
┌──────────────────────────────────────────────┐
│ 팀 조직 한 사람 ↔ 스크럼 역할 분담 │
│ AI 실행 단일 ↔ 멀티에이전트 │
│ 네트워크 스타 ↔ 메시 │
│ 애플리케이션 모놀리식 ↔ MSA │
│ 코드 내부 퍼사드 ↔ 책임 연쇄 │
│ 컨테이너 엔진 dockerd ↔ Podman │
│ OS 커널 모놀리식 ↔ 마이크로커널 │
│ CPU 권한 Ring 0 ↔ Ring 0 / Ring 3 │
└──────────────────────────────────────────────┘
배율 ↓ (0) (1)
맨 위(사람 조직)와 맨 아래(CPU 특권 레벨) 사이에 여덟 배율이 있는데, 판별 질문은 하나뿐입니다.
이 성질이 이 교재의 학습 전략 전체를 정당화합니다.
| 프랙탈이 아니라면 | 프랙탈이므로 |
|---|---|
| 새 기술마다 새로 외워야 함 | 축이 어디에 꽂히는지만 정하면 됨 |
| 배운 것과 새 것이 무관 | 새 것은 배운 것의 다른 배율 |
| 안 배운 것은 알 수 없음 | 안 배운 것도 추론 가능 |
⭐ 이 책을 덮은 뒤 새 기술을 만났을 때 할 일
- 이것은 무엇의 한 종류인가? (상위 범주)
- 형제 개념과 무엇으로 갈리는가? (종차 — 여덟 축 중 어디에 꽂히는가)
- 이건 아니다 — 반례는 무엇인가?
- 그다음에야 비유를 찾는다. (기억 보조용으로만)
쿠버네티스도, 서비스 메시도, 아직 이름도 없는 다음 도구도 이 네 질문으로 열립니다. 축이 여덟 개뿐이기 때문입니다.
13.4 미국식 분류가 결국 무엇이었나
1주차에서 시작한 또 하나의 원칙을 정산합니다.
| 한국식 (관계 기반) | 미국식 (분류 기반) | |
|---|---|---|
| 묶는 방식 | 원숭이와 바나나 | 사자와 원숭이 |
| 이해의 축 | 무엇과 이어지는가 | 무엇에 속하는가 |
| 결과 | 경계가 흐려짐 | 경계가 분명해짐 |
소프트웨어 개념은 전부 유(類)와 종차(種差) 정의법을 코드로 옮긴 것입니다. 그래서 이 교재는 늘 같은 형식을 썼습니다.
X — [상위 범주]인데, [종차]는 점에서 [형제 개념]과 구별된다.
그리고 그 종차 자리에 들어간 것이 여덟 개의 축이었습니다. 분류 우선 사고와 프랙탈 구조는 같은 것의 앞뒷면입니다. 분류가 되기 때문에 배율을 바꿔도 같은 질문이 통하고, 배율을 바꿔도 통하기 때문에 분류가 힘을 갖습니다.
13.5 번역어가 왜곡한 곳 모음
이 교재가 반복해서 바로잡은 한국어 번역 문제입니다. 마지막으로 모아둡니다.
| 단어 | ❌ 흔한 오해 | ⭕ 원 뜻 |
|---|---|---|
| Base (Database) | 기초 | 거점 · 저장소 |
| 개체 / 객체 | 같은 말의 오타 | Entity(존재의 단위) / Object(행위의 대상) — 완전히 다른 단어 |
| Kernel | 그냥 "핵심" | 껍질(Shell) 안의 알맹이 — 하드웨어 권한을 가진 유일한 영역 |
| Reverse Proxy | 반대 방향으로 흐름 | 대리하는 대상이 반대 (클라이언트 ↔ 서버) |
| CD | 하나의 개념 | Delivery(수동 승인) / Deployment(무개입) — 두 개념 |
| DIP | Dependency Injection | Dependency Inversion (의존 역전) |
| 비동기 | 더 빠름 | 한 건의 시간은 같음. 처리량이 늘어남 |
13.6 그래서 이제 무엇을 할 수 있는가
| 4월의 나 | 지금의 나 |
|---|---|
| 파이썬 스크립트를 실행함 | 스크립트를 서버로 바꾸고, 컨테이너에 넣고, 도메인에 붙임 |
| 코드가 되면 끝 | 아키텍처의 어느 칸에 놓을지 먼저 정함 |
| DB에 값을 넣음 | 개체·객체·DTO·ORM의 경계를 그으며 넣음 |
| AI에게 물어봄 | 하네스를 설계해 에이전트를 돌리고, 실패를 4분류함 |
| 배포가 두려움 | DNS → TLS → 프록시 → 앱 → DB 순으로 끊어서 진단함 |
| "잘 됐어요"라고 말함 | "Recall@5 92%, Latency −40%" 라고 말함 |
마지막 한 문장
이 책이 가르친 것은 도구가 아닙니다. 도구는 바뀝니다. 이 책이 가르친 것은 모르는 것 앞에서 던질 질문의 순서입니다. 그 순서는 CPU 안에서도, 서버 백 대 위에서도, 사람 네 명의 팀에서도 같습니다. 그것이 프랙탈이고, 그것이 이 열다섯 장의 결론입니다.
부록 A. 용어 사전
| 용어 | 영문 | 상위 범주 | 정의 |
|---|---|---|---|
| 커널 | Kernel | OS 구성요소 | OS 최하단에서 하드웨어와 응용 프로그램을 중계하는 핵심 모듈 |
| 사용자 모드 | User Mode (Ring 3) | CPU 실행 모드 | 하드웨어 직접 접근이 불가능한 제약 권한 영역 |
| 커널 모드 | Kernel Mode (Ring 0) | CPU 실행 모드 | 모든 명령과 전체 메모리에 접근 가능한 무제한 권한 영역 |
| 시스템 콜 | System Call | 인터페이스 | 응용 프로그램이 커널 모드로 전환해 기능을 요청하는 표준 API |
| 모놀리식 커널 | Monolithic Kernel | 커널 구조 | 드라이버·파일시스템까지 한 주소 공간에 둔 커널 (Linux·macOS·FreeBSD) |
| 마이크로커널 | Microkernel | 커널 구조 | 최소 기능만 커널에 두고 나머지를 사용자 공간으로 분리 (QNX·L4·Minix) |
| 데몬 | Daemon | 프로세스 유형 | 백그라운드에 상주하며 요청을 기다리는 프로세스 |
| Rootless | — | 보안 모드 | 일반 사용자 권한으로 컨테이너를 실행하는 방식 |
| 포워드 프록시 | Forward Proxy | 프록시 | 클라이언트 앞에 서서 클라이언트를 대리 (Squid·VPN) |
| 리버스 프록시 | Reverse Proxy | 프록시 | 서버 앞에 서서 서버를 대리 (Nginx·HAProxy·Cloudflare) |
| Continuous Delivery | — | 방법론 | 배포 가능 상태까지 자동, 최종 배포는 수동 승인 |
| Continuous Deployment | — | 방법론 | 사람 개입 없이 자동으로 운영 반영 |
| IAM 역할 | IAM Role | 아이덴티티 기반 정책 | 주체에 붙는 정책. Principal 없음 |
| 외부 루프 | Outer Loop | 하네스 개념 | 모델이 아니라 빌드·테스트가 종료를 판정하는 바깥 루프 |
| 셸 | Shell | OS 구성요소 | 커널을 감싸 사용자 명령을 전달하는 껍데기 |
| 스케줄링 | Scheduling | 커널 기능 | 여러 프로세스가 CPU를 번갈아 쓰도록 순서를 조율 |
| 가상 메모리 | Virtual Memory | 커널 기능 | 프로세스마다 독립된 주소 공간을 주는 기법 |
| 스왑 | Swap | 커널 기능 | RAM이 부족할 때 디스크를 메모리처럼 쓰는 영역 |
| IPC | Inter-Process Communication | 통신 방식 | 분리된 프로세스끼리 메시지를 주고받는 것 |
| OCI | Open Container Initiative | 표준 | 컨테이너 이미지·런타임의 공개 표준 |
| 단일 장애점 | SPOF | 구조 위험 | 그 하나가 죽으면 전체가 멈추는 지점 |
| Pod | — | 배치 단위 | IP·스토리지를 공유하며 함께 살고 죽는 컨테이너 묶음 |
| SSL 종료 | SSL/TLS Termination | 기능 | 암호화 해제를 프록시가 몰아서 처리 |
| CI | Continuous Integration | 방법론 | push/PR마다 자동 빌드·자동 테스트로 조기 검증 |
| GitOps | — | 운영 방식 | Git 저장소의 상태를 클러스터에 계속 수렴시키는 방식 |
| 버킷 정책 | Bucket Policy | 리소스 기반 정책 | 자원에 붙는 정책. Principal 필요 |
| OCR | Optical Character Recognition | 기술 | 이미지 속 글자를 텍스트로 변환 (구문 단계) |
| 지킬 | Jekyll | 정적 사이트 생성기 | 마크다운을 웹사이트로 변환. 개발 로그 저장소로 사용 |
| 가이드 / 센서 | Guide / Sensor | 하네스 축 | 행동 전 방향 설정 / 행동 후 결과 체크 |
| recall@k | — | 검색 지표 | 상위 k개 안에 정답이 들어 있는 비율 |
| 프랙탈 | Fractal | 구조 개념 | 같은 구조가 배율을 바꿔 반복되는 것 |
부록 B. 스스로 확인하기
| # | 질문 | 답이 있는 곳 |
|---|---|---|
| 1 | 커널의 4대 역할을 순서대로 말할 수 있는가? | 1.3 |
| 2 | Ring 0과 Ring 3의 경계를 넘는 유일한 방법은? | 1.5 |
| 3 | 모놀리식 커널과 마이크로커널의 트레이드오프는? | 1.6 |
| 4 | dockerd가 죽으면 왜 전체가 영향을 받는가? | 2.3 |
| 5 | Podman이 Rootless를 기본으로 삼은 이유는? | 2.4 · 2.8 |
| 6 | Continuous Delivery와 Deployment를 가르는 한 가지 질문은? | 4.3 |
| 7 | 포워드와 리버스 프록시에서 "거꾸로"인 것은 무엇인가? | 3.3 |
| 8 | 502와 504는 각각 무엇이 문제인가? | 3.5 |
| 9 | CI/CD가 하네스 이론의 무엇에 해당하는가? | 4.7 |
| 10 | GetObject와 ListBucket의 ARN은 왜 다른가? | 6.4 |
| 11 | RFP 하네스 4원칙을 대고 각각 예를 들 수 있는가? | 8.4 |
| 12 | 이 교재의 판별 축 여덟 개를 말할 수 있는가? | 13.1 |
부록 C. 자주 하는 실수
| 실수 | 바로잡기 |
|---|---|
| "마이크로커널이 더 발전한 것" | ⚠️ 세상에서 가장 많이 쓰는 커널(Linux)은 모놀리식입니다. 트레이드오프 |
| "async를 붙였는데 안 빨라짐" | ⚠️ 시스템 콜 대기(I/O) 가 없는 CPU-bound 구간에는 효과 없음 |
| "서버가 느리면 코드부터 본다" | ⚠️ 스왑이 도는지(RAM 부족) 먼저 확인 |
| "컨테이너는 VM처럼 격리된다" | ❌ 커널을 공유하므로 격리가 더 약합니다 |
| "Rootless면 안전하다" | ⚠️ 탈옥을 막는 게 아니라 피해 범위를 줄이는 장치입니다 |
| "리버스 프록시는 반대로 흐른다" | ❌ 흐름이 아니라 대리 대상이 반대입니다 |
| "502면 서버가 없는 것" | ⚠️ 프록시 뒤의 앱이 죽은 것. 504는 앱이 늦은 것 |
| "CD는 하나의 개념" | ❌ Delivery(수동 승인) / Deployment(무개입) 둘입니다 |
":latest만 쓰면 편하다" | ❌ 되돌릴 대상이 사라집니다. 커밋 해시 태그를 쓰세요 |
"VISION_S3_BUCKET에 ARN을 넣음" | ❌ 버킷 이름만. ARN 전체를 넣으면 NoSuchBucket |
"ListBucket도 /* 붙임" | ❌ 객체 대상만 /*. 버킷 대상은 /* 없음 |
| "업로드가 안 되니 버킷을 퍼블릭으로" | ❌ 퍼블릭 차단은 켠 채로 IAM 역할로 해결합니다 |
| "EC2 서버에도 액세스 키를 넣는다" | ⚠️ 같은 계정이면 IAM 역할이 표준. 키를 심지 않습니다 |
".env.example에 실제 값을 적어 공유" | ❌ 키 이름만. 값은 절대 금지 |
| "비용을 줄였다고 쓰면 됨" | ⚠️ 숫자와 측정 도구가 없으면 아무 정보가 아닙니다 |
부록 D. 날짜별 색인
| 날짜 | 다룬 내용 | 이 장의 절 |
|---|---|---|
| 8/3 (월) | 플러터 카카오 OAuth, 웹·모바일 로그인 분리와 Redis 모바일 토큰, 하네스 md 선작성, S3 업로드와 ARN 함정, IAM 역할 4단계, 포트/어댑터 업로드 경로 | 5.1~5.4, 6 |
| 8/4 (화) | 영수증 가계부 리버스 파이프라인, OCR, DESIGN.md 하네스, tailwindcss·shadcn 통일, 취업생 이력서 해부, 면접 정량화 포인트 | 7, 8.1, 10.1~10.3 |
| 8/6 (목) | 커널 4대 역할·실행 모드·시스템 콜·커널 구조 분류, CI/CD, 웹 프록시와 포워드/리버스, Docker vs Podman | 1, 2, 3, 4 |
| 8/9 (일) | 팀의 CLAUDE.md·AGENTS.md 논의 | 8.2, 12 |
| 8/20 (목) | 가상 클라이언트 요구사항, 멀티에이전트 금융 리포트 주제 확정, SI 산출물 순서, 공공 SI 시나리오, 지킬 개발제안서, CLAUDE.md 진행사항 기록 규칙 | 9.1~9.4, 8.3 |
| 8/21 (금) | 팀 샘플 저장소, 채용 공고 분석, 포트폴리오 리프레이밍, 스크럼 칸반, RDS(Aurora pgvector) 구성과 .env 규칙, RFP 하네스 4원칙 | 9.4 |
| 8/24 (월) | 팀·개인 AWS 크레딧, RDS·EC2·S3 준비 완료, 지킬 폴더 깊이 2, 지킬 테마 자료 | 9.6, 8.3, 12 |
| 8/25 (화) | 사용자별 칸반 분리, AI 챔피언십, 디자인 레퍼런스 | 9.4, 12 |
부록 E. Gemini / NotebookLM 프롬프트
복습 문제 받기
이 15주차 교재만 근거로 8문제를 내줘. 비전공자 기준으로.
"커널 모드와 시스템 콜", "Continuous Delivery vs Deployment",
"포워드 vs 리버스 프록시"는 반드시 포함해줘.
답은 바로 주지 말고, 내가 답한 다음에 채점하고
틀린 이유를 교재의 어느 절을 근거로 설명해줘. 교재에 없는 내용은 꺼내지 마.
인포그래픽 ① — 커널과 두 개의 링
「1.4 동작 원리 — CPU 실행 모드」와 「1.5 시스템 콜」을 한 장으로 만들어줘.
- 동심원 두 개: 안쪽 Ring 0(커널 모드), 바깥 Ring 3(사용자 모드)
- 두 원 사이에 "시스템 콜"이라는 하나의 문만 그리기
- 각 원 안에 무엇이 도는지(응용 프로그램 / 커널·드라이버) 배치
- 아래에 open·read·write·socket·fork 를 실제 우리 코드와 짝지어 표시
- 전문용어는 한글(영문) 병기
인포그래픽 ② — 프랙탈 축 지도
「13.2 같은 축, 아홉 개의 배율」 표를 세로 인포그래픽으로 만들어줘.
- 위에서 아래로 배율이 작아지는 축(팀 → AI → 네트워크 → 앱 → 코드 → 컨테이너 → 커널 → CPU)
- 각 줄 왼쪽에 "하나로 뭉침", 오른쪽에 "여럿으로 쪼갬"
- 가운데 세로선 하나로 모든 줄을 관통시켜 "같은 축"임을 시각화
- 오른쪽 여백에 "쪼갠 대가"를 작게 표기
- 맨 아래에 한 문장: "뭉치면 빠르지만 같이 죽고, 쪼개면 안전하지만 통신 비용을 낸다"
막힐 때
15주차에서 "___" 가 이해가 안 돼.
이 교재의 판별 축 여덟 개(디스크↔메모리, 추상↔구상, 속성↔기능, 로컬↔원격,
하나↔여럿, 동기↔비동기, 무상태↔상태, 구문론↔의미론)만 써서 다시 설명해줘.
교재에 없는 새 비유는 만들지 마.
아직 안 배운 것 추론해보기
나는 이 교재로 커널·컨테이너·프록시·CI/CD까지 배웠어.
쿠버네티스를 아직 안 배웠는데, 교재의 판별 축 여덟 개만 써서
쿠버네티스가 어떤 축의 어느 쪽에 놓이는 도구일지 추론해줘.
새 용어를 설명하지 말고, 내가 이미 아는 개념(Pod, SPOF, 선언적 상태, GitOps)과
연결해서만 말해줘. 그다음 내 추론이 맞는지 채점해줘.
LangTailor