Ch.9 유사 사례와 키워드 정리¶
앞에서 AI가 자주 틀리는 패턴과 CS 관점 코드 리뷰 체크리스트를 정리했다. 이번에는 유사 사례를 더 보고, Part 2 전체를 마무리한다.
9-6. 유사 사례¶
사례: AI가 만든 캐시 코드에 Cache Stampede가 숨어있었다¶
AI에게 "Redis 캐시를 적용해줘"라고 했다. AI가 준 코드:
def get_user(user_id: int):
cached = redis.get(f"user:{user_id}")
if cached:
return json.loads(cached)
user = db.query(User).get(user_id)
redis.set(f"user:{user_id}", json.dumps(user.dict()), ex=60)
return user
잘 동작한다. 그런데 캐시 만료 순간에 동시 요청 100개가 들어오면? 100개 전부 캐시 미스가 나고, 100개 전부 DB를 조회한다. 이게 Cache Stampede다.
CS를 아는 사람은 이 코드를 보고 "캐시 만료 시점의 동시성이 고려되지 않았다"는 걸 안다. Mutex Lock이나 캐시 갱신 전략(예: 만료 전에 미리 갱신)이 필요하다. Ch.17에서 자세히 다룬다.
사례: AI가 만든 재귀 코드가 Stack Overflow를 냈다¶
AI에게 "카테고리 트리를 순회하는 함수를 만들어줘"라고 했다. AI가 준 재귀 코드는 카테고리가 5단계면 잘 동작했지만, 운영 DB에서 100단계 깊이의 데이터가 들어오자 RecursionError: maximum recursion depth exceeded가 발생했다.
Ch.4에서 배운 것: 재귀는 함수 호출마다 Stack Frame이 쌓인다. Python의 기본 재귀 제한은 1,000이다. 명시적 Stack(리스트)을 사용한 반복문으로 바꾸면 해결된다. Ch.12에서 자세히 다룬다.
AI 코드 리뷰 워크플로우¶
지금까지 본 내용을 실제 작업 흐름으로 정리하면 3단 패턴이 나온다. 자가 리뷰, AI 리뷰, 사람 리뷰. 각 단계는 다른 종류의 오류를 잡는다.
flowchart TD
P[프롬프트 작성<br/>CS 키워드 포함] --> G[AI 코드 생성]
G --> S1[1단계: 자가 리뷰<br/>받자마자 훑어보기]
S1 -->|문법 오류, 누락 등<br/>명백한 문제| FIX1[수정 후<br/>재생성]
FIX1 --> G
S1 -->|기능적으로 OK| S2[2단계: AI 메타 리뷰<br/>체크리스트 기반]
S2 -->|동시성, 성능, 보안<br/>패턴 매칭형 문제| FIX2[지적 사항 검토<br/>및 수정 요청]
FIX2 --> G
S2 -->|AI 리뷰 통과| S3[3단계: 사람 리뷰<br/>CS 시각으로 마지막 검증]
S3 -->|사각지대 발견| FIX3[수동 수정<br/>또는 재생성]
FIX3 --> G
S3 -->|승인| MERGE[병합/배포]
style S1 fill:#f0f8ff
style S2 fill:#fff8dc
style S3 fill:#f0fff0
각 단계의 역할은 다음과 같다.
| 단계 | 누가 | 무엇을 보는가 | 잡는 오류의 종류 |
|---|---|---|---|
| 1단계 자가 리뷰 | 본인 (생성 직후) | 문법, 의도와의 일치, 명백한 누락 | 표면적인 오류 |
| 2단계 AI 메타 리뷰 | AI (체크리스트로) | 동시성, 복잡도, 보안 등 패턴화된 문제 | 잘 알려진 안티패턴 |
| 3단계 사람 리뷰 | 본인 또는 동료 | CS 사각지대, 도메인 맥락, 운영 환경 특수성 | AI도 사람도 놓치는 것 |
핵심은 단계를 건너뛰지 않는 것이다. AI가 만든 코드를 받자마자 PR로 올리면 1단계와 2단계가 사라진다. AI에게만 리뷰를 시키면 3단계가 사라진다. 세 단계 모두를 거치는 게 AI를 안전하게 쓰는 최소한의 워크플로우다.
Part 2 마무리: AI 시대의 CS¶
Part 2 (Ch.7~9)에서 말하고 싶은 결론은 세 줄이다:
- CS 키워드를 알아야 좋은 프롬프트를 쓸 수 있다 (Ch.7)
- 카테고리별 키워드를 알아야 문제를 진단하고 방향을 잡을 수 있다 (Ch.8)
- CS 지식이 있어야 AI의 답을 검증할 수 있다 (Ch.9)
AI는 도구다. 도구를 잘 쓰려면 도구의 한계를 알아야 한다. AI의 한계는 "기능은 만들지만, 품질은 보장하지 않는다"는 거다. 품질을 보장하는 건 개발자의 CS 역량이다.
Part 3부터는 다시 CS 본론으로 돌아간다. 자료구조, 알고리즘, 데이터베이스, 캐시, 아키텍처, 보안까지. 각 챕터에서 배우는 키워드가 곧 AI에게 줄 수 있는 프롬프트 재료가 된다는 걸 기억하면서 읽으면 된다.
면접 Q&A (이 챕터로 답할 수 있는 단골 질문)¶
AI가 만든 코드, 그냥 동작하면 그대로 써도 되지 않나요?
동작 여부와 품질은 다른 문제다. AI는 기능은 만들지만 품질은 보장하지 않는다. 본문에서 본 캐시 코드는 잘 동작했지만 만료 순간 Cache Stampede가 숨어 있었다. 재귀 코드도 5단계 깊이에서는 잘 돌다가 100단계에서 Stack Overflow를 냈다. 운영에 들어가야 드러나는 함정이 많다.
AI가 자주 틀리는 대표적인 패턴이 뭔가요?
크게 셋이다. 1) 동시성을 놓친다 (캐시 만료 시점의 Race Condition, 재고 차감의 Lock 누락 등). 2) 성능을 안 본다 (O(n^2) 로직, N+1 쿼리). 3) 과한 추상화 (구체 구현이 하나뿐인 인터페이스 같은 YAGNI 위반). 그래서 CS 관점 체크리스트로 동시성·복잡도·I/O 패턴·DB 쿼리·설계 적절성을 따로 봐야 한다.
AI 코드 리뷰할 때 뭘 기준으로 봐야 하나요?
본문 체크리스트가 그 기준이다. 동시성(Race Condition·Lock 누락), 성능/복잡도(Time Complexity), I/O 패턴(CPU Bound와 I/O Bound 혼동), DB(N+1, Index 누락), 보안, 설계 적절성(YAGNI)을 카테고리별로 점검한다. 단순히 "잘 짰나"가 아니라 CS 키워드별로 항목을 매기는 게 핵심이다.
AI가 만든 재귀 코드는 왜 위험한가요?
Stack Frame이 함수 호출마다 쌓이기 때문이다. Python 기본 재귀 제한은 1,000이라 운영에서 깊이가 깊은 데이터가 들어오면 RecursionError가 난다. 본문 사례처럼 5단계 카테고리에서는 잘 돌다가 100단계 깊이에서 터진다. 명시적 Stack을 쓰는 반복문으로 바꾸면 해결된다.
AI가 만든 캐시 코드에서 어떤 문제를 봐야 하나요?
캐시 만료 순간의 동시성이다. 본문 코드처럼 단순히 get/set만 있으면 만료 시점에 동시 요청 100개가 전부 DB로 흘러간다(Cache Stampede). Mutex Lock으로 단일 갱신을 보장하거나, 만료 전에 미리 갱신하는 전략이 있어야 한다. AI는 보통 여기까지 자동으로 챙겨주지 않는다.
AI에게 코드 리뷰를 시켜도 되나요?
체크리스트를 프롬프트에 넣어주면 가능하다. "이 코드를 동시성·복잡도·I/O 패턴·DB 쿼리 관점에서 점검해줘" 식으로 카테고리를 명시한다. 다만 AI 스스로 리뷰한 답도 다시 검증해야 한다. Hallucination은 코드 생성에서뿐 아니라 리뷰에서도 발생한다.
결국 AI 시대에 CS를 공부해야 하는 이유는?
세 가지다. 좋은 프롬프트를 쓰려면 키워드가 필요하고(Ch.7), 카테고리별로 문제를 진단하려면 키워드 사전이 필요하고(Ch.8), AI 답을 검증하려면 CS 지식이 필요하다(Ch.9). AI는 도구고, 도구의 한계를 채우는 게 개발자의 CS 역량이다.
오늘의 키워드 정리¶
새 키워드¶
Code Review (코드 리뷰)
작성된 코드를 다른 사람(또는 자동화 도구)이 검토하는 과정이다. 기능 동작 여부뿐 아니라 동시성, 성능, 보안, 가독성 등을 확인한다. AI가 만든 코드도 반드시 리뷰해야 한다. 이 챕터에서는 CS 관점의 리뷰 체크리스트를 제시했다.
YAGNI (You Ain't Gonna Need It)
"지금 필요하지 않은 기능을 미리 만들지 마라"는 소프트웨어 공학 원칙이다. AI는 확장 가능성을 고려해서 불필요한 추상화를 만드는 경향이 있다. 구체 구현이 하나뿐인 인터페이스, 사용처가 하나뿐인 팩토리 패턴 등이 YAGNI 위반의 전형이다. Ch.20에서 관심사의 분리와 함께 다룬다.
Cache Stampede (캐시 스탬피드)
캐시가 만료되는 순간에 대량의 요청이 동시에 원본 저장소(DB 등)를 조회하는 현상이다. 캐시가 있을 때는 안정적이다가 만료 순간에 DB 부하가 폭증한다. Mutex Lock, 만료 전 갱신, 확률적 갱신 등으로 방지한다. Ch.17에서 자세히 다룬다.
재등장 키워드¶
| 키워드 | 최초 등장 | 이번 챕터에서의 역할 |
|---|---|---|
| Race Condition | Ch.5 | AI가 놓치는 동시성 문제의 대표 사례 |
| Time Complexity | Ch.8 | AI 코드의 성능 문제를 판단하는 기준 |
| CPU Bound / I/O Bound | Ch.3 | AI가 잘못 선택하는 I/O 패턴 |
| N+1 Problem | Ch.8 | 코드 리뷰 체크리스트 DB 항목 |
| Hallucination | Ch.7 | AI가 자신 있게 틀리는 근본 원인 |
| Stack Frame | Ch.4 | 재귀 코드의 Stack Overflow 위험 |
| Prompt Engineering | Ch.7 | 체크리스트를 AI 프롬프트에 활용 |
키워드 연관 관계¶
graph LR
CR["Code Review"] --> CHK["체크리스트"]
CHK --> CON["동시성<br/>(Ch.5)"]
CHK --> PERF["성능/복잡도<br/>(Ch.10)"]
CHK --> IO["I/O 패턴<br/>(Ch.3)"]
CHK --> DBC["DB/쿼리<br/>(Ch.13~16)"]
CHK --> SEC["보안<br/>(Ch.23)"]
CHK --> DES["설계 적절성<br/>(Ch.20)"]
DES --> YAGNI
CON --> RC["Race Condition"]
PERF --> TC["Time Complexity"]
CR -->|"AI에게<br/>리뷰 시킬 때도"| PE["Prompt Engineering<br/>(Ch.7)"]
CS2["Cache Stampede"] -.->|"Ch.17"| CON
여기까지의 지도 (누적)¶
위의 "키워드 연관 관계"가 이번 챕터 안의 연결이라면, 아래는 Ch.1부터 지금까지 도메인별로 쌓인 키워드다. 빈 레인은 앞으로 그 챕터에서 채워진다 — 다 채워지는 과정이 곧 이 강의의 지도다. (이번 챕터에서 추가된 키워드는 굵게.)
| 도메인 | 누적 키워드 (등장 챕터) |
|---|---|
| OS·실행 | System Call·Kernel·Mode Switch·Buffer·File Descriptor(2) → CPU/IO Bound·GIL·Event Loop·async/await·Thread/Process Pool·Context Switch·IPC(3) → Process·Thread·PCB/TCB·Memory Layout·Virtual Memory·Page·TLB·OOM(4) |
| 동시성·트랜잭션 | Race Condition·Critical Section·Mutex/Lock·Deadlock·Semaphore·Starvation(5) |
| 자료구조·알고리즘 | — (Ch.10에서 시작) |
| DB·캐시·튜닝 | — (Ch.13에서 시작) |
| 네트워크·분산 | TCP/IP·Socket·3/4-Way Handshake·Connection Pool·Keep-Alive·TIME_WAIT(6) |
| 설계·AI·품질·보안 | Computational Thinking·CS 키워드(1) → LLM·Token·Context Window·Hallucination·Prompt Engineering(7) → 키워드 사전·DNS·Load Balancing·Circuit Breaker·CQRS(8) → Code Review·YAGNI·Cache Stampede(9) |
Part 3 (Ch.10)부터는 자료구조와 알고리즘의 실무로 넘어간다. 첫 챕터 제목이 "contains()를 쓰지 마세요"다. 코드 한 줄이 성능을 수천 배 바꾸는 이야기로 시작한다.