CherryPlan 프로젝트 세팅하면서 처음 Sonnet 4를 붙인 게 올해 2월이었어요. 그때까지만 해도 "AI 어시스턴트는 어디까지나 보조"라는 생각이 강했거든요. 근데 어느 날 리팩토링 작업 중간에 컨텍스트가 길어져서 반쯤 포기하고 "아까 말한 거 기억해? useCartStore에서 파생된 셀렉터 분리하는 거"라고 던졌는데, 그냥 기억하고 이어서 작업을 해줬어요. 그 순간 뭔가 달라졌다는 걸 체감했어요. 단순히 코드 생성기가 아니라 같이 작업하는 존재처럼 느껴지기 시작한 거예요. 그 이후로 CherryPlan 블로그 자동화, 개인 사이드 프로젝트, 그리고 회사 신규 프로젝트까지 — 거의 모든 작업에 Sonnet 4를 투입하고 있어요. 3개월간 실무에서 직접 쓰면서 느낀 것들, 오늘 솔직하게 풀어볼게요.

Claude Sonnet 4가 뭔데요, 이전이랑 뭐가 달라요?

Claude Sonnet 4는 Anthropic이 2025년 말 출시한 모델이에요. Claude 3.5 Sonnet 대비 가장 크게 달라진 건 컨텍스트 유지력과 추론 깊이예요.
이전 모델들은 대화가 길어지면 앞 내용을 슬쩍 잊어버리거나, 일관성이 흔들리는 경우가 있었어요. Sonnet 4는 그 부분이 눈에 띄게 개선됐고, 단순히 "답 주는" 게 아니라 "왜 이게 문제인지"를 역으로 파고드는 능력이 생겼어요.
개발자 입장에서 체감 차이는 세 가지로 압축돼요.
1. 긴 리팩토링 세션에서 컨텍스트를 끝까지 들고 감
CherryPlan 블로그 자동화 스크립트 리팩토링할 때였어요. 대화가 20턴을 넘어가는 상황에서 "아까 말한 useCartStore 셀렉터 분리 작업 이어서 해줘"라고 던졌는데, 중간에 흐름이 끊기지 않고 정확히 그 맥락에서 이어받았어요. 이전 모델이었으면 "죄송합니다, 앞 내용을 다시 공유해주시겠어요?" 나왔을 타이밍이었거든요.
실제로 써보니 — 컨텍스트 유지가 되니까 작업 흐름이 끊기지 않아요. 리팩토링처럼 연속적인 판단이 필요한 작업에서 체감이 가장 커요. 중간에 "요약 다시 해줘"를 안 쳐도 되는 것만으로도 시간이 꽤 줄어요.
// 리팩토링 전 — 스토어에 직접 접근
const cart = useCartStore((state) => state.items)
const total = useCartStore((state) => state.items.reduce(...))
// 리팩토링 후 — Sonnet 4가 제안한 셀렉터 분리
const selectCartItems = (state: CartState) => state.items
const selectCartTotal = (state: CartState) =>
state.items.reduce((sum, item) => sum + item.price * item.qty, 0)
const cart = useCartStore(selectCartItems)
const total = useCartStore(selectCartTotal)
실제로 써보니 — 이 패턴을 제안하면서 "나중에 items가 바뀌면 셀렉터만 수정하면 돼요, 컴포넌트 건드릴 필요 없어요"까지 설명해줬어요. 단순 코드 변환이 아니라 왜 이렇게 해야 하는지를 같이 짚어주는 거예요.
2. 타입 에러, 표면이 아니라 근본 원인을 짚어줌
회사 신규 프로젝트 작업 중 Type 'string | undefined' is not assignable to type 'string' 에러가 떴을 때예요. 보통 이런 에러는 그냥 ! 붙이거나 옵셔널 체이닝으로 때우고 싶은 유혹이 있잖아요. Sonnet 4는 에러 메시지 던졌더니 스택 위로 거슬러 올라가서 "이 값이 undefined가 될 수 있는 건 API 응답 타입 정의가 느슨해서예요, 여기서부터 고쳐야 해요"라고 짚어줬어요.
// API 응답 타입 — 문제의 근원
type UserResponse = {
id: string
name: string | undefined // ← 여기가 문제
}
// Sonnet 4가 제안한 수정
type UserResponse = {
id: string
name: string // API 스펙 확인 후 확정
}
// 혹은 진짜 undefined 가능성이 있다면
type UserResponse = {
id: string
name?: string // 명시적 optional
}
// 사용하는 쪽에서도 타입 가드 추가
const displayName = user.name ?? '이름 없음'
실제로 써보니 남발하는 코드가 눈에 띄게 줄었어요.
근본 원인을 짚어주니까 같은 에러가 다른 컴포넌트에서 반복되는 일이 없어졌어요. 타입 안정성 측면에서 코드 퀄리티가 올라간 게 체감돼요.
3. 에러 메시지만 던지면 원인 + 수정 + 재발 방지까지
CherryPlan 자동화 스크립트 돌리다가 터진 에러예요.
TypeError: Cannot read properties of undefined (reading 'map')
at processPostList (/scripts/auto-publish.js:47:23)
이걸 그냥 붙여넣었더니 돌아온 답이 이랬어요.
// 문제 원인: API 응답이 빈 배열이 아닌 undefined를 반환하는 케이스 미처리
// 수정 전
const processed = postList.map(post => formatPost(post))
// 수정 후
const processed = (postList ?? []).map(post => formatPost(post))
// 재발 방지: API 응답 자체에 기본값 처리
async function fetchPostList(): Promise<Post[]> {
const response = await api.getPosts()
return response.data ?? [] // 여기서 한 번 막기
}
원인 설명, 즉시 수정 코드, 그리고 "이 패턴을 API 레이어에서 한 번 막으면 이후엔 이런 에러 안 봐도 돼요"까지. 에러 디버깅 시간이 체감상 절반 이상 줄었어요.

솔직한 한계
Sonnet 4도 못 하는 게 있어요.
최신 라이브러리 버전에 어두워요. Next.js 15나 React 19처럼 최근에 나온 버전의 세부 변경사항은 가끔 틀려요. "이 API는 이렇게 쓰면 돼요"라고 알려줬는데 실제로 돌려보면 deprecated된 경우가 있어요. 무조건 공식 docs 교차 확인은 필수예요.
프로젝트 전체 구조를 한 번에 파악하진 못해요. 파일 하나씩 붙여넣으면서 컨텍스트 쌓아야 해요. 처음부터 전체 그림을 알려주는 게 효율이 훨씬 높아요.
결국 판단은 내가 해야 해요. Sonnet 4가 제안한 코드가 항상 정답은 아니에요. 비즈니스 로직이나 팀 컨벤션은 내가 더 잘 알아요. AI가 틀렸을 때 알아챌 수 있는 기본기는 유지해야 해요.

마무리
CherryPlan 자동화 스크립트 디버깅 시간이 평균 2시간에서 30분 이하로 줄었어요. 회사 신규 프로젝트에서 타입 에러로 인한 수정 횟수도 5회 이상에서 1~2회로 줄었고요. Sonnet 4는 "코드 생성기"가 아니라 "같이 생각하는 동료"에 가까워졌어요
'개발 실무' 카테고리의 다른 글
| [Claude Code 실전 정복 #6] 레거시 코드 리팩토링을 AI한테 맡겨봤더니 — 2,000줄짜리 파일이 이렇게 됐어요 (0) | 2026.05.16 |
|---|---|
| Cursor 쓰다가 Claude Code로 갈아탄 7년차 개발자의 솔직 후기 (0) | 2026.05.15 |
| Claude에 MCP 연결하면 뭐가 달라지냐고요? 노션·피그마·구글캘린더 세팅 실전기 (0) | 2026.05.14 |
| 2026년 프론트엔드 개발자의 직무가 바뀌고 있어요 — 7년차가 체감한 변화 (0) | 2026.05.13 |
| [Claude Code 실전 정복 #5] 에러 메시지 붙여넣으면 알아서 고쳐주는 버그 수정 실전기 (2026) (0) | 2026.05.11 |