모노레포에서 FE 협업을 위한 Ai Infra 세팅하기

Lennon·2026년 8월 17일
post-thumbnail

들어가며

안녕하세요. 프론트엔드 개발자 Lennon입니다.

이전 회고 글에서 클로드 코드 Max가 지원됨에 따라 업무에 어떻게 효율적으로 녹여낼지도 하나의 과제가 될 것 같아요 라고 적었었는데요, 이번 글이 해당 내용의 일부일 것 같아요.

요즘 AI 코딩 툴을 사내에 도입하신 분들이 정말 많을 것 같아요. 그런데 막상 팀에 들이고 나면 개인이 잘 쓰는 것과 팀이 잘 쓰는 건 꽤 다른 문제라는 걸 느끼게 됩니다.

저희 상황을 먼저 말씀드리면, 하나의 모노레포에서 세 팀의 프론트엔드 개발자가 각자 다른 영역을 개발하고 있습니다. 그래서 아래 두 가지를 바랐어요.

1. 누가 어떤 작업을 하든 코어 컨벤션은 항상 지켜지길 바랐다.
2. 각자의 작업 범위에 맞는 문서만 컨텍스트로 올라오길 바랐다.

이 두 가지를 .claude 세팅으로 풀어낸 이야기를 해보려고 합니다.

혹시 더 좋은 접근이 떠오르신다면 댓글 남겨주시면 감사드리겠습니다 🙂

왜 세팅이 필요했나

저희 레포는 Turborepo 기반 모노레포이고, 앱 세 개(Portal, Brand, Hub)와 여러 패키지로 구성되어 있습니다.

여기서 중요한 건 영역별로 소유한 팀이 다르다는 점이에요.

경로소유
apps/brand, apps/hub, apps/portal/app/(core)/**, domains, features, sharedCore
apps/portal/app/(stores)/stores/[storeId]/dodopoint/**Dodopoint 팀
packages/dodopoint-portal/**Dodopoint 팀
apps/portal/app/(stores)/stores/[storeId]/nowwaiting/**Nowwaiting 팀
packages/nowwaiting-portal/**Nowwaiting 팀

같은 apps/portal 안에서도 라우트를 나눠 갖고 있는 형태입니다. 그리고 Dodopoint / Nowwaiting 팀도 Core가 정의한 공통 규칙은 지켜야 하고요.

이 상태에서 세팅 없이 AI를 쓰면 두 가지가 걱정이었어요.

하나는 사람마다 결과가 다르다는 점입니다. 누군가는 "우리는 AsyncBoundary로 감싸고 props 타입명은 Props야"를 매번 적어주고, 누군가는 안 적어줍니다. 그러면 같은 기능인데도 PR 모양이 달라져요.

또 하나는 컨텍스트를 매번 손으로 알려줘야 한다는 점입니다. 나우웨이팅 작업을 시작할 때마다 "이건 독립 앱이 아니고 Portal에 마운트되는 패키지야, Core 영역은 건드리면 안 돼"를 설명하는 건 좀 아깝잖아요. 새로 합류하신 분이라면 그 설명 자체를 모르실 수도 있고요.

즉 저희가 원한 건 공통 규칙은 항상 + 팀 규칙은 해당 작업일 때만 이었습니다.

그럼 어떻게 나눌까

앞의 두 조건을 같이 만족시키는 게 생각보다 까다로웠습니다. 서로 방향이 반대라서요.

한 곳에 다 모으면 공통 규칙은 확실히 지켜집니다. 대신 나우웨이팅 패키지만 만지는 작업에도 Hub, Brand 문서까지 전부 딸려옵니다. 2번 조건이 깨지죠.

영역별로 쪼개면 작업 범위에 맞는 문서만 붙습니다. 대신 AsyncBoundary 패턴이나 Props 타입 규칙 같은 공통 컨벤션을 영역마다 복사해둬야 해요. 다섯 군데에 같은 내용이 있으면 규칙이 하나 바뀔 때 다섯 군데를 고쳐야 하고, 현실적으로 한두 군데는 빠뜨리게 됩니다. 그러면 팀마다 기준이 갈리기 시작하니 1번 조건이 오히려 더 위험해집니다.

정리하면 범위를 좁히려면 중복이 생기고, 중복을 없애려면 범위가 넓어지는 구조였어요.

✅ 규칙은 경로로 스코프, 내용은 따로

그래서 정리한 방향은 이렇습니다.

규칙 파일(rules)  = "어떤 경로를 작업할 때, 어떤 문서를 붙일지"만 선언한다
내용 파일(context) = 실제 아키텍처·컨벤션·정책 내용을 담는다

선언과 내용을 분리하면 같은 내용 파일을 여러 규칙이 가리킬 수 있어서 중복이 사라집니다. 그리고 규칙 파일만 열어보면 "이 경로를 만지면 무슨 문서가 붙는지"가 한눈에 보이게 되고요.

이제 실제 구조를 보겠습니다.

.claude 구조 사전 설명

폴더는 네 덩어리입니다.

- 🗂️ .claude
    - 📑 settings.json                 권한·언어 등 레포 공용 설정
    - 🗂️ rules                         경로별 규칙 진입점
        - 📑 global.md                 항상 적용
        - 📑 apps.md                   apps/**
        - 📑 portal.md / hub.md / brand.md
        - 📑 portal-packages.md        packages/{dodopoint,nowwaiting}-portal/**
        - 📑 nowwaiting-portal.md / dodopoint-portal.md
    - 🗂️ context                       rules에서 import할 문서들
        - 📑 conventions.md
        - 📑 architecture.md
        - 📑 packages.md
        - 📑 policy-entry.md
        - 🗂️ apps / nowwaiting-portal / dodopoint-portal ...
            - 📑 architecture.md
            - 📑 policy.md
    - 🗂️ commands
        - 📑 commit.md / pr.md / review.md 등등,,

rules — 경로가 곧 팀 경계

rules 아래 파일들은 frontmatter에 paths를 적어둡니다. 해당 경로의 파일을 작업할 때만 이 규칙이 컨텍스트로 올라옵니다.

apps 공통 규칙은 이렇게 생겼어요.

---
paths:
  - "apps/**/*"
---

# apps/ 공통 규칙

@.claude/context/apps/architecture.md

그리고 global.md에는 paths가 없습니다.

# 모노레포 전역 규칙

@.claude/context/packages.md
@.claude/context/conventions.md

@.claude/context/architecture.md

## 정책 진입점

@.claude/context/policy-entry.md

경로 조건이 없으니 항상 적용됩니다. 처음에 원했던 1번 조건이 여기서 해결됩니다. 어느 팀이 어디를 만지든 컨벤션과 전체 아키텍처는 무조건 붙습니다.

두 팀이 규칙을 공유하는 경우

Dodopoint / Nowwaiting 두 팀은 각각 자기 패키지를 갖고 있지만, 두 팀이서 서로 리뷰를 하기에 공용 규칙을 정의하는 목적이었습니다.
그래서 그 공통 부분은 paths를 두 개 적은 파일 하나로 처리했어요.

---
paths:
  - "packages/dodopoint-portal/**/*"
  - "packages/nowwaiting-portal/**/*"
---

# Portal 패키지 공통 규칙

@.claude/context/portal-packages/architecture.md

앞에서 걱정했던 중복 문제가 이 지점에서 해결되는 것 같아요. 두 팀에 같은 내용을 복사하는 대신, 규칙 파일이 같은 문서를 가리키게 만들면 되니까요.

정리하면

경로를 건드릴 때 붙는 문서는 이렇게 누적됩니다.

작업 경로적용되는 규칙
어디든global
apps/portal/**global + apps + portal
apps/hub/**global + apps + hub
packages/nowwaiting-portal/**global + portal-packages + nowwaiting-portal
packages/dodopoint-portal/**global + portal-packages + dodopoint-portal

나우웨이팅 작업에는 Hub나 Brand 문서가 올라오지 않습니다. 반대로 어떤 작업이든 conventions.md는 빠지지 않습니다.

개인적으로는 이 구조의 가장 큰 장점이 팀 경계가 파일로 드러난다는 점인 것 같아요. rules 폴더만 열어봐도 이 레포에 몇 개의 영역이 있고 각자 무슨 문서를 기준으로 삼는지가 보입니다. AI를 위한 세팅으로 시작했는데, 사람이 읽기에도 괜찮은 지도가 된 셈이에요.

context — 규칙은 얇게, 내용은 따로

@경로 문법은 해당 파일을 그 자리에 끼워 넣어주는 import 같은 개념입니다. 그래서 rules는 조립 설명서 역할만 하고, 살은 전부 context에 있습니다.

이렇게 나눈 이유는 두 가지입니다.

하나의 문서를 여러 규칙이 가리켜야 했습니다. 위의 portal-packages 케이스처럼요. 규칙 파일에 내용을 직접 적어버리면 이게 불가능합니다.

수정 빈도가 다릅니다. "어느 경로에 어떤 문서를 붙일지"는 팀 구성이 바뀔 때나 손대지만, 컨벤션 문서는 새 패턴이 정해질 때마다 고칩니다. 덕분에 PR에서 rules/가 바뀌면 "구조가 바뀌었다", context/만 바뀌면 "내용이 바뀌었다"로 읽히기도 하고요.

구조 축 / 도메인 축

context 안에서 문서를 또 두 종류로 나눴습니다.

architecture.md  → 코드가 어떻게 생겼는지 (레이어, import 방향, 폴더 구조)
policy.md        → 비즈니스 규칙이 무엇인지 (상태값, 권한, 도메인 정책)

처음엔 굳이 나눌 필요가 있나 싶었는데, 실제로 써보니 물어보는 성격이 완전히 다릅니다.

"이 컴포넌트를 어느 폴더에 둬야 하지?"는 아키텍처 질문이고, "이 상태에서 이 버튼이 보여도 되나?"는 정책 질문이에요. 전자는 저희가 정하는 것이고, 후자는 기획·정책 문서가 정하는 것이니 원본도 다르고 최신화 주기도 다릅니다.

그래서 앱·패키지마다 두 파일이 나란히 있는 형태가 되었습니다.

commands — 리뷰 기준을 팀 공용 명령으로

commands 폴더에 md 파일을 두면 /파일명으로 호출할 수 있는 커맨드가 됩니다. 저희는 네 개를 만들었어요.

/commit              변경사항을 컨벤션에 맞는 커밋으로
/pr                  PR 제목·본문 생성 후 draft PR
/review              컨벤션·아키텍처·정책 3축 리뷰
등등

/commit, /pr은 이전 글에서 다뤘던 커밋 메시지·PR 템플릿 자동화와 결이 비슷합니다. 이미 팀에 있는 규칙을 커맨드도 알고 있게 만든 정도예요.

뒤의 두 개가 이 세팅에서 하려던 것에 더 가깝습니다.

/review리뷰 기준을 사람 머릿속이 아니라 파일에 둔 것입니다. 컨벤션이나 레이어 위반은 눈에 보이지만, "정책과 실제로 맞는지"는 문서를 외우고 있지 않으면 못 잡거든요. 그래서 세 축을 어떤 순서로 보고, 정책 위반은 어떤 심각도로 두고, 근거 없는 지적은 어떻게 처리할지를 커맨드 문서에 적어뒀습니다.

커맨드는 frontmatter로 사용할 도구를 제한할 수도 있습니다. 리뷰 커맨드에는 읽기 계열만 열어뒀어요. 리뷰를 시켰는데 파일이 고쳐져 있으면 곤란하니까요.

두 커맨드의 공통점은 반복되는 판단과 절차를 문서로 굳혔다는 점입니다. 리뷰 기준이 사람마다 달라지지 않고, 새로 합류하신 분도 커맨드 한 번으로 자기 팀 경계를 보게 됩니다.

AI에게 주는 문서는 금방 썩는다

여기까지가 구조 이야기였고, 이 섹션은 운영하면서 가장 크게 깨달은 부분입니다.

정책 진입점 문서를 만들 때 처음엔 이렇게 하고 싶었어요.

정책 문서를 매번 원격에서 읽는 건 느리니까, 핵심 수치와 규칙을 .claude 안에 요약해두자.

그런데 이게 위험합니다. 원본 정책 문서는 계속 바뀌거든요. 정책이 추가되고, 상태값이 하나 늘고, 기한이 조정됩니다. 그때 .claude 안의 요약본은 아무도 안 고칩니다. 틀렸다는 신호가 어디에도 안 뜨니까요.

그리고 요약본이 낡았을 때가 요약본이 없을 때보다 나쁩니다. 없으면 원본을 찾아보지만, 있으면 그걸 믿고 그대로 코드를 짜게 되니까요. 조용히 틀린 코드가 나오는 게 제일 무서운 것 같아요.

✅ 값은 담지 않고, 위치만 담는다

정책은 github repo에서 md로 관리되기에, gh로 항상 최신 정책을 바라보도록 적용했어요.

그래서 이 문서엔 어떤 원본이 있고, 우리 코드의 어느 부분이 어디에 대응하고, 그걸 어떻게 가져오는지만 둡니다. 실제 값이 필요하면 그때 원본을 읽어요. 조금 느려지지만 틀릴 일이 없습니다.

마무리

이번 글에선 모노레포에서 세 팀이 협업하기 위한 .claude 세팅 경험을 공유해 보았습니다.

정리하면 이렇습니다.

공통 규칙은 paths 없는 전역 규칙으로 항상 적용
팀 규칙은 paths로 작업 경로에 스코프
선언(rules)과 내용(context)을 분리해 중복 제거
아키텍처(구조)와 정책(도메인)을 다른 문서로 분리
반복하는 판단(리뷰 기준·세션 시작)은 커맨드로 고정
정책 원본은 복사하지 않고 위치만 가리킨다

핵심은 결국 누가 어디를 만지든 지켜야 할 건 항상 붙고, 그 외엔 필요한 것만 붙는다 한 줄인 것 같아요.

당연하게도 정답은 아닙니다. 저희는 팀 경계를 경로로 깔끔하게 나눠지길 원해 그대로 서비스의 pacakges화를 진행해 paths 기반 분리가 잘 맞았지만, 한 폴더를 여러 팀이 함께 만지는 구조라면 다른 접근이 필요할 것 같습니다.

조금 더 개선할 수 있는 부분이 보인다면 언제든지 댓글 달아주세요 🙂

긴 글 읽어주셔서 감사합니다.

profile
좋은 글을 쓰려 노력합니다. 제 경험이 누군가에게 도움이 되기를 바랍니다 🌊

0개의 댓글