TypeScript와 Next.js 최적화를 위해 4,000줄짜리 에이전트 스킬을 만든 이유

TypeScript와 Next.js 최적화를 위해 4,000줄짜리 에이전트 스킬을 만든 이유

#TypeScript와 Next.js 최적화를 위해 4,000줄짜리 에이전트 스킬을 만든 이유

문제

저는 프론트엔드 작업을 할 때 Claude Code를 자주 쓰고, 가끔 Codex도 함께 씁니다. 그런데 거의 매일 비슷한 실수를 다시 고치게 됩니다.

// AI가 이렇게 생성함 const user: User = await res.json();

겉보기에는 멀쩡합니다. TypeScript도 아무 말 안 하죠. 하지만 res.json()은 런타임에서 any를 반환합니다. API 응답 형태가 바뀌면, 이 코드는 조용히 프로덕션에서 깨질 수 있습니다.

// 이것도 AI가 정말 자주 만듭니다 const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState<Error | null>(null); const [data, setData] = useState<User | null>(null);

상태를 세 조각으로 나누면, 실제로는 말이 안 되는 조합이 가능해집니다. isLoading: true인데 data가 이미 있다거나, error가 있는데도 isLoading이 여전히 true인 상태 같은 것들 말이죠.

그리고 개인적으로 가장 자주 보는 패턴은 이것입니다.

"use client"; // 페이지 컴포넌트에 일단 붙여버림 export default function ProductPage() { // ...결국 페이지 전체가 클라이언트 렌더링됨 }

이건 드문 엣지 케이스가 아닙니다. 오히려 너무 자주 반복됩니다. 이유는 간단합니다. AI 에이전트가 참고할 수 있는, 구조화된 프론트엔드 TypeScript 패턴 레퍼런스가 부족하기 때문입니다.

그때그때 고치면 되는 것 아닌가?

저도 그렇게 했습니다. 몇 달 동안은요. 그러다 어느 순간 이런 생각이 들었습니다.

  • 매번 똑같은 패턴을 반복해서 수정하고 있다
  • 이 수정 내용이 세션 사이에 남지 않는다
  • 새 대화가 시작될 때마다 다시 처음부터 설명해야 한다

결국 제게 필요했던 건, 에이전트가 코드를 생성하기 전에 먼저 읽을 수 있는 기준서였습니다. 채팅창에 붙여 넣는 튜토리얼이 아니라, 자동으로 참고할 수 있는 구조화된 레퍼런스 말이죠.

내가 만든 것

typescript-react-patterns 는 Claude Code, Cursor, Codex, 그리고 SKILL.md를 읽을 수 있는 어떤 AI 도구에서든 사용할 수 있는 Agent Skill입니다.

총 17개 파일, 4,000줄 이상으로 구성되어 있고, 구조는 크게 세 부분입니다.

typescript-react-patterns/ ├── SKILL.md 허브: 에이전트 규칙, 의사결정 가이드, 체크리스트 ├── rules/ 11개의 패턴 모듈 ├── typescript-core.md ├── react-typescript-patterns.md ├── nextjs-typescript.md ├── component-patterns.md ├── data-fetching-and-api-types.md ├── forms-and-validation.md ├── state-management.md ├── performance-and-accessibility.md ├── debugging-checklists.md ├── code-review-rules.md └── anti-patterns.md └── playbooks/ 3개의 디버깅 가이드 ├── type-error-debugging.md ├── hydration-issues.md └── effect-dependency-bugs.md

무엇이 다른가

시중에 에이전트 스킬은 이미 많습니다. 하지만 대부분은 코드 스니펫 모음에 가깝습니다. 이 스킬은 단순히 패턴을 보여주는 것이 아니라, 에이전트가 어떤 패턴을 선택해야 하는지 판단하도록 돕는 의사결정 지원 도구로 설계했습니다.

1. 코드를 쓰기 전에 먼저 점검하게 한다

이 스킬은 에이전트에게 코드 작성 전에 먼저 확인할 것을 요구합니다.

  • 이 코드는 서버 코드인가, 클라이언트 코드인가?
  • 런타임 검증이 필요한가? 외부에서 들어오는 데이터라면 답은 거의 항상 Yes입니다.
  • Next.js 버전은 무엇인가? 15 이상에서는 params가 Promise입니다.
  • 지금 절대 가정하면 안 되는 것은 무엇인가?

이런 질문을 먼저 던지게 만드는 것만으로도, 생성되는 코드 품질이 꽤 달라집니다.

2. 패턴 모음이 아니라 의사결정 플로우차트가 있다

중요한 건 "어떤 패턴이 있는가"보다 "지금 어떤 패턴을 써야 하는가"입니다.

데이터가 서버/API에서 오는가? ├─ TanStack Query 사용 (useState 아님) └─ 아니오 URL로 공유되어야 하는가? ├─ searchParams 사용 └─ 아니오 개의 컴포넌트가 상태를 쓰는가? ├─ 1개 useState └─ 여러 selector와 함께 Zustand

이런 식의 플로우차트와 결정 기준이, 예제 10개보다 실제로 더 도움이 됩니다.

3. 규칙을 강도별로 분류했다

모든 규칙이 같은 무게를 가지면, 에이전트는 사소한 취향 차이도 절대 규칙처럼 받아들입니다. 그래서 규칙을 세 가지로 나눴습니다.

  • [HARD RULE]: 어기면 버그가 날 가능성이 높은 규칙. 예외 없음 예: "API 응답은 런타임에서 검증하라."
  • [DEFAULT]: 특별한 이유가 없으면 따르는 기본값 예: "Props는 interface를 우선 사용하라."
  • [SITUATIONAL]: 상황에 따라 달라지는 규칙 예: "Polymorphic component는 디자인 시스템의 기반 컴포넌트에서만 고려하라."

이 분류를 넣고 나서, 에이전트가 모든 가이드를 똑같이 강제하지 않게 되었습니다.

4. 실제로 자주 터지는 Before / After 예제를 담았다

장난감 예제가 아니라, 프론트엔드에서 정말 자주 마주치는 문제를 다뤘습니다.

API 타이핑 예시

// ❌ Before const user: User = await res.json(); // ✅ After const userSchema = z.object({ id: z.string(), name: z.string(), email: z.string().email(), }); type User = z.infer<typeof userSchema>; const user = userSchema.parse(await res.json());

로딩 상태 예시

// ❌ Before — 말이 안 되는 상태 조합이 가능함 const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [data, setData] = useState(null); // ✅ After — 불가능한 상태를 타입으로 막음 type State<T> = | { status: "idle" } | { status: "loading" } | { status: "success"; data: T } | { status: "error"; error: Error };

핵심은 단순히 "더 예쁜 코드"가 아니라, 불가능한 상태를 표현할 수 없게 만드는 것입니다.

5. 디버깅 플레이북이 있다

코드를 잘 쓰는 것만큼 중요한 건, 문제가 생겼을 때 빠르게 진단하는 일입니다. 그래서 이 스킬에는 단계별 디버깅 가이드를 넣었습니다.

  • 타입 에러 아래쪽부터 읽는 법, 에러를 분류하는 법, React/Next.js에서 흔한 원인을 확인하는 순서
  • Hydration mismatch 증상에서 원인으로 따라가는 흐름도 useEffect로 해결할지, dynamic으로 분리할지, Suspense가 맞는지 판단 가능
  • useEffect 버그 무한 루프, stale closure, cleanup 누락처럼 자주 나오는 문제를 유형별로 정리

에이전트가 문제를 "고치는" 데서 멈추지 않고, "왜 고장 났는지"를 추적하게 만드는 것이 목적입니다.

6. 코드 리뷰에서 리스크와 취향을 구분한다

코드 리뷰에서 모든 지적이 같은 레벨이면 피드백이 과해집니다. 그래서 이 스킬은 리스크선호를 구분합니다.

리스크

  • API 데이터에 as 사용
  • 객체를 useEffect 의존성에 직접 넣음
  • 클라이언트 컴포넌트에서 서버 전용 모듈 import

이런 건 실제 버그 가능성이 높기 때문에 강하게 잡아야 합니다.

선호

  • type vs interface
  • 이벤트 핸들러 네이밍
  • import 정렬 방식

이런 건 언급할 수는 있지만, 막아야 할 문제는 아닙니다.

사용 방법

설치는 한 줄이면 됩니다.

git clone https://github.com/leejpsd/typescript-react-patterns ~/.claude/skills/typescript-react-patterns

에이전트는 SKILL.md를 읽고, 현재 작업 맥락에 맞는 규칙 파일을 참고합니다. 예를 들어 폼 작업을 하고 있으면 forms-and-validation.md를, 타입 에러를 다루고 있으면 playbooks/type-error-debugging.md를 읽는 식입니다.

Claude Code, Cursor, Codex, Gemini CLI처럼 SKILL.md 형식을 읽을 수 있는 도구라면 모두 활용할 수 있습니다.

무엇을 다루고 있나

모듈주요 내용
TypeScript CoreNarrowing, generics, utility types, as const, satisfies, unknown vs any
React PatternsProps, children, events, hooks, context, forwardRef, generic components
Next.jsApp Router params, Server Actions, RSC boundary, Edge, useOptimistic
Component PatternsDiscriminated Props, compound components, modal/dialog, polymorphic patterns
Data FetchingZod 검증, TanStack Query, Result<T, E>, pagination, error handling
Formsreact-hook-form + Zod, Server Actions, 멀티스텝 체크아웃 예시
State Management상태 관리 의사결정 매트릭스, Zustand, Context, URL state
Performance & A11y메모이제이션 트레이드오프, focus 관리, aria-live, 키보드 내비게이션
Anti-patterns자주 나오는 12가지 실수와 그 증상, 원인, 해결책

만들면서 배운 점

1. 양보다 구조가 중요하다

초기 버전은 파일 수가 더 많았지만 구조가 약했습니다. 지금 버전은 파일 수는 줄었지만, 각 모듈을 더 밀도 있게 정리했고 템플릿도 통일했습니다.

기본 구조는 다음과 같습니다.

  • Scope
  • Key Rules
  • Examples
  • Anti-patterns
  • Review Checklist

이렇게 틀을 맞추니 에이전트가 읽고 활용하기 훨씬 쉬워졌습니다.

2. 에이전트 스킬에는 예제보다 의사결정 지원이 더 중요하다

패턴 10개를 보여주는 것보다, 지금 어떤 패턴을 선택해야 하는지 알려주는 편이 훨씬 유용했습니다. 플로우차트와 결정 매트릭스가 단순 코드 스니펫보다 더 큰 가치를 줬습니다.

3. 규칙은 반드시 분류해야 한다

[HARD RULE], [DEFAULT], [SITUATIONAL]로 나눈 뒤 가장 큰 변화가 생겼습니다. 에이전트가 모든 가이드를 절대 규칙처럼 취급하지 않게 됐습니다.

4. 교차 참조가 중복을 막아준다

각 파일에 See also 링크를 넣어 두었습니다. 덕분에 모든 파일이 모든 내용을 반복하지 않아도, 필요한 맥락을 따라가며 읽을 수 있습니다.

기여하기

이 스킬은 MIT 라이선스로 공개되어 있고, PR도 환영합니다. 특히 아래 영역을 우선적으로 보강하고 싶습니다.

  • 테스트 패턴 Vitest, Testing Library
  • 국제화 관련 타입 패턴
  • 더 많은 디버깅 플레이북
  • 접근성 심화 가이드

직접 써 보시고 부족한 점이나 잘못된 내용이 있다면 이슈를 열어 주세요. 이 프로젝트는 한 번에 완성하는 문서가 아니라, 실제 사용을 통해 계속 다듬어 가는 레퍼런스로 만들고 싶습니다.

링크

유용했다면 GitHub에서 스타 하나 눌러주시면, 더 많은 사람이 이 프로젝트를 찾는 데 큰 도움이 됩니다.

JP
이중표Frontend Engineer

3년차 프론트엔드 개발자. Next.js, React, TypeScript 기반 웹 애플리케이션 개발 전문. 대규모 트래픽 환경에서 SSR·ISR 렌더링 전략 설계 경험.

이력서 보기