알고리즘 인터뷰는 정답 코드를 빠르게 작성하는 능력을 본다. 그러나 DoorDash, Uber, Stripe, Netflix, Amazon이 보는 것은 다르다. “실제 서비스에서 마주칠 법한 문제를 어떻게 해석하고, 어떤 구조로 설계하고, 어떤 트레이드오프를 고려하면서 확장 가능하게 구현하는가.” 이 흐름을 다루는 문제 해결 전략이 Code Craft다. 이 글은 Code Craft 다섯 단계가 각각 어떤 판단을 요구하는지, 그리고 그 판단이 결국 좋은 설계 다섯 원칙으로 어떻게 이어지는지를 정리한다. Claude Code를 Harness Engineering 도구로 쓰는 사람에게도 동일하게 적용된다
Code Craft는 알고리즘이 아니다
알고리즘은 투 포인터, BFS, DFS, DP, HashMap 같은 패턴으로 정답 코드를 제한 시간 안에 작성하는 방식이다. 잘못된 방식은 아니다. 그러나 실무에서 마주치는 문제는 다음과 같이 생겼다
- “DoorDash Dasher의 Payout 계산 기능을 만들어라.”
- “Spotify 플레이리스트 매니저를 만들어라.”
- “토스의 더치페이 기능을 구현해라.”
이런 요구사항은 처음부터 완벽하게 주어지지 않는다. 정책은 자주 바뀌고, 환불·취소 같은 예외 경로가 숨어 있으며, 소수점 처리 같은 결정 권한이 지원자에게 넘어와 있다. Code Craft는 이 모호함을 코딩 이전 단계에서 정리하는 사고 과정이다
Code Craft는 OOD(객체지향 설계), API 디자인, Low-Level Design, Product Design, System Design을 하나의 문제 안에서 연결한다. Spotify 플레이리스트 매니저를 예로 들면, 겉으로는 단순한 CRUD처럼 보인다. 그러나 한 발만 들어가면 “같은 곡 중복을 허용하는가”, “순서 변경 API는 어떤 형태가 좋은가”, “수백만 명이 동시에 추가하면 어떻게 되는가” 같은 질문이 한꺼번에 등장한다. Code Craft는 이 질문들을 단계적으로 정리해 답을 만들어 가는 방식이다
Code Craft 다섯 단계
Code Craft는 다섯 단계로 구성된다. 각 단계는 다음 단계의 입력이 된다.
Explore → Brainstorm → Plan → Implement → Verify 요구사항 탐색 대안 비교 구조 설계 구현 검증
Explore – 요구사항을 명확히 한다
Explore 단계의 핵심은 “코딩하기 전에 묻는다”이다. 다섯 가지를 정리한다.
- 제품 요구사항: 어떤 기능을 어떤 범위로 만들 것인가
- 애매한 부분의 명확화: 비즈니스 정책과 UI/UX의 결정되지 않은 영역을 질문으로 좁힌다
- 입력과 출력: 어떤 데이터가 들어가야 어떤 결과가 나오는가
- 제약 조건: 데이터의 최댓값·최솟값, 처리량 제한
- 예외 상황: 환불, 취소, 잘못된 입력, 빈 데이터
DoorDash Payout 예제를 다시 보면, 단순히 “기본 요금 × 횟수 + 팁”으로 끝낼 수 있는 문제가 아니다. Payout은 거리, 시간, 보너스, Peak Time, 팁 같은 여러 요소로 구성되며, 환불·취소 주문은 다르게 처리되어야 하고, 소수점 처리 정책도 결정되어야 한다. Explore 단계는 이런 요소들을 빠짐없이 끄집어내는 단계다
Claude Code에 일을 시킬 때도 이 과정을 그대로 옮길 수 있다. plan mode에서 모델에게 곧장 “Payout 계산기 만들어”라고 하지 않는다. 먼저 요구사항을 사람이 정리해서 명세로 넘기고, 모델에게 빠진 질문을 역으로 받는다. 이 과정 없이 들어가면 모델이 그럴듯한 코드를 만들어도 요구사항과 어긋난 결과가 나온다
Brainstorm – 자료구조와 패턴을 비교한다
Explore에서 요구사항이 명확해지면 다음은 “무엇으로 풀 것인가”를 비교한다.
- 어떤 자료구조를 쓸 것인가 (List, Map, Tree, Queue 등)
- 어떤 패턴을 적용할 것인가 (Strategy, Observer, Factory 등)
- 각 선택의 장단점, 즉 트레이드오프는 무엇인가
이 단계의 함정은 “정답을 빨리 고르려는 마음”이다. Brainstorm은 정답을 고르는 단계가 아니라, 후보를 두세 개 늘어놓고 비교 가능한 상태로 만드는 단계다. 비교 가능한 상태라는 말은 “왜 이 구조를 선택했는가”를 다음 단계에서 한 문장으로 답할 수 있다는 뜻이다
Plan – 클래스, 흐름, 책임을 설계한다
Plan 단계는 Code Craft에서 가장 무게 있는 단계다. 세 가지를 결정한다
- 어떤 클래스와 객체가 필요한가
- 데이터가 어떻게 흘러가는가
- 어떤 모듈이 어떤 책임을 지는가
데이터 흐름은 화면별로 입력과 출력을 정리하는 것으로 시작한다. 예를 들어 친구 리스트 화면에서 친구 상세 화면으로 이동할 때, 어떤 데이터가 입력으로 들어와야 리스트가 그려지고, 어떤 데이터를 다음 화면으로 넘겨야 상세 정보가 표시되는지 단계별로 끊어 본다
[친구 리스트 화면]
input : userId
output : selectedFriend
│
▼
[친구 상세 화면]
input : selectedFriend
output : (편집 결과)
책임 분배는 “결제 모듈은 결제만 책임진다”는 원칙이다. 결제 모듈이 결제도 하고 알림도 보내고 통계도 집계하면 좋은 설계가 아니다. Plan 단계에서 책임 경계를 어떻게 그었는가에 따라, 다음 절에서 다룰 좋은 설계 다섯 원칙이 자동으로 따라붙는다
Implement – 읽고, 테스트하고, 확장할 수 있게 만든다
구현 단계의 기준은 “돌아가는 코드”가 아니라 다음 셋이다
- 읽기 쉬운가
- 테스트 가능한가
- 변경에 유연한가
Claude Code로 구현할 때 이 셋을 사람이 정의해 주지 않으면 모델은 “돌아가는 코드”까지만 만든다. 함수 단위를 어느 정도로 끊을지, 어디에 테스트 경계를 둘지, 어떤 부분을 인터페이스 뒤에 숨길지는 Plan 단계의 결정이 그대로 프롬프트가 된다
Verify – Edge Case로 검증한다
마지막 단계는 검증이다. 단위 테스트만을 의미하지 않는다. 다음 케이스를 가정해서 동작을 점검한다
- 유효하지 않은 입력 (숫자 칸에 문자가 들어왔을 때)
- 빈 데이터
- 중복 입력
- 외부 호출 실패
- 동시성 충돌
DoorDash Payout이라면 “환불된 주문을 다시 정산했을 때 합계가 음수가 되지 않는가”, “소수점 반올림 방향이 정책과 일치하는가” 같은 케이스를 모두 통과해야 검증이 끝난다
Code Craft 다섯 단계가 좋은 설계 다섯 원칙으로 이어진다
Code Craft의 Plan 단계에서 결정되는 것이 결국 “어떤 모듈에 어떤 책임을 줄 것인가”이다. 이 결정의 품질을 판단하는 기준이 좋은 설계 다섯 원칙이다. 좋은 설계는 잘 정리된 집과 같다. 부엌에 요리 도구가 있고, 욕실에 세면도구가 있고, 옷장에 옷이 있다. 숟가락이 욕실에 있으면 집은 작동하지만 살기 어렵다. 소프트웨어도 같다. 로그인 코드는 로그인 쪽에, 결제 코드는 결제 쪽에, 화면 코드는 화면 쪽에 있어야 문제가 생겼을 때 어디를 봐야 할지 알 수 있다. 좋은 설계는 완벽한 구조가 아니라 현재 요구사항에 맞는 합리적 선택이다. 다섯 원칙은 그 합리적 선택을 가능하게 만드는 기준이다
모듈화 – 부품을 갈아 끼울 수 있게 만든다
모듈화는 시스템을 작은 부품으로 나누어, 한 부품을 바꿔도 전체가 무너지지 않게 만드는 작업이다. 레고 자동차에서 바퀴가 마음에 들지 않으면 바퀴만 바꾸면 된다. 컴퓨터에서 RAM이 부족하면 RAM만 바꾸면 된다. 소프트웨어에서는 결제 시스템을 Stripe에서 PayPal로 바꾸는 상황을 떠올리면 된다. 결제 부분만 바꿔서 끝나면 모듈화가 잘 된 것이고, 앱 전체를 뜯어야 한다면 모듈화가 약한 것이다. 모듈화는 교체 가능성, 호환성, 독립성, 그리고 느슨한 결합을 함께 요구한다
관심사 분리 – 각자 자기 일만 한다
관심사 분리는 회사 조직과 같다. HR은 채용을, 마케팅은 홍보를, 회계는 돈 관리를 한다. 한 사람이 채용·회계·광고·서버 관리를 모두 하면 처음에는 빨라 보이지만, 누가 무엇을 책임지는지 알 수 없어지면서 어디도 손대지 못한다. 소프트웨어에서도 로그인 담당 코드는 로그인만, 결제 담당 코드는 결제만, 데이터 저장 담당 코드는 저장만 해야 한다. Code Craft의 Plan 단계에서 “어떤 모듈이 어떤 책임을 지는가”를 결정하는 이유가 여기 있다
캡슐화 – 내부 복잡함을 숨기고 버튼만 제공한다
캡슐화는 내부를 몰라도 쓸 수 있게 만드는 작업이다. 전자레인지를 쓸 때 전기회로와 열 전달 원리를 몰라도 버튼만 누르면 음식이 데워진다. 자동차도 엔진 구조를 모르고 핸들·브레이크·엑셀로 운전한다. 좋은 모듈은 외부에 노출하는 인터페이스가 좁고, 내부 구현은 자유롭게 바꿀 수 있다. 캡슐화가 잘 되어 있으면 내부 변경이 의존하는 쪽을 깨뜨리지 않고 배포될 수 있다
적응성 – 바뀔 가능성이 높은 부분만 유연하게 둔다
요구사항은 변한다. 좋은 설계는 변화의 비용을 낮춘다. 단, 모든 것을 유연하게 만들려고 하면 복잡도가 폭발한다. 좋은 설계는 바뀔 가능성이 높은 부분만 유연하게 두고, 안정적인 부분은 단순하게 둔다. DoorDash Payout으로 다시 돌아가 보자. 기본 요금 정책은 시장 상황에 따라 자주 바뀐다. 이 부분은 외부 설정값으로 빼서 유연하게 둔다. 반면 “기본 요금 × 횟수 + 팁”이라는 계산 로직 자체는 거의 변하지 않으므로 코드 안에 단순하게 둔다. 변하는 부분과 변하지 않는 부분을 분리하는 판단이 적응성의 핵심이다
직관성 – 처음 보는 사람도 헷갈리지 않는다
직관성은 사용하거나 수정할 때 자연스럽게 이해되는 구조다. 엘리베이터 버튼의 위·아래 화살표가 거꾸로 배치되어 있으면 기능은 동작해도 사용자는 헷갈린다. 코드도 같다. 처음 보는 사람이 “로그인 문제는 여기를 보면 되겠구나”, “결제 금액 계산은 여기 있겠구나”라고 예상할 수 있어야 한다. 직관적이라는 말은 무조건 단순하다는 뜻이 아니다. 복잡한 문제는 복잡할 수밖에 없다. 다만 좋은 설계는 그 복잡함을 한곳에 섞어 두지 않고, 단위로 나누어 추론 가능하게 만든다
골디락스 범위 – 단순함과 복잡함 사이
좋은 설계의 품질은 요구사항, 맥락, 제약에 따라 달라진다. 단순한 설계가 자동으로 좋은 것은 아니고, 복잡한 설계가 자동으로 나쁜 것도 아니다. 문제에 맞는 적절한 수준, 즉 골디락스 범위(Goldilocks zone)를 찾는 것이 목표다
복잡도와 이상성(ideality)을 두 축으로 놓으면 다음과 같이 정리된다
이상성 ↑
│ ● Goldilocks
│ ╱ ╲
│ ╱ ╲
│ ● ●
│ 단순 설계 복잡한 설계
│ ╱ ╲
│ ● ●
└─────────────────────────────→ 복잡도
모호한 모노리스 비현실
- 모호한 모노리스: 복잡도는 낮아 보이지만 구조가 모호해 좋은 설계가 아니다
- 단순 설계: 요구사항이 작을 때는 적절하지만, 커지면 부족하다
- 골디락스: 문제에 맞는 복잡도와 가장 높은 이상성을 동시에 가진다
- 복잡한 설계: 필요한 복잡도일 수 있지만 과하면 이상성이 떨어진다
- 비현실: 너무 복잡해서 실제로 사용하거나 유지하기 어렵다
Over-engineering과 Under-engineering은 이 축의 양쪽 끝이다. Code Craft의 Brainstorm 단계에서 후보를 두세 개 놓고 비교하는 이유는, 골디락스 범위에 들어오는 선택지를 의식적으로 찾기 위해서다
결합도와 응집도 – 모듈 경계를 판단하는 두 지표
좋은 설계의 모듈 경계를 판단할 때 가장 자주 쓰는 두 지표가 결합도(Coupling)와 응집도(Cohesion)이다
- 응집도(Cohesion): 한 모듈 안의 요소들이 얼마나 서로 관련 있는가
- 결합도(Coupling): 모듈과 모듈 사이의 연결이 얼마나 많은가
네 가지 조합을 표로 정리하면 다음과 같다
| 결합도 | 응집도 | 상태 | 설명 |
|---|---|---|---|
| 높음 | 낮음 | 잘못 선택된 경계 | 여러 작은 그룹이 어설프게 나뉘어 복잡하게 얽혀 있다 |
| 낮음 | 낮음 | 파괴적 탈결합 (Destructive Decoupling) | 연결은 적지만 의미 있는 경계나 응집이 부족하다 |
| 높음 | 높음 | 거대한 단일 덩어리 | 한 모듈에 너무 많은 책임이 들어가 있다 |
| 낮음 | 높음 | 이상적 | 관련 있는 것끼리 명확히 묶이고, 필요한 연결만 존재한다 |
낮은 결합도와 높은 응집도가 이상적인 이유는 명확하다. 모듈 내부 변경이 외부를 깨뜨리지 않고 배포될 수 있고, 의도치 않은 수정과 오용을 줄이며, 유지 보수성을 높인다. Code Craft의 Plan 단계에서 클래스를 나누고 책임을 분배할 때, “이 결정이 결합도를 낮추는가, 응집도를 높이는가”를 자문하면 모듈 경계가 자연스럽게 잡힌다
Claude Code와 함께 쓰는 방법
Claude Code는 다섯 단계 어디에든 끼어들 수 있다. 다만 모델에게 단계의 판단을 위임하면 결과가 들쭉날쭉해진다. 사람이 단계마다 무엇을 결정해야 하는지 알고 있어야 모델의 답이 의미를 가진다
단계별 분담을 정리하면 다음과 같다
| 단계 | 사람이 결정할 것 | Claude Code에 맡길 것 |
|---|---|---|
| Explore | 비즈니스 정책, 우선순위 | 빠진 질문 목록 생성, 예외 케이스 후보 추출 |
| Brainstorm | 트레이드오프 기준 | 자료구조·패턴 후보 나열과 장단점 정리 |
| Plan | 책임 분배, 모듈 경계 | 데이터 흐름도 초안, 클래스 다이어그램 텍스트 |
| Implement | 함수 분리 기준, 테스트 경계 | 인터페이스 안쪽 구현, 보일러플레이트 |
| Verify | 어떤 케이스를 검증할지 | 단위 테스트와 Edge Case 코드 생성 |
이 표를 거꾸로 읽으면 “AI보다 더 큰 컴퓨터가 되어야 한다”는 말의 의미가 분명해진다. 사람이 단계마다 올바른 질문을 던질 수 있을 때, 모델은 그 질문에 빠르고 일관되게 답한다. Harness Engineering이 강조하는 지점도 여기다. AI를 도구가 아니라 오케스트레이션 대상으로 다룰 줄 알아야 한다
정리
정리하면 Code Craft는 다섯 단계로 문제를 풀고, 그 결과를 좋은 설계 다섯 원칙과 두 지표(결합도·응집도)로 평가한다. 한 줄로 요약하면, 좋은 코드는 빠르게 짠 코드가 아니라 다음 사람이 손댈 수 있는 코드다. 그리고 그 다음 사람이 자기 자신일 가능성이 가장 높다
출처 – 인프런 [Claude Code Harness Engineering 클로드코드 심화 CLI 하네스 엔지니어링 실무]