0.3 외우지 말고, 모델을 세우고 검증하라
CS 지식은 읽은 페이지 수가 아니라 낯선 현상을 설명하고 다음 결과를 예측하는 능력으로 남아야 한다. 현상에서 질문을 만들고, 최소 동작 모델로 예측한 뒤, 구현과 계측으로 틀린 가정을 수정하는 학습 루프를 세운다.
학습 목표
- 사실의 기억과 재사용 가능한 동작 모델의 차이를 설명한다.
- 현상 관찰에서 판단 기록까지 이어지는 모델·예측·검증 학습 루프를 수행한다.
- 자신의 빈 지식과 현재 문제에 맞춰 순차 학습과 문제 중심 학습 경로를 선택한다.
- 검색·AI·벤치마크 결과를 가설과 1차 자료로 검증하는 기준을 적용한다.
- 설명·예측·측정·선택을 기준으로 학습 완료 여부를 평가한다.
배경: 많이 읽었는데 현장에서 떠오르지 않는 이유
자료구조 책을 읽고 Big-O 표를 외웠다. 운영체제 강의에서 프로세스와 가상 메모리를 배웠다. 네트워크 책에서 TCP의 흐름 제어와 혼잡 제어도 읽었다. 그런데 Linux 호스트의 운영 대시보드에서 CPU는 낮고 load average만 높은 상황을 보면 무엇부터 확인할지 떠오르지 않는다. 연결 리스트의 삽입이 O(1)이라는 문장은 기억하지만 실제 서비스에서 배열보다 나은 조건은 설명하기 어렵다.
지식이 없어서만은 아니다. 학습할 때 본 질문과 현장에서 풀어야 할 질문의 형태가 다르기 때문이다.
| 학습할 때 남은 문장 | 현장에서 필요한 판단 |
|---|---|
| 해시 조회는 평균 O(1)이다 | 키 수·분포·메모리 한도에서 배열·트리·해시 중 무엇을 선택할 것인가? |
| 가상 메모리는 주소를 변환한다 | 메모리 할당은 성공했는데 첫 접근에서 지연과 RSS가 증가하는 이유는 무엇인가? |
| TCP는 신뢰할 수 있는 바이트 스트림이다 | 응답 타임아웃 뒤 요청을 재시도해도 애플리케이션 상태가 안전한가? |
| 트랜잭션에는 격리 수준이 있다 | 이 불변식에 필요한 격리와 충돌 비용은 무엇인가? |
| 캐시는 빠르다 | 작업 집합과 접근 지역성, 무효화 요구에서 캐시가 실제 이득인가? |
왼쪽은 사실 지식이고 오른쪽은 조건을 포함한 전이(transfer) 문제다. 새로운 상황에 지식을 사용하려면 개념 이름과 정의 사이에 원인 → 내부 상태 변화 → 관찰 결과의 연결이 있어야 한다. 이 연결을 여기서는 동작 모델(working model)이라 부른다.
동작 모델은 실제 시스템의 모든 세부를 복제하지 않는다. 현재 질문에 답할 만큼만 정밀한 실행 가능한 설명이다. “연결 풀 최대 크기가 100이고 쿼리 한 개가 평균 50ms이므로, 동시 요청이 지속적으로 처리 용량을 넘으면 새 요청은 큐에서 기다리고 p99가 평균보다 먼저 증가한다”는 문장은 모델이다. 부하를 늘렸을 때 대기 시간이 어느 방향으로 변할지 예측할 수 있기 때문이다.
좋은 모델은 무엇을 할 수 있는가
학습 노트가 모델인지 확인하는 가장 간단한 방법은 동사를 바꾸는 것이다. “정의할 수 있다”에서 멈추지 않고 설명, 예측, 측정, 선택할 수 있어야 한다.
설명한다: 현상이 생기는 메커니즘을 연결한다
“GC 때문에 느리다”는 이름 붙이기다. 예를 들어 세대별 GC를 사용하는 런타임에서 “할당률이 높아 young generation이 자주 차고, 승격된 객체가 old generation 압력을 높였으며, 전체 정지(stop-the-world) 구간이 요청 처리를 멈췄다”는 메커니즘 설명이다. 모든 GC가 같은 세대 구조나 정지 방식을 쓰는 것은 아니므로 대상 런타임·수집기·버전을 함께 기록한다. 설명은 관찰한 지연과 힙·GC 상태 사이에 인과 경로를 제시한다.
좋은 설명은 반사실(counterfactual)도 포함한다. 원인이 맞다면 할당률을 낮추거나 힙 압력을 제거했을 때 정지 빈도와 꼬리 지연이 어떻게 달라져야 하는지 말할 수 있다.
예측한다: 조건을 바꾸기 전에 방향을 말한다
벤치마크를 먼저 실행하면 나온 숫자에 맞춰 이야기를 만들기 쉽다. 측정 전에 다음을 기록한다.
- 입력 크기를 10배로 늘리면 어느 구현의 시간이 더 빠르게 증가할 것인가?
- 데이터 배치를 연속 메모리로 바꾸면 캐시 미스와 실행 시간은 어느 방향으로 변할 것인가?
- CPU 바운드 워커 스레드를 코어 수 이상으로 늘리면 처리량과 컨텍스트 스위치는 어떻게 변할 것인가?
- 동시 요청이 연결 풀 크기를 넘으면 평균과 p99 중 무엇이 먼저 흔들릴 것인가?
정확한 수치를 맞힐 필요는 없다. 방향과 이유, 예상 경계가 있어야 한다. 예측이 틀렸을 때 모델의 어느 가정을 수정할지 알 수 있기 때문이다.
측정한다: 모델의 상태와 관찰 지표를 연결한다
측정은 숫자를 모으는 일이 아니라 모델 속 보이지 않는 상태를 간접 관찰하는 일이다.
- 알고리즘의 지배 연산은 입력 크기별 실행 횟수와 시간 곡선으로 본다.
- CPU 병목은 on-CPU 프로파일과 하드웨어 카운터로 본다.
- 스케줄링·I/O 대기는 off-CPU 시간, 런 큐, I/O 큐로 본다.
- GC 가설은 할당률, 세대별 사용량, 정지 이벤트와 요청 지연을 맞춰 본다.
- 네트워크 가설은 연결 단계별 시간, 재전송, 패킷 손실, 서버 큐를 구분해 본다.
- DB 가설은 실행 계획, 읽은 행과 반환한 행, 락 대기, 로그 플러시를 본다.
지표 이름을 아는 것보다 그 지표가 모델의 어느 상태를 대변하며 무엇을 놓치는지 아는 것이 중요하다. CPU 100%는 계산이 유용하게 진행 중인지, 스핀 중인지, GC인지 구분하지 않는다. 평균 응답 시간은 소수의 긴 요청을 숨긴다. 힙 크기는 네이티브 메모리와 RSS 전체를 설명하지 않는다.
선택한다: 이득과 비용을 요구사항에 연결한다
학습의 최종 결과는 “A가 B보다 좋다”가 아니라 조건부 결정이다.
읽기가 쓰기보다 훨씬 많고, 같은 키가 반복되며, 최대 수 초의 오래된 값을 허용하므로 캐시를 둔다. 대신 무효화 실패와 메모리 상한을 운영 비용으로 받아들이고, 권한 데이터는 강한 최신성이 필요하므로 캐시 대상에서 제외한다.
이 문장에는 워크로드, 허용할 보장, 선택한 메커니즘, 지불할 비용, 적용하지 않을 경계가 있다. 다음 시스템에서 조건이 달라지면 결론도 바꿀 수 있다. 이것이 제품 사용법보다 오래 남는 지식이다.
다섯 단계 학습 루프
이 커리큘럼의 각 문서와 실습은 다음 루프로 읽는다.
1. 현상과 질문을 고정한다
↓
2. 최소 동작 모델을 그린다
↓
3. 결과를 먼저 예측한다
↓
4. 구현·계측으로 검증한다
↓
5. 판단 기준과 남은 경계를 기록한다
└───────────────↺ 모델 수정1단계: 현상과 질문을 고정한다
주제를 “가상 메모리 공부”, “TCP 공부”로 적지 않는다. 답을 검증할 수 있는 질문으로 바꾼다.
- 왜
malloc이 성공한 시점과 RSS가 증가하는 시점이 다른가? - 왜 패킷 손실이 적어도 처리량이 크게 떨어질 수 있는가?
- 왜 같은 O(n) 순회가 데이터 배치에 따라 여러 배 차이 나는가?
- 왜 비동기 파일 API가 실제로는 스레드 풀을 사용할 수 있는가?
좋은 질문에는 기대와 놀라움이 있다. 이미 답이 정의에 포함된 질문보다, 자신이 가진 모델로는 설명되지 않는 현상이 학습에 유리하다.
업무에서 가져온 질문이라면 먼저 증거를 보존한다. 입력, 환경, 버전, 지표의 시간 범위, 재현 조건을 기록한다. 재현이 어려운 장애도 “무엇을 관찰하지 못해 구분할 수 없었는가”를 다음 설계 과제로 만들 수 있다.
2단계: 최소 동작 모델을 그린다
문서를 읽기 전에 현재 아는 범위에서 실행 단위를 그린다. 틀려도 된다. 빈칸과 잘못된 연결을 발견하는 것이 목적이다.
예를 들어 Linux의 일반 파일에 대한 기본 버퍼링 I/O(buffered I/O)를 단순화해 다음처럼 시작할 수 있다.
애플리케이션 write
→ 운영체제
→ 디스크
→ 완료본문을 읽으며 페이지 캐시, dirty page, write-back, 장치 캐시, fsync를 추가한다.
write
→ 사용자 버퍼에서 페이지 캐시로 복사
→ dirty 표시
→ write는 내구성을 보장하지 않고 먼저 반환할 수 있음
→ 커널 write-back
→ 장치/컨트롤러 캐시
→ 저장 장치가 완료를 보고한 경계
fsync(file) → 파일 데이터와 해당 파일 메타데이터의 완료를 기다림
fsync(dir) → 새 이름·이름 변경의 디렉터리 엔트리 내구성이 필요할 때 별도 검토이 모델은 Linux의 일반적인 경로를 설명할 뿐 모든 파일 시스템·운영체제·장치가 같은 완료 의미를 제공한다는 뜻은 아니다. 직접 I/O(direct I/O)도 페이지 캐시를 우회하는 방식이지 그 자체로 전원 장애 후 내구성을 보장하지 않는다. 모델이 정교해지면서 “write 성공은 내구성을 뜻한다”는 기존 가정이 어디서 틀렸는지 보인다. 모델에는 최소한 다음이 있어야 한다.
- 상태를 가진 구성 요소
- 상태를 바꾸는 연산
- 순서와 동시 실행 가능성
- 비용이 발생하거나 대기하는 지점
- 실패할 수 있는 경계
- 외부에서 관찰할 수 있는 신호
다이어그램을 예쁘게 만드는 것이 목표가 아니다. 입력이나 실패 조건을 바꿨을 때 결과를 추론할 수 있는지가 기준이다.
3단계: 결과를 먼저 예측한다
실습을 실행하기 전에 짧은 예측표를 작성한다.
| 항목 | 기록 예시 |
|---|---|
| 변화 | 순차 배열 접근을 무작위 포인터 추적으로 바꾼다 |
| 예측 | 원소 수가 캐시를 넘는 구간부터 포인터 추적 쪽 시간이 더 빠르게 증가한다 |
| 이유 | 하드웨어 프리페처와 공간 지역성을 활용하기 어렵고 캐시 미스 의존 체인이 생긴다 |
| 관찰 | 입력 크기별 ns/op, cache miss 가능 시 카운터, 메모리 사용량 |
| 반증 | 충분히 큰 작업 집합에서도 두 접근의 시간과 미스 차이가 없다 |
| 통제 | 같은 연산 수, 워밍업, 결과 소비, 반복 횟수, CPU 환경 |
반증 조건이 중요하다. 어떤 결과가 나와도 자신의 설명이 맞다고 할 수 있다면 검증 가능한 모델이 아니다. “아마 런타임 최적화 때문” 같은 만능 설명을 피하려면 컴파일 결과나 프로파일처럼 구분할 추가 관찰을 정한다.
4단계: 구현하고 계측한다
직접 구현은 표준 도구를 대체하기 위해서가 아니라 숨은 상태 변화를 관찰하기 위해 한다. 해시 테이블을 구현하면 충돌, 부하율, 리사이징 순간을 계수할 수 있다. 작은 GC를 만들면 root에서 도달성을 추적하고 회수 대상이 정해지는 과정을 볼 수 있다. 패킷 캡처는 fetch 한 줄 아래 연결과 재전송을 펼친다.
실험은 한 번에 한 가설을 구분하도록 작게 만든다.
- 입력 크기, 분포, 동시성 중 하나만 먼저 바꾼다.
- 비교할 두 구현의 결과와 수행 작업이 같은지 확인한다.
- JIT 워밍업, dead-code elimination, GC, 페이지 캐시 같은 교란을 기록한다.
- 평균만 보지 않고 분포와 반복 간 변동을 본다.
- 개발 노트북의 결과를 운영 환경의 절대값으로 일반화하지 않는다.
예상과 다른 결과가 나오면 실험 실패가 아니라 학습이 시작된 것이다. 가능한 원인은 모델 오류, 구현 오류, 계측 오류, 환경의 숨은 변수다. 결과를 설명하기 위해 가정을 하나씩 확인한다.
5단계: 판단 기준과 남은 경계를 기록한다
실험 보고서를 숫자 표로 끝내지 않는다. 다음 형식으로 한 단락을 남긴다.
이 환경과 입력 분포에서는 배열 기반 구현이 연결 구조보다 빨랐다. 두 구현의 점근 복잡도는 같지만 연속 접근이 캐시와 프리페처를 활용했고, 연결 구조는 노드별 할당과 포인터 추적 비용을 냈다. 중간 삽입 위치가 이미 주어지고 순회가 드문 워크로드에서는 결론이 달라질 수 있다. 운영 선택 전에는 실제 원소 크기와 삽입·순회 비율로 다시 측정한다.
이 기록은 결과, 메커니즘, 적용 조건, 반대 조건, 다음 검증을 포함한다. 시간이 지나 도구나 하드웨어가 바뀌어도 판단을 재검증할 수 있다.
선수 학습은 장벽이 아니라 추론의 의존 관계다
“CS 학습이 선행되어야 한다”는 말은 모든 이론을 마친 뒤에야 실무를 할 수 있다는 뜻이 아니다. 어떤 결론을 이해하려면 그 결론이 사용하는 모델이 먼저 있어야 한다는 뜻이다.
예를 들어 JIT의 최적화와 역최적화를 이해하려면 다음 연결이 필요하다.
소스 구문과 의미
→ AST/IR 표현
→ 타입·프로파일 가정
→ 최적화된 기계 코드
→ 가정 위반
→ 안전한 실행 단계로 역최적화각 화살표가 비어 있으면 “워밍업하면 빨라진다”, “타입이 바뀌면 느려질 수 있다”는 팁만 남는다. 반대로 전체 컴파일러 이론을 먼저 완주할 필요도 없다. 현재 현상을 설명하는 데 필요한 구문 표현, 실행 티어, 가정과 역최적화 모델부터 세우고 부족한 부분을 확장할 수 있다.
선수 지식의 적정 수준은 다음 질문으로 판단한다.
- 이 문서가 사용하는 입력·상태·연산을 자신의 말로 설명할 수 있는가?
- 결론이 기대는 전제와 실패 조건을 구분할 수 있는가?
- 실험 결과가 예상과 다를 때 어느 앞단 모델을 의심할지 아는가?
세 질문 중 하나가 막히면 링크된 앞 문서로 돌아간다. 선수 학습은 진입을 막는 시험이 아니라 추론 사슬의 빠진 고리를 찾는 장치다.
두 가지 학습 경로
기반 우선 경로: 전반의 빈틈을 메운다
다음 상황에는 Part 1부터 권장 순서로 읽는 편이 낫다.
- 경력 동안 특정 프레임워크와 도메인에 집중해 시스템 전반의 연결이 약하다.
- 성능·장애 문제에서 늘 다른 사람의 진단이나 도구 결론에 의존한다.
- 알고리즘, 런타임, OS, 네트워크 중 어디가 빈틈인지 스스로 판단하기 어렵다.
- 장기적으로 아키텍처·플랫폼·성능 책임 범위를 넓히려 한다.
순차 학습에서도 챕터마다 하나의 업무 사례를 연결한다. 모든 실습을 완벽하게 확장하기보다 기본 실험을 재현하고 예측과 결과가 갈린 부분을 깊게 본다. 매 Part가 끝날 때 과거 장애 하나를 새 모델로 다시 분석한다.
문제 우선 경로: 현재 증상에서 의존 관계를 거슬러 간다
즉시 해결해야 할 문제와 학습 동기가 분명하다면 증상에서 시작한다.
- 0.2의 방식으로 요청 경로와 경쟁 가설을 적는다.
- 가장 구분력이 큰 관찰을 정하고 관련 챕터의 인트로를 읽는다.
- 인트로의 질문을 이해하지 못하면 링크된 선수 챕터로 이동한다.
- 최소 실험으로 현재 문제의 메커니즘을 재현한다.
- 해결책과 비용을 기록한 뒤 인접 계층에서 같은 가정이 반복되는지 확인한다.
예를 들어 “Node.js API에서 CPU는 낮은데 요청이 멈춘다”면 챕터 8 운영체제의 스케줄링·I/O 모델에서 시작할 수 있다. 이벤트 루프와 런타임의 책임이 비어 있으면 챕터 6 런타임과 메모리로 이동하고, 실제 파일·네트워크 대기가 문제라면 운영체제와 네트워크 문서를 연결한다.
문제 우선 경로의 위험은 임시 해결에 필요한 조각만 모으는 것이다. 이를 막기 위해 해결 뒤에 “다른 입력·부하·실패에서도 같은 결론인가?”라는 전이 질문을 하나 더 푼다.
한 문서를 공부하는 구체적인 방법
다섯 단계 학습 루프를 문서 한 편에 적용할 때는 다음 기록만 남긴다.
| 시점 | 기록할 내용 |
|---|---|
| 읽기 전 5~10분 | 핵심 질문, 현재 생각하는 실행 순서, 결과를 바꿀 조건, 확인할 업무 사례 |
| 읽는 중 | 원인 → 상태 변화 → 관찰, 보장과 구현 세부, 평균·최악·경계 조건, 현재 모델과 충돌한 문장 |
| 읽은 직후 | 본문 없이 다시 그린 실행 흐름, 다섯 문장 이내의 답, 조건을 바꾼 예측, 검증할 실험·운영 지표 |
| 며칠 뒤 | 표면이 다른 문제에 같은 모델을 적용한 전이 질문과 달라진 조건 |
백지에서 시작하기 어렵다면 “연결 풀을 두 배로 늘리면 처리량과 DB 락 대기는 어떻게 달라질까?”처럼 한 변수를 바꾼 질문을 쓴다. 읽는 중에는 모든 문장을 요약하지 않고 자신의 예측을 바꾸는 정보에 집중한다. 읽은 뒤 설명이 막히면 처음부터 다시 읽지 말고 끊어진 인과 연결에 해당하는 절만 찾아 모델을 수정한다.
전이할 때는 같은 예제를 반복하지 않는다. 예를 들어 큐 포화를 배웠다면 DB 연결 풀과 CI 작업 큐를 비교하고, 트랜잭션 격리를 배웠다면 재고 차감과 좌석 예약에서 필요한 불변식을 비교한다. 표면 용어를 걷어 냈을 때 같은 구조가 보이면 지식이 목록에서 모델로 바뀌고 있다는 신호다.
검색과 AI를 학습에 사용하는 기준
검색 엔진과 AI 도구는 설명, 코드, 가설 후보를 빠르게 제공한다. 이 속도는 학습 루프를 줄일 수도 있고 건너뛰게 할 수도 있다. 답을 먼저 받으면 자신의 모델과 예측이 드러나지 않아 무엇을 모르는지 알기 어렵다.
도구를 다음 역할로 제한하면 학습을 강화할 수 있다.
좋은 사용: 경쟁 가설과 검증 자료를 넓힌다
- “이 증상을 만들 수 있는 계층별 가설을 나열하고 각 가설을 구분할 지표를 제안하라.”
- “내 설명에서 표준이 보장하는 동작과 특정 구현 세부를 구분하라.”
- “이 벤치마크에서 결과를 왜곡할 교란 변수를 찾아라.”
- “내가 세운 비용 모델이 깨지는 반례 입력을 만들어라.”
- “이 주장의 근거가 되는 표준·RFC·원 논문·공식 문서의 위치를 알려 달라.”
도구의 출력은 후보이지 증거가 아니다. 기술 사실은 표준, RFC, 공식 문서, 원 논문, 공식 소스에서 확인한다. 버전과 구현에 따라 달라지는 내용은 실험 환경을 명시하고 직접 관찰한다.
나쁜 사용: 판단을 감춘다
- 전체 해결 코드를 받은 뒤 실행 성공만 확인한다.
- 출처 없는 성능 수치와 “모범 사례”를 일반 법칙으로 사용한다.
- 이해되지 않는 오류를 계속 붙여 넣으며 임의의 수정안을 순서대로 시도한다.
- 모델과 반증 조건 없이 생성된 아키텍처를 채택한다.
- 요약을 많이 저장한 것을 학습 진도로 센다.
AI가 만든 코드가 테스트를 통과해도 왜 그 자료구조와 동시성 제어가 필요한지, 실패 시 어떤 상태가 남는지 설명하지 못하면 운영 판단은 여전히 외부에 위임된 상태다.
답을 받기 전에 남길 세 줄
도구를 호출하기 전에 다음만 적어도 수동적 소비를 크게 줄일 수 있다.
- 현재 가장 가능성이 높다고 보는 설명
- 그 설명이 맞다면 관찰되어야 할 결과
- 틀렸음을 보여 줄 결과
답을 받은 뒤에는 어떤 가설이 새로 생겼고 어떤 근거로 우선순위가 바뀌었는지 기록한다.
실험이 거짓말하는 흔한 방식
만들며 검증한다는 원칙도 실험 설계가 나쁘면 잘못된 확신을 만든다.
대표하지 않는 입력
작은 무작위 데이터에서 빠른 구현이 정렬된 대규모 운영 데이터에서도 빠르다는 보장은 없다. 최대 크기, 분포, 중복률, 읽기·쓰기 비율, 병적 입력을 구분한다. 한 점의 숫자보다 입력을 단계적으로 늘린 곡선을 본다.
다른 작업을 비교한다
한 구현은 결과를 실제로 소비하고 다른 구현은 계산 결과가 사용되지 않아 컴파일러가 제거할 수 있다. 캐시된 파일 읽기와 콜드 디스크 읽기, 연결 재사용 요청과 매번 TLS를 맺는 요청도 같은 작업이 아니다. 비교 대상의 의미 계약과 수행 경로를 먼저 맞춘다.
환경의 숨은 상태
JIT 워밍업, CPU 주파수, 백그라운드 프로세스, GC, 페이지 캐시, 네트워크 경로가 결과를 바꾼다. 완벽한 통제는 어렵지만 환경·버전·반복 방법을 기록하고 실행 순서를 섞으며 분산을 제시한다.
측정 자체의 오버헤드
상세 로그와 트레이싱은 실행 시간을 바꾸고, 샘플링 프로파일러는 짧은 이벤트를 놓칠 수 있다. 관찰 도구가 보는 것과 개입하는 정도를 이해한다. 서로 다른 원리의 관찰이 같은 결론을 지지하는지 교차 확인한다.
숫자는 맞지만 질문이 틀렸다
함수 하나를 20% 빠르게 만들었어도 전체 요청 시간에서 그 함수가 1%라면 사용자 영향은 미미하다. 처리량이 늘었어도 p99와 오류율이 요구사항을 넘을 수 있다. 항상 출발점의 시스템 불변식과 종단 지표로 돌아간다.
학습 산출물: 지식이 판단으로 남게 한다
챕터마다 긴 요약 대신 네 가지 작은 산출물을 남긴다.
모델 카드
주제:
입력/상태/연산:
핵심 실행 흐름:
지배 비용:
깨지는 경계:
관찰 방법:예측과 실험 기록
바꾼 변수:
예측과 이유:
통제한 조건:
관찰 결과:
예측과 달랐던 점:
수정한 모델:판단 문장
<조건>에서는 <선택>을 한다.
<메커니즘>으로 <이득>을 얻고,
<비용/실패 모드>를 받아들인다.
<경계>가 나타나면 <대안>을 다시 검토한다.전이 질문
같은 모델을 다른 도메인에 적용하는 문제 하나를 직접 만든다. 정답보다 조건이 바뀌면 결론도 바뀌도록 설계한다. 예를 들어 캐시 학습 후 “권한 정보, 상품 설명, 환율에 같은 TTL을 적용할 수 없는 이유”를 묻는다.
이 네 산출물은 면접 답안 모음이 아니다. 설계 리뷰, 장애 조사, ADR, 성능 실험에서 그대로 재사용할 수 있다.
2주 학습 스프린트 예시
업무와 병행할 때 한 주제를 다음처럼 작게 운영할 수 있다. 예시는 “API의 p99가 동시 요청 증가와 함께 급격히 늘어나는 이유”다.
| 시점 | 활동 | 산출물 |
|---|---|---|
| 1일차 | 실제 지표와 요청 경로를 보고 경쟁 가설을 적는다 | 기대/관찰, 계층 지도 |
| 2~3일차 | 관련 인트로와 본문에서 큐·스케줄링·I/O 모델을 읽는다 | 모델 카드 초안 |
| 4일차 | 연결 풀과 작업 큐를 포함한 최소 서버를 만든다 | 재현 코드, 실행 환경 |
| 5일차 | 부하 전 예측을 적고 동시성을 단계적으로 늘린다 | p50/p95/p99, 큐 대기 곡선 |
| 2주차 1일 | 풀 크기·서비스 시간을 하나씩 바꿔 모델을 검증한다 | 비교 실험 |
| 2주차 2일 | 무제한 큐, 빠른 실패, 배압(backpressure)을 비교한다 | 트레이드오프 표 |
| 2주차 3일 | 운영 시스템의 설정과 지표를 같은 모델로 다시 읽는다 | 적용 차이와 미확인 가정 |
| 2주차 4일 | 동료에게 10분 설명하고 반례를 받는다 | 수정한 모델 |
| 2주차 5일 | 조건부 선택 문장과 다음 전이 질문을 쓴다 | 판단 기록 |
분량이 많아 보이면 구현 범위를 줄인다. 모델·예측·관찰·수정의 고리는 자르지 않는다. 본문 세 편을 읽고 아무것도 측정하지 않는 것보다 한 메커니즘을 끝까지 검증하는 편이 판단 능력을 더 잘 만든다.
학습 완료의 기준
문서를 끝까지 읽었다는 사실은 진행 상태이지 완료 증거가 아니다. 한 주제에서 다음 질문에 답할 수 있으면 일단 다음으로 이동한다.
- 설명 — 표면 API 아래의 주요 상태와 실행 순서를 자신의 말로 설명할 수 있는가?
- 예측 — 입력·부하·실패 조건 하나를 바꿨을 때 결과의 방향을 예측할 수 있는가?
- 측정 — 경쟁 가설을 구분할 지표나 최소 실험을 고를 수 있는가?
- 선택 — 두 대안의 이득·비용·경계를 요구사항과 연결할 수 있는가?
- 전이 — 표면이 다른 문제에서 같은 구조를 발견할 수 있는가?
모든 구현 세부를 기억할 필요는 없다. 정확한 함수명과 플래그는 다시 찾을 수 있다. 무엇을 찾아야 하는지, 출처를 어떻게 검증할지, 결과가 이상할 때 어느 모델을 의심할지 아는 것이 더 오래가는 역량이다.
ACM·IEEE의 Computing Curricula 2020은 컴퓨팅 역량을 지식(무엇을 아는가), 기술(어떻게 수행하는가), 태도와 성향(dispositions)의 결합으로 다룬다. 이 관점에서 정의만 아는 것은 역량의 한 부분이다. 관찰을 의심하고, 근거를 확인하고, 트레이드오프를 명시하며, 실패에서 모델을 수정하는 습관까지 함께 형성되어야 한다.
정리
- 사실 지식이 현장 판단으로 전이되려면 원인·내부 상태·관찰 결과를 잇는 동작 모델이 필요하다.
- 좋은 모델은 현상을 설명하고, 조건 변화의 결과를 예측하고, 관찰 방법과 선택의 비용을 제시한다.
- 학습은 현상과 질문 고정, 최소 모델 구성, 사전 예측, 구현·계측, 판단 기록의 반복으로 진행한다.
- 선수 학습은 모든 내용을 먼저 암기하라는 요구가 아니라 현재 추론이 의존하는 빠진 모델을 채우는 과정이다.
- 검색과 AI는 경쟁 가설과 자료를 넓히는 데 사용하고, 기술 사실과 성능 결론은 1차 자료와 직접 관찰로 검증한다.
- 완료 기준은 읽은 분량이 아니라 설명·예측·측정·선택·전이할 수 있는가이다.
확인 문제
1. 한 개발자가 “B-tree는 O(log n), 해시 인덱스는 평균 O(1)이므로 해시 인덱스가 더 빠르다”고 학습 노트에 적었다. 이 사실 지식을 판단 모델로 바꾸기 위해 추가할 내용을 작성하라.
정답과 해설
연산과 요구사항을 먼저 고정해야 한다. 등가 키 조회만 하는지 범위·정렬·prefix 조회가 필요한지, 키 분포와 데이터 크기, 메모리·디스크 배치, 쓰기 비율을 적는다. B-tree는 순서를 유지해 범위 탐색과 디스크 페이지 단위 접근에 적합하고, 해시 구조는 등가 조회에 유리할 수 있지만 순서 질의를 지원하지 않으며 충돌·리사이징 비용이 있다. 예측은 대표 워크로드에서 등가 조회 지연, 범위 조회 가능성, 쓰기 비용, 저장 공간을 비교하도록 세운다. “O(1)이 더 빠르다”가 아니라 “등가 조회가 지배적이고 순서 질의가 없으며 구현의 충돌·공간 비용을 감당하는 조건에서 해시가 후보”라는 조건부 판단이 되어야 한다.
2. 파일 쓰기 벤치마크에서 write 직후 종료한 프로그램이 매우 높은 처리량을 보였다. 모델·예측·검증 루프로 이 결과를 평가하라.
정답과 해설
먼저 질문이 사용자 공간 버퍼 복사 속도인지 저장 장치의 내구 쓰기 처리량인지 고정한다. 파일 쓰기 모델에 페이지 캐시, dirty page, write-back, 장치 캐시와 완료 경계를 넣는다. write 반환만 기다리면 데이터가 페이지 캐시에 들어간 속도를 주로 측정했을 수 있다고 예측한다. fsync 포함·제외와 동기 쓰기 조건을 구분하고 장치 I/O와 dirty page 변화를 관찰한다. 데이터 크기를 메모리보다 크게 하는 실험은 write-back과 throttling을 드러낼 수 있지만 내구성을 증명하지 않으며, 직접 I/O도 페이지 캐시 우회와 내구성 보장을 구분해 해석한다. 파일 시스템·장치·가상화 환경을 기록한다. 결과는 틀린 숫자가 아니라 “내구성” 질문에 맞지 않는 측정일 수 있다.
3. AI가 제안한 락 없는(lock-free) 큐 구현이 단위 테스트와 간단한 벤치마크를 통과했다. 채택 전에 어떤 세 줄 예측과 검증을 남겨야 하는가?
정답과 해설
현재 설명으로 큐의 선형화 지점, 메모리 가시성·순서, 빈 큐와 가득 찬 큐의 상태 전이를 적는다. 맞다면 여러 생산자·소비자의 모든 실행에서 항목이 유실·중복되지 않고 API 순서 계약을 만족해야 하며, 경합 시 진행 보장이 어떤 형태인지 예측한다. 틀렸음을 보일 결과는 특정 인터리빙에서 유실·중복·오래된 값 관찰·무한 재시도다. 언어 메모리 모델과 원자 연산의 공식 문서를 확인하고, stress test와 선형 가능성 검사, thread sanitizer 등 가능한 도구를 사용한다. 처리량뿐 아니라 경합 수준별 재시도, 꼬리 지연, CPU 소비를 비교한다. 구현을 설명·검증할 팀 역량과 유지보수 비용이 표준 동기화 큐 대비 이득을 정당화하는지도 판단한다.
4. 문제 우선 경로로 재시도 장애를 해결한 뒤 학습이 단편적인 팁으로 끝나지 않았는지 확인할 전이 질문 두 개를 만들어라.
정답과 해설
예시는 다음과 같다. 첫째, “HTTP 요청이 아니라 메시지 소비 실패에서 재시도·backoff·dead-letter 정책은 어떻게 달라지며 중복 처리 불변식은 어디서 지키는가?” 둘째, “DB 트랜잭션 충돌 재시도와 과부하 상태의 원격 호출 재시도는 모두 다시 실행이지만, 재시도가 성공 가능성을 높이는 조건과 부하를 증폭하는 조건은 어떻게 다른가?” 좋은 전이 질문은 표면 기술을 바꾸면서 실패의 일시성, 멱등성, 시간·시도 예산, 자원 포화라는 같은 모델을 다시 사용하게 한다.
참고 자료
- ACM·IEEE-CS, Computing Curricula 2020 — 컴퓨팅 역량을 지식, 기술, 태도와 성향의 결합으로 정의하고 지식을 실제 과업 수행과 연결하는 관점을 참고한다.
- Chris Jones, Effective Troubleshooting — 시스템의 동작 지식과 가설-검증 절차를 결합하고, 관찰·진단·처치에서 생기는 추론 오류를 줄이는 학습 모델로 사용한다.
- Brendan Gregg, Performance Analysis Methodology — 문제 진술, 워크로드 특성화, USE, CPU·off-CPU 분석처럼 질문에 맞는 성능 방법론을 선택하는 지도를 참고한다.
- Linux man-pages, write(2), fsync(2) —
write성공과 파일·디렉터리의 내구성 완료 경계가 서로 다르다는 점을 확인한다. - Oracle, Garbage-First Garbage Collector — 세대 구조, 승격, 동시 단계와 전체 정지 구간이 결합된 GC의 구체적인 예를 확인한다.
- Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms 4th ed. (2022) — 알고리즘의 정확성과 비용을 입력·불변식·증명·실험으로 연결하는 표준 모델을 확인한다.
- Peter J. Denning, The Locality Principle (2005) — 캐시·메모리·분산 환경을 가로지르는 지역성 모델이 서로 다른 현장 문제로 전이되는 사례를 확인한다.