실용주의 접근법
- 2.1 좋은 설계의 핵심
- 2.2 DRY — 반복하지 마라
- 2.3 직교성
- 2.4 가역성
- 2.5 예광탄
- 2.6 프로토타입과 포스트잇
- 2.7 도메인 언어
- 2.8 추정
실용주의 프로그래머가 문제에 접근하는 방법론을 다루는 장이야. 1장이 마인드셋이었다면, 여기는 "그래서 구체적으로 어떻게?"에 대한 답이지.
20주년 기념판에서 새로 추가된 절인데, 저자들이 좋은 설계의 본질을 한 문장으로 압축해. ETC — Easier to Change. 바꾸기 쉬운 게 좋은 설계야.
왜 결합도를 줄이라고 할까? 바꾸기 쉬워지니까. 왜 단일 책임 원칙을 따르라고 할까? 바꾸기 쉬워지니까. 왜 좋은 이름을 쓰라고 할까? 코드를 읽기 쉬워지고, 그래서 바꾸기 쉬워지니까.
모든 설계 원칙의 상위에 ETC가 있어. 뭔가 고민될 때 **"이 결정이 나중에 바꾸기 더 쉽게 만드는가?"**를 물어보면 돼. 저자들은 이걸 가치(value)가 아니라 본능(instinct)으로 만들라고 하거든. 의식적으로 훈련해서 무의식으로 내려보내라는 거야.
Don't Repeat Yourself. 아마 이 책에서 가장 유명한 원칙일 거야.
하지만 많은 사람이 DRY를 "코드를 복붙하지 마라"로만 이해하는데, 저자들은 그게 아니라고 강조하지. DRY는 **"모든 지식은 시스템 내에서 단 한 번만, 모호하지 않게, 권위 있게 표현되어야 한다"**는 원칙이야.
코드 중복만이 DRY 위반이 아니거든:
- 코드 중복 — 가장 눈에 잘 띄는 형태
- 문서화 중복 — 코드에 이미 있는 걸 주석으로 또 쓰는 것
- 데이터 중복 — 같은 정보가 여러 곳에 저장되는 것
- 표현의 중복 — API 클라이언트와 서버가 같은 지식을 각각 갖는 것
- 개발자 간 중복 — 팀 내에서 같은 기능을 다른 사람이 또 만드는 것
특히 마지막이 가장 잡기 어렵지. 해결책은 소통이야 — 팀원들이 서로 뭘 하고 있는지 알아야 해.
주의할 점: DRY를 과도하게 적용하면 오히려 해가 돼. 두 코드가 우연히 비슷해 보이는 거랑 실제로 같은 지식을 표현하는 건 다르잖아. 우연의 중복을 억지로 합치면 나중에 하나가 바뀔 때 난리가 나거든.
**직교적(orthogonal)**이라는 건 두 개 이상의 것이 서로 영향을 주지 않는다는 뜻이야. 수학에서 직교하는 두 벡터처럼 — 한쪽을 바꿔도 다른 쪽은 안 바뀌지.
직교적인 시스템의 장점:
- 생산성 향상 — 변경의 범위가 국소적이니까 개발 시간이 줄어들어
- 리스크 감소 — 한 부분이 고장 나도 나머지는 멀쩡해
- 테스트 용이 — 각 컴포넌트를 독립적으로 테스트할 수 있지
직교성을 확인하는 간단한 방법: "A를 바꿀 때 B도 바꿔야 하는가?" 바꿔야 한다면 직교적이지 않은 거야.
설계뿐 아니라 팀 조직에도 적용돼. 기능 A를 수정하는데 세 팀이 모여서 회의해야 한다면, 그 조직은 직교적이지 않은 거지.
최종 결정이란 없어. 저자들은 이걸 강하게 주장하거든.
특정 데이터베이스, 특정 프레임워크, 특정 배포 방식에 올인하지 마. 세상은 바뀌고, 요구사항은 바뀌고, 고객의 마음은 바뀌잖아. 오늘의 최선이 내일의 족쇄가 될 수 있어.
가역성을 확보하는 방법:
- 결정을 코드 곳곳에 뿌리지 말고 한 곳에 캡슐화하라
- 추상화 레이어를 활용해 — 직접 DB를 호출하지 말고 인터페이스를 둬
- 서드파티 라이브러리를 직접 호출하지 말고 래핑해
저자들이 이 절에서 하는 비유: "미래에 대비할 수 없다면, 최소한 미래를 대응할 수 있게는 만들어라." 유연성은 아키텍처의 핵심 속성이야.
**예광탄 개발(tracer bullet development)**은 이 책의 시그니처 개념 중 하나야.
군사 용어에서 가져왔거든. 예광탄은 발사하면 빛을 내면서 날아가서 실시간으로 조준을 수정할 수 있게 해주지. 소프트웨어 개발도 마찬가지 — 전체 시스템을 관통하는 얇은 기능 하나를 먼저 만들어서 끝까지 돌려보라는 거야.
예광탄 코드의 특징:
- UI부터 데이터베이스까지 전체 레이어를 관통해
- 프로토타입과 다르게 실제 프로덕션 코드야 (버리지 않아)
- 얇지만 동작하는 골격이지
- 여기에 살을 붙여가면서 완성해
프로토타입과의 차이를 명확히 해야 해:
- 예광탄: 실제 코드. 얇지만 동작함. 유지하고 확장함
- 프로토타입: 실험용. 한 가지만 검증하고 버림
예광탄은 빗나갈 수도 있어. 그게 핵심이야. 일찍 빗나가는 걸 발견해서 일찍 조준을 수정할 수 있다는 거지.
프로토타입은 예광탄과 달라. 프로토타입은 배우기 위해 만들고, 다 배우면 버리는 거야.
프로토타입으로 검증할 수 있는 것들:
- 아키텍처가 성립하는가?
- 기존 시스템과 연동이 가능한가?
- 성능이 충분한가?
- UI/UX가 자연스러운가?
프로토타입은 꼭 코드일 필요 없어. 포스트잇, 화이트보드, 목업 툴 — 뭐든 돼. 핵심은 **"위험한 가정을 검증하는 데 최소 비용을 쓰는 것"**이지.
중요한 규칙: 프로토타입은 반드시 버려야 해. 프로토타입을 프로덕션 코드로 발전시키면 기술 부채의 늪에 빠지거든. 이걸 팀과 이해관계자에게 미리 명확히 해야 해. "이건 실험이고, 끝나면 버립니다."
문제를 풀 때 그 문제의 영역(도메인)에 가까운 언어를 사용하라는 얘기야.
내부 도메인 언어(Internal DSL)와 외부 도메인 언어(External DSL)를 구분하거든:
- 내부 DSL: 호스트 언어 안에서 만드는 것. Ruby의 RSpec, Kotlin의 Gradle DSL 같은 것
- 외부 DSL: 별도의 파서가 필요한 독립 언어. SQL, CSS, 정규표현식 같은 것
20주년 기념판에서는 이전 판보다 톤이 좀 바뀌었어. 이전에는 외부 DSL을 적극 권장했는데, 이번에는 **"비용과 이점을 따져봐라"**는 쪽으로. 외부 DSL을 만들고 유지하는 건 비싸거든. 대부분의 경우 메타데이터(설정 파일, YAML 등)로 충분하지.
저자들이 추정(estimation)을 심각하게 다루는 이유가 있어: 소프트웨어 프로젝트에서 추정은 피할 수 없는데, 대부분 형편없이 하기 때문이야.
추정의 정확도는 단위로 드러나지:
- "약 6개월" — 5~7개월일 수 있음
- "약 150일" — 거의 정확히 150일이라는 뉘앙스
- 같은 기간인데 단위 선택이 정확도에 대한 기대를 만들어
추정하는 방법 PERT도 소개해 — 낙관적/보통/비관적 추정치를 구해서 가중 평균.
핵심 조언:
- **"나중에 알려드리겠습니다"**가 최고의 추정이야. 즉석에서 억지로 답하지 마
- 추정을 기록하고 실제와 비교해. 그래야 추정 실력이 늘지
- 추정이 틀렸다면 왜 틀렸는지 분석해
- 프로젝트 초기에 가장 불확실하므로 범위를 넓게 잡고, 진행하면서 좁혀가야 해
정리
2장 읽고 기억할 거 세 가지:
- ETC(Easier to Change)가 좋은 설계의 핵심이야. 모든 설계 원칙은 결국 여기로 수렴하거든
- DRY는 코드 중복만이 아니야. 지식의 중복을 제거해야 해
- 예광탄과 프로토타입을 구분해. 하나는 살리고, 하나는 버리는 거지