“속도는 키보드에서 나지 않는다. 맥락을 싸 들고 계단을 오를 힘에서 난다.
에이전트는 그 가방을 잠깐 들어 준 짐꾼에 가깝다. 방향은 여전히 내가 잡는다.”
이 글은 수치 실험 보고서가 아니다.
커밋 수로 “AI 덕에 N배”를 증명하지도 않겠다. 그건 깃 메타데이터가 미워한다.
대신 나는 비슷한 모양의 일을 두 번 겪었고, 두 번째가 첫 번째보다 덜 지쳤다는 체감이 분명했다.
약간 과장해서 말하면, 늘어난 건 손가락이 아니라 동시에 들고 가는 맥락의 개수다.
아래에서 그 차이를 생산성이 만들어지는 지점(leverage points) 으로 쪼개 본다.
회사명·티켓·PR 번호는 일부러 넣지 않았다. “우리 팀 일”처럼 읽히면 성공이다.
배경 — 같은 종족의 일, 두 번
첫 번째는 거의 1년 전쯤이었다.
회원·등급·혜택·결제 말머리가 한 번에 바뀌는, 말 그대로 정책이 제품을 통째로 밀어버리는 작업.
auth, product, mypage, order … 한 모노레포 안에서 여러 앱이 동시에 숨을 참는 유형.
두 번째는 최근이다.
제휴·공동브랜드 카드처럼, 결제·홈·콘텐츠·마이페이지·공용 패키지에 같은 정책을 여러 얼굴로 퍼뜨려야 하는 작업. 역시 횡단이다.
기능은 다르다.
그런데 작업의 형태는 닮았다.
- “이 플로우에서 쓰는 API/스토리지/플래그가 저쪽 앱에도 있나?”
- “런칭 뒤 한 달은 예외·엣지가 터진다”
- “리뷰어는 도메인은 아는데, 이 레포의 실제 경로는 모른다”
차이는 에이전트형 편집기와 MCP·터미널까지 붙은 루프를 두 번째에는 이미 몸에 익혔다는 점이다.
첫 번째 때는 그게 없었다.
사례 두 권 — 익명으로 적은 타임라인
아래는 실제 일정·인명·티켓을 숨긴 합성 일기다. 주차는 느낌 화로 적었다. “우리도 저런 주 있었지”가 떠오르면 된다.
A권. 정책 횡단 — 회원·등급·지갑·주문서가 한 breath로 움직여야 할 때 (에이전트 루프 전)
- 착수: PDP의 적립·등급 문구를 바꾸려면
product만이 아니라order의 완료/취소,mypage의 등급 카드, 가입/로그인 플로우까지 같은 약속으로 맞춰야 했다. API 스키마는 공유됐는데, 프론트의 “어느 파일이 진짜 화면인지”는 공유되지 않았다. - 1주차: “적립”, “등급”, “통합”만 검색해도 수백 건이 뜬다. 이벤트용 코드, 죽은 플래그, 레거시 네이밍이 한데 섞였다. 동료에게 물어도 답은 “그때 난 그 앱만 봤어” 였다.
- 3주차: 한 덩어리 PR은 리뷰가 불가능해서 여러 PR로 쪼갰다. 순서가 어긋나면 QA가 “반만 나간 제품”을 본다. 회의는 늘었다.
- 런칭 직후: 비로그인·통합·레거시 등급 조합에서 문구 한 줄이 어긋났다. 원인 추적에 반나절. PM 입장에서는 “한 줄인데?” 였고, 개발 입장에서는 “그 한 줄이 열 군데에 복제돼 있어서” 였다.
B권. 결제·제휴 표시 횡단 — 카드·배너·지갑이 동시에 움직일 때 (에이전트형 편집기 + MCP를 이미 쓰던 시기)
- 착수: checkout 배너, 홈 피드 카드, 지갑 행이 같은 eligibility를 써야 했다.
content-hub는 약관 링크만 맞추고 배너는 켜지 않기로 채팅 스레드에서 잘랐다 — 그게 나중에 “왜 홈만?” 질문을 막아 준다. - 1주차: 출발 타입(
PartnerMethodContext류)과 “이 타입을 import하는 파일만” 목록을 먼저 뽑게 했다. Pages Router / App Router로 갈라진 경로를 표로 받아 두고 잤다. - 2주차: 배너 UI는 앱마다 복제되지만
surface만 바꾸는 패턴으로 맞췄다. 내가 직접 친 줄은 카피·플래그 가드·payload 필드 이름 정도였다. - 런칭 직후: 특정 지갑 × 외부 PG 조합만 깨졌다. 런칭 전에 넣어 둔 진단 분기 덕분에 로그 한 번에 후보가 세 개로 줄었다. “다 터졌다”가 아니라 “조합 하나”로 좁혀졌다.
A와 B의 기능은 다르다. 그러나 돈 나가는 곳은 같다 — 탐색, 복제-변형, 횡단 누락, 런칭 화재, 리뷰어의 이해, 나중에 나를 위한 기록.
아래 각 절은 이 두 권을 같은 레버로 다시 읽는다.
생산성을 “만들어 내는” 지점들
여기서부터가 본론이다. 어디에서 시간이 줄고, 에너지가 남는가.
각 절의 말미에는 익명화한 코드·마크다운 조각을 덧붙였다. 실제 파일과 1:1로 맞지 않으며, 레버가 걸리는 형태만 빌려 온 것이다.
1. 탐색 비용 — “어디에 묻혀 있지?”
횡단 작업의 첫 과금은 탐색이다.
페이지 라우트, 피처 플래그, 공용 훅, 결제 어댑터, 스토리지 래퍼 … 이름은 다 아는데 실제 import 경로를 모른다.
예전: 검색·grep·동료에게 물음·예전 PR 기억 더듬기. 하루가 가볍게 갈린다.
지금: “이 동작과 비슷한 패턴을 레포에서 찾아서, App Router 쪽과 Pages Router 쪽을 비교해 줘”처럼 행동 단위로 던진다.
과장 한 스푼: 내가 동시에 열어 두는 탭 수가 줄어드는 느낌은, CPU 코어가 늘은 것과 비슷하다. (실제로는 내가 던지는 질문의 질이 병목이지만.)
생산성 지점 요약: 첫 주차의 불확실성을 압축하는 구간.
사례로 읽으면: A권 1주차는 “검색 결과가 너무 많아 어디부터 열지를 결정하는 데 에너지가 나갔다. B권은 같은 며칠을 타입·import 목록으로 먼저 좁혀, 탭 지옥이 ‘표 몇 줄’로 바뀌었다.
// 가상. “같은 도메인 이름이 여러 덩어리에 붙어 있을 때”의 출발점.
// 에이전트에게는 보통 이렇게 묶어 던진다:
// “PartnerMethodContext를 import하는 곳과, 결제 직전에만 쓰는 곳을 나눠 줘.”
export type PartnerMethodContext = {
brandId: string
isEligible: boolean
lastSyncedAt: string | null
}
// apps/checkout-shell/.../SubmitBar.tsx (레거시 라우터 쪽 가정)
// apps/account-hub/.../WalletRow.tsx (신규 라우터 쪽 가정)
// packages/payments-ui/.../usePartnerMethod.ts (공용 훅 가정)
2. 반복의 양산 — “같은 문장, 열 번째”
두 번째 과금은 복붙의 변형이다.
에러 메시지, 토스트, Snowplow 속성, 조건부 렌더 … 한 앱에서 맞춰 놓고, 다른 앱에서 조금씩 다른 이유로 다시 써야 한다.
예전: 손으로 복사하고, 놓치는 prop 하나에 QA가 돌아온다.
지금: “이 컴포넌트 패턴을 유지한 채로, B앱의 라우팅 제약만 반영해 초안을”처럼 제약을 같이 적어 달라고 한다.
내가 검토할 건 의미가 맞는지뿐이다.
생산성 지점 요약: 저위험·고빈도 편집의 속도. (고위험 로직은 여전히 사람이 천천히.)
사례로 읽으면: A권에서는 같은 문장을 손으로 옮기다 한 앱만 다른 조사어가 남는 실수가 났다. B권은 “골격은 이 컴포넌트, 제약만 바꿔”라고 못 박고 초안을 내게 해서, 내 눈이 카피와 조건만 따라가게 됐다.
// 가상. B앱만 라우팅 제약이 다를 때 — “골격은 같고 import 경로만 다르다” 류.
// 에이전트 초안 후 내가 반드시 보는 건 copy·조건·플래그 가드 세 군데뿐.
// apps/checkout-shell/components/PartnerBadge.tsx
export function PartnerBadge(props: { tier: 'gold' | 'silver' }) {
const { data } = usePartnerSummary({ surface: 'checkout' })
if (!data?.showBadge) return null
return <span className={badgeClass(props.tier)}>{data.label}</span>
}
// apps/account-hub/components/PartnerBadge.tsx
export function PartnerBadge(props: { tier: 'gold' | 'silver' }) {
const { data } = usePartnerSummary({ surface: 'wallet' }) // 라우팅·캐시 정책만 다름
if (!data?.showBadge) return null
return <span className={badgeClass(props.tier)}>{data.label}</span>
}
3. 횡단 일관성 — “한쪽만 고치면 안 된다”
카드·등급·혜택류는 한 화면이 곧 약속이다. 주문서에서 본 문구가 마이페이지와 다르면 고객은 “버그”가 아니라 신뢰 붕괴로 읽는다.
예전: 머릿속 체크리스트. 빠뜨리면 릴리즈 후에 듣는다.
지금: “이번 변경이 걸릴 앱 목록을 표로 만들고, 각각 무엇을 확인할지 한 단락씩” 요청한다. 체크리스트 초안 공장이다.
생산성 지점 요약: 누락 방지. 속도라기보다 사고 비용의 이동 — 런칭 한 달 뒤의 나를 구한다.
사례로 읽으면: A권 런칭 직후의 “한 줄 어긋남”은 누가 어디까지 맞춰야 하는지가 머릿속에만 있었을 때 잘 생긴다. B권은 POLICY_SURFACES 같은 표를 먼저 두고 “이번 스프린트에 없는 얼굴은 없나?”를 기계적으로 훑었다.
/**
* 가상. “한 정책이 여러 화면에 얼굴이 있다”를 표로 박아 두면,
* 에이전트가 체크리스트 문장을 앱마다 생성하기 쉽다.
*/
export const POLICY_SURFACES = [
{ app: 'checkout-shell', route: '/pay', mustShow: ['eligibleBanner', 'methodFinePrint'] },
{ app: 'account-hub', route: '/wallet', mustShow: ['eligibleBanner', 'balanceFootnote'] },
{ app: 'home-feed', route: '/', mustShow: ['eligibleBanner'] },
{ app: 'content-hub', route: '/promo/x', mustShow: ['termsLink'] },
] as const
// 실제 PR에서는 각 mustShow 옆에 QA 시나리오 한 줄씩 붙인다.
4. 런칭 후 — “예외가 정사”
실서비스는 친절하지 않다.
결제 수단 조합, 웹뷰, 앱 브릿지, 비회원 … 진짜 일은 런칭 후다.
예전: 로그와 채팅과 티켓 사이를 오가며 가설을 하나씩 세운다.
지금: 파일 경로와 스택, 재현 순서를 묶어 “가능한 원인 후보를 세 가지로만 좁혀 줘”처럼 쓴다.
틀린 가설이 나와도, 나는 같은 시간에 더 많은 가설을 버릴 수 있다.
생산성 지점 요약: 디버깅 루프의 폭. (대신 잘못 쓰면 빠르게 틀린 결론도 찍는다 — 그게 트레이드오프.)
사례로 읽으면: A권에서 반나절 걸렸던 조합 버그가 B권에서는 분기 이름이 있는 패치로 들어갔다. “뭐가 터졌나?”가 아니라 “세 가지 중 어떤 diag인가?”로 질문이 바뀐다.
// 가상. 런칭 직후: “조합 폭발”을 한 줄 진단으로 접는 패턴.
type PayDiag =
| { code: 'WALLET_BRIDGE'; hasThirdParty: boolean }
| { code: 'PARTNER_PAYLOAD'; droppedFields: string[] }
| { code: 'LEGACY_ROUTE'; usedPagesRouterHack: boolean }
type CheckoutInput = {
legacyIframe: boolean
partnerToken?: string
hasThirdPartyWallet: boolean
}
type Payload = { version: 2; body: Record<string, unknown> }
function buildCheckoutPayload(
input: CheckoutInput,
): { ok: true; value: Payload } | { ok: false; diag: PayDiag } {
if (input.legacyIframe && !input.partnerToken) {
return {
ok: false,
diag: { code: 'WALLET_BRIDGE', hasThirdParty: input.hasThirdPartyWallet },
}
}
// ...
return { ok: true, value: { version: 2, body: {} } }
}
// 에이전트에게: “ok: false 분기만 골라, 원인 후보 문장으로 바꿔 줘”
5. 리뷰 가능성 — “diff만 보내지 말 것”
횡단 PR은 diff가 길다. 리뷰어는 의도를 먼저 알고 싶다.
예전: PR 설명을 한 밤중에 반쯤 비운 채 올리게 된다.
지금: “무엇을 같게 만들었는지 / 무엇은 의도적으로 다르게 두었는지 / 롤백 시 어디를 볼지” 세 단락 초안을 먼저 뽑는다.
과장 한 스푼: 리뷰는 대화의 질이 올라가서, “LGTM”이 빨라진다기보다 의미 있는 지적이 일찍 들어온다.
생산성 지점 요약: 합의 비용 절감.
사례로 읽으면: A권 때는 diff가 긴 PR에 설명이 비어 리뷰가 감으로 갔다. B권은 “content-hub는 배너를 안 켠다”처럼 스레드에서 자른 합의를 PR 본문 첫 단락에 박아, 왜 파일 수가 다른지를 설명하지 않아도 됐다.
<!-- 가상. PR 본문에 그대로 붙이는 뼈대. 에이전트가 초안, 사람이 숫자·이름만 고친다. -->
## 의도
- checkout / wallet / home 에서 **같은 eligibility 문구**를 쓴다.
- content-hub 는 약관 링크만 맞추고, 배너는 의도적으로 숨긴다 (PM 합의: 스레드 링크).
## 리뷰어가 볼 곳
- `packages/payments-ui/usePartnerSummary.ts` — surface별 캐시 키
- `apps/checkout-shell/.../SubmitBar.tsx` — payload에 붙는 optional 필드
## 롤백
- 플래그 `FF_PARTNER_PHASE2`만 끄면 배너·payload 확장 분기 전체가 구 경로로 돌아간다.
6. 나 자신의 캐시 — 티켓·브랜치·채팅 한 줄로
예전 글에서도 썼다. 티켓·저장소·채팅을 같은 날 같은 언어로 맞춰 보면, 반기 정리할 때 덜 운다.
에이전트는 그때 번역기다. “스레드에서 이렇게 정리됐으니 티켓 첫 문단과 PR 제목 후보를” …
생산성 지점 요약: 추적가능성이라는 느린 자산. 당장의 기능 속도보다 3개월 뒤의 나를 산다.
사례로 읽으면: A권은 반기 정리할 때 “그때 왜 shop만 먼저였지?” 를 기억에 의존해야 했다. B권은 scope_apps, non_goals, slack_thread 한 덩어리가 티켓 상단에 남아 미래의 나와 담당 바꾼 동료에게 말을 건넨다.
# 가상. 이슈 트래커 첫 문단에 붙이는 “한 화면 요약” 초안 (YAML이든 Markdown이든 형식은 팀마다 다름)
title: Partner display phase 2 — cross-app alignment
branch_pattern: feat/partner-phase2-*
scope_apps: [checkout-shell, account-hub, home-feed, content-hub]
non_goals:
- native app shell (별 티켓)
risk_hotspots:
- pages-router iframe 결제
- third-party wallet token refresh
slack_thread: "(링크 — 스레드가 범위의 진실인 날이 있다)"
안 생기는 곳 — 과장하지 않을 것
솔직해야 글이 산다.
- 우선순위와 정치(자원 배분) 는 AI가 해결 못 한다. 오히려 빨리 치면 더 빨리 잘못된 것을 만든다.
- 프로덕션 장애의 윤리 — 누가 롤백할지, 고객에게 뭐라 말할지.
- 팀 규범과 충돌할 때의 대화 — “문서에 없는데 왜 했나요?” 같은 건 여전히 사람.
- 커밋 메시지에 ‘쿠델러로 씀’은 안 찍힌다. 깃으로 AI 효과를 증명하려 들면 싸움이 난다.
그래서 나는 뭐라고 말하고 싶냐
“에이전트가 개발자를 대체한다”가 아니라,
횡단 작업에서 맥락 비용이 제일 비싼데, 그 비용을 한 번 호출로 압축할 수 있다고 말하고 싶다.
첫 번째 대형 횡단에서는 그 압축기가 없었다.
두 번째에서는 있었다. 기능 난이도가 같았다면 손가락만으로 승부했을 텐데, 현실은 다르고, 그래도 지침의 곡선은 분명히 달랐다.
과장 한 스푼 더:
“시간이 반으로 줄었다”보다, “같은 두뇌로 한 주에 한 겹 더 올라갔다” 쪽이 진실에 가깝다.
마치며 — 생산성 지점 체크리스트 (나만의)
배포 전에 나는 이런 질문을 한다.
- 이번 주 탐색을 덜 했는가, 아니면 확인을 덜 했는가? (후자면 위험.)
- 반복 편집을 에이전트에게 맡긴 부분의 인터페이스(타입·이름) 는 내가 고정했는가?
- 횡단 누락 표를 만들었는가?
- PR 첫 문단에 의도가 서 있는가?
- 런칭 후 한 주 동안 가설 교체 속도가 빨라졌는가?
전부 예라면, 그 주의 생산성은 도구 덕이 아니라 내가 레버리지를 잡은 위치 덕이다.
도구는 레버를 길게 만들어 줄 뿐이다.
한 줄 결: 생산성은 타이핑 속도가 아니라 맥락 비용에서 깎인다. 에이전트는 그 비용이 가장 비싼 횡단 구간에서, 레버의 길이를 늘려 준다.