Overview
Claude Code Max를 쓰면서 컨텍스트 엔지니어링을 적용해봤다. 같은 프롬프트를 던져도 맥락을 어떻게 넘기느냐에 따라 결과가 달라졌고, 그 과정에서 내가 이해한 설계 방향도 더 선명해졌다.
시작은 도구 지원
회사에서는 개발 도구로 IntelliJ를 지원하고 있으며 대부분은 IDE에서 지원하는 AI를 썻다. 하지만 나는 Cursor를 좀 더 선호해서 지원을 받지 않고 개인적으로 사용하고 있었다.
그렇게 스프린트 진행 도중, 회사에서 Claude Code Max 도입을 검토하게 됐다. 정식 도입 전에 먼저 사전 실험을 해볼 사람을 찾고 있었고, 내가 자원해서 진행하게 됐다.
안 그래도 최근에 AI 오케스트레이션이라는 주제에 관심이 생기면서 AI 활용 자체에 대한 관심이 높아져 있던 시점이었다. 게다가 보름 뒤에 팀원들 앞에서 후기 발표를 해야 한다는 얘기를 들으니, 그냥 "좋더라" 수준이 아니라 좀 더 체계적으로 접근해보고 싶었다.

실제로 마지막에는 이렇게 팀원들 앞에서 사용기를 공유했다. 혼자 써보고 끝낸 실험이 아니라, 팀 안에서 어떤 방식으로 활용하면 좋을지 같이 정리해보는 자리이기도 했다.
AI를 쓰고는 있지만..
요즘 대부분의 사람들은 AI 안 쓰고 개발하는 경우가 거의 없는 듯하다. 나 또한 마찬가지였는데 나의 사용 방식은 단순했다.
- 막히는 부분이 생기면 프롬프트를 던진다
- 답변에서 필요한 부분만 가져다 쓴다
- 다음 작업에서 다시 프롬프트를 던진다
간단한 작업에는 이걸로도 충분하다. 근데 도메인 지식이나 팀 컨벤션이 깊게 얽힌 작업에서는 매번 같은 배경을 반복 설명해야 하는 비효율이 있는 듯했다.
이번에는 다르게 해보기로 했다
그래서 이번에는 단순히 프롬프트만 잘 쓰는 게 아니라, AI한테 넘기는 맥락 자체를 설계해보기로 했다. 소위 말하는 컨텍스트 엔지니어링이다.
비슷한 맥락에서 SDD(Spec Driven Development)라는 것도 있는데, 이건 개발 시작 전에 제품 명세서를 작성해서 넘기는 방식이다. 처음부터 새로 만드는 프로젝트에는 괜찮을 수 있지만, 이미 전체적인 구조와 컨벤션이 잡혀 있고 스프린트 단위로 돌아가는 환경에서는 맞지 않다고 느꼈다.
내가 더 필요하다고 느낀 건, "지금 내가 뭘 하려는지"에 대한 맥락이었다. 프로젝트의 도메인 지식, 팀에서 합의한 설계 원칙, 이번에 내가 맡은 범위. 이런 정보가 없으면 AI는 일반적인 방식으로밖에 답을 못 한다.
특히 앞으로 팀 전체가 AI를 쓰게 될 텐데, 각자 따로 프롬프트만 던지면 같은 컨벤션을 공유하고 있어도 AI 결과물은 제각각일 수 있다. 컨텍스트 문서를 공유하면 누가 쓰든 팀 방향에 맞는 결과가 나오지 않을까 싶었다.
문서는 이런 식으로
마침 이번에 맡은 티켓이 장바구니 페이지 관련이라는 명확한 주제가 있었다. 그래서 남은 태스크들을 하나의 마크다운 파일로 정리해봤다. 이 마저도 AI와 함께 만들어버린..
실제로 넘긴 문서의 대략적인 구조는 다음과 같다.
# Sprint: [커머스 도메인] 장바구니 [그룹 기반 주문 구조] 구현
## 목표
장바구니(Cart) 페이지를 **스토어별 [그룹 단위 처리 구조]** 로 전면 재구성한다.
기존 flat한 상품 리스트 → 스토어별 [논리적 그룹 구조] 로 전환하고,
이에 맞춰 데이터 흐름·선택 상태·UI를 리팩토링한다.
## 핵심 변경 사항
### 1. 데이터 모델: flat → grouped
- 카트 API를 `[기존 API 버전]` → `[신규 API 버전]`
- 응답 구조: `Item[]` → `{ [그룹 컬렉션 키]: [Group 엔티티][] }`
### 2. 타입 시스템 분리
- `[API DTO 계층]` / `[UI 전용 모델 계층]` / `[Mapper 변환 계층]`
- 원칙: UI는 DTO를 직접 참조하지 않음, Usecase 레이어에서만 매핑 수행
### 3. API 구조 재정의 (3단 레이어)
- `[Repository Layer]` — 순수 네트워크 호출
- `[Query Wrapper Layer]` — 상태 관리 라이브러리 래핑
- `[Usecase Layer]` — 비즈니스 로직 + 모델 변환
### 4. 선택 상태 리팩토링
- 기존: [모놀리식 내부 상태 배열], 부모 ↔ 자식 동기화 useEffect, prop drilling
- 변경: [외부 선택 스토어] 도입, Set 기반 ID 관리
- [아이템 단위 토글] / [그룹 단위 토글] / [전체 선택 토글]
- 삭제 시 스토어 동기화 처리
### 5. 컴포넌트 구조 재정의
- 컨테이너는 레이아웃만 담당, 로직은 커스텀 훅으로 분리
## 설계 원칙 요약
- UI는 `[외부 계약 모델]`을 모름
- 선택 상태는 `[외부 스토어]`에서 관리
- API는 `[3단 추상 레이어]` 유지
- 삭제는 `[Optimistic Strategy]` 적용같은 프롬프트, 다른 결과
같은 질문을 두 가지 방식으로 던져봤다. 하나는 프롬프트만, 다른 하나는 컨텍스트 문서를 함께.

결과는 꽤 달랐다.

구체적으로 어떤 차이가 있었는지 항목별로 정리하면 아래와 같다.
| 항목 | 컨텍스트 없음 (프롬프트만) | 컨텍스트 포함 (마크다운 문서 제공) |
|---|---|---|
| 상태 관리 도구 | Recoil atom을 활용한 단순 상태 통합 | 코드리뷰에서 배운 useSyncExternalStore 기반으로 설계한 커스텀 스토어 |
| 구조 및 컨벤션 | 기존 레거시 폴더 구조를 그대로 유지 | 팀 합의인 3단 분리 및 _store/ 디렉토리 패턴 적용 |
| 도메인 이해도 | 단순 ID 배열 관리 (일반적인 장바구니 로직) | 스토어별 묶음배송 맥락 파악, toggleStore 등 그룹화 액션 설계 |
| 레거시 처리 | 기존 파일 위에 땜질식으로 리팩토링 | 팀 컨벤션에 맞춰 불필요한 의존성 걷어내고 책임 분리 |
다른 거지, 틀린 건 아니다
여기서 짚고 넘어갈 게, 컨텍스트 없이 나온 결과가 결코 틀린 답은 아니란 생각이 들었다.
예를 들어 Recoil atom을 선택한 것도 합리적이긴 하다. 프로젝트에 이미 Recoil이 있으니까. 하지만 그게 이번에 내가 원한 방향은 아니었다. 코드리뷰를 통해 배운 useSyncExternalStore를 바탕으로 선택 상태를 외부 스토어로 분리하는 설계를 내가 잡아뒀었고, 컨텍스트 없이는 AI가 이걸 알 방법이 없었다.
반면 컨텍스트를 넘기자 동작이 확실히 달라졌다. 내가 설계한 방향을 정확히 캐치했고, _store/ 디렉토리를 분리하는 등 팀 컨벤션에 맞게 구조를 잡았다. 심지어 '스토어별 묶음배송'이라는 도메인 요구사항을 이해하고 toggleStore(itemIds[]) 같은 그룹 단위 액션까지 스스로 설계에 반영했다.
틀리고 맞고의 문제가 아니라, 내가 원하는 방향으로 나오느냐의 차이였다.
그 외에 기억에 남는 것들
컨텍스트 엔지니어링과는 별개로, 2주간 쓰면서 신기했던 동작들이 몇 가지 있었다.
하나는 작업이 길어질 것 같다고 판단하면, 스스로 여러 개의 하위 에이전트를 생성해서 병렬로 처리하는 모습이었다. 메인 모델이 작업을 분할하고 더 가벼운 모델한테 나눠서 맡기는 식이었는데, 따로 지시하지 않았는데도 알아서 그렇게 동작했다.
또 토큰 사용량이 얼마나 늘어났는지 궁금하여 전체 코드를 순회하며 데드코드를 찾으라는 지시를 했다. 이런 단순하지만 반복이 많은 작업을 만나면 갑자기 토큰 사용을 멈추더니 파이썬 스크립트를 하나 작성해서 그걸로 처리해버리는 경우가 기억에 남는다. 자기가 직접 반복 작업을 하는 대신 자동화 코드를 짜서 돌린 건데 많이 신기했다.
마무리
처음엔 나의 의도를 마크다운으로 정리하고 전달하는 과정이 번거롭기도 했다. 근데 한번 만들어두니까 단순 구현에 쓰는 시간이 줄었고 그만큼 구조 설계나 코드리뷰 반영 같은 쪽에 더 신경 쓸 수 있었다. 아직 배울 게 많은 입장에서 오히려 이 시간이 생긴 게 개인적으로는 가장 큰 수확이었다.
AI에게 뭘 시키느냐보다 이해한 맥락을 얼마나 잘 전달하느냐가 결과를 바꿨다. 그리고 그 과정을 거치며 팀의 의도를 더 알수있었다.