Cursor + Git Worktree 병렬 개발 한계와 해법

Context engineering으로 개발 생산성 N배 극대화

Pepper • Hi, im pepper! im Software engineer🙂

  • 엔지니어링

안녕하세요, 채널톡 소프트웨어 엔지니어 페퍼입니다!

채널톡에서 병렬로 브랜치 작업을 진행하며 겪은 문제들과, 이를 해결하기 위해 어떤 방법들을 사용했는지 정리했습니다. 병렬 브랜치 작업을 시도하시는 분들에게, 채널톡은 어떤 문제를 마주했고 이를 어떻게 풀었는지, 또 알면 미리 좋은 팁들을 공유하고자 합니다.

문제 : Cursor는 일하지만 나는?


채널톡에선 개발 IDE로 Cursor AI를 사용합니다. Cursor를 이용하여 개발을 하다보면 개발 속도가 늘고, 테스트 코드를 더 꼼꼼하게 짤 수 있죠. 더 나아가 엔지니어는 제품 개발의 더 중요한 부분에 집중할 수 있게 됐어요. 컴퓨터 공학부 이광근 교수는 '컴퓨터 과학이 여는 세계' 책에서 AI의 발달로 인해 사람은 인간 본연의 일을 할 수 있게 된다고 했죠. 즉 더 중요한 일을 할 수 있게 됐습니다. 하지만 명과 암은 항상 함께 하듯, 자연스레 여러 문제점과 개선 됐으면 하는 부분이 생겨났습니다.

Cursor를 이용하여 개발하니 멍하니 있는 시간이 종종 생겼습니다. Cursor에게 지시한 코드 작성 작업이 끝날 때 까지 기다리는 시간이죠. '그동안 다른 일을 하고 있으면 되지 않는가?' 의문을 가지실 수 있습니다. 맞습니다. 아키텍처를 재점검 할 수도 있고, 장애 발생 가능 지점을 확인하거나 다른 팀원들의 연락에 답장을 할 수도 있습니다. 다만 일을 하다보면 코드 작성 할 일만 남을 때가 있기도 해서 이런 멍 때리는 시간을 완벽히 피할 순 없습니다.

서로 다른 Repository에 있는 코드 작업을 여러개 해야할 경우엔 Cursor를 여러개 띄우면 해결됐습니다. 하지만 하나의 레포에서 여러 PR을 작업하고 싶은 경우엔 문제가 생겼습니다. 커서가 코드 작성을 하고 있을 때 새로운 PR로 checkout하면 코드 base가 바뀌게 되죠. 이 문제를 해결하기 위해 채널에선 두가지 시도를 했습니다.

시도한 해결 방법


git clone: 1차 공유 후 얻은 해결법

처음으로 시도한 방법은 git clone이였습니다. 관련 고민을 팀장에게 공유 했는데, git clone 하는 방식을 소개 해주셨어요. 시도해보니 git clone으로 병렬 PR 작업을 할 수 있었지만 여러 문제점이 존재했어요.

  • 문제점1 : git clone 할 때 마다 기존에 clone된 레포와 다른 폴더 이름을 새로 지정해야 함.

  • 문제점2 : git remote add도 매번 필요.

  • 문제점3 : 실수 가능성이 높음. git checkout develop or main을 잘못 실행하면 IDE indexing이 다시 시작. Cursor의 긴 indexing 시간을 생각 했을 때, 이는 굉장히 불편한 일.

git worktree : 2차 공유 후 얻은 해결법

팀의 Weekly scrum에선 이번 주에 겪은 문제와 해결한 방법 및 얻은 교훈을 나눕니다. 이때 git clone 문제를 공유했습니다. 이 문제에 대해 팀원 @clo는 git worktree을 추천했습니다. clone, remote add, indexing 등 많은 문제를 해결 할 수 있다고 했죠. 그 후 git worktree를 사용한 결과, Cursor와 함께 브랜치 병렬 작업 하기 아주 적합하다고 판단했습니다. 2개 이상의 PR을 동시에 작업할 수 있었죠. 리서치 결과, Git worktree를 AI IDE와 사용하는 방법은 Claude code에서도 권장하는 방법이기도 했습니다.

Common workflows - Anthropic

Learn about common workflows with Claude Code.

Anthropic

Anthropic

Common workflows - Anthropic

지금 부터 실제 적용 예시, 도입 효과, 도입시 겪는 문제점과 그 해법, 나아가 실전 tip까지 공유 드리겠습니다. 그 전에 Git worktree가 무엇인지 간단하게 설명해드리겠습니다.

Git worktree란?

  • 같은 레포지토리에 붙어 있는 여러 브랜치를 관리할 때 사용하는 도구입니다.

  • 하나의 레포지토리에 연관된 worktree는 main worktree와 linked worktree로 분류되죠. main worktree는 git init, git clone을 통해 만들어집니다. 그에 반해 linked worktree는 main worktree와 linked worktree에서 만들어집니다.

  • git clone과 달리 브랜치와 커밋 히스토리를 공유합니다.

  • 사용 방법 : 공식 문서와 타 블로그에서 많이 다루니 여기서 작성하지 않았습니다:)

도입 효과


개발 생산성 향상

Git worktree와 Cursor와 함께 개발을 하니 단일 레포에서 병렬로 코드 작업 할 필요가 있을 때 작업 속도가 2배 이상 늘었습니다. 단순히 다수의 PR을 동시에 작업할 수 있어서가 아닙니다. 브랜치별 작업 환경이 완전히 분리된 것이 핵심입니다. 먼저, IDE indexing을 매번 할 필요 없어졌습니다. 더 빠르게 AI에게 작업을 전달할 수 있게 됐죠. 다음으로 AI Agent가 실행 가능한 코드를 작성할 수 있는 환경을 만드는데 큰 도움이 됩니다. 코드 작성을 AI Agent에 맡길 경우엔 컴파일 및 테스트를 실행할 수 있는 독립적인 환경을 쉽게 설정할 수 있는 것이 중요합니다. 그래야 AI가 자신이 작성한 코드를 쉽게 검증할 수 있죠. Git worktree는 브랜치간 환경을 독립적으로 분리 하여 AI Agent에게 코드 작업을 대리하는데 유리한 환경을 만듭니다.

실제 적용 예시


단일 레포에서 병렬로 브랜치 작업할 경우에 사용해주세요 🙂

1. 첫번째 브랜치의 작업 명세서를 작성합니다.

# AsyncDirect 리팩토링 명세

## 목표

현재 AsyncDirect 클래스의 복잡성을 줄이고, 책임을 적절히 분리하여 유지보수성과 가독성을 개선합니다.

## 주요 개선 사항

  1. ThreadPool 인스턴스 변경

    • ...

  2. ThreadPool 생성 책임 분리

    1. ...

  3. 생명주기 관리 단순화

    • ...

  4. 메트릭 등록 로직 분리

    • ...

  5. 불필요한 상태 관리 제거

    • ...

2. 명세서를 만족하는 구현을 완성하기 위한 sub task들을 Cursor와 함께 작성합니다.

3. worktree를 생성 후 작업 명세서를 전달합니다.

  1. 먼저 git clone을 한 main worktree로 갑니다.

Plaintext
cd main-repo
  1. 새로운 작업을 진행할 브랜치를 linked worktree로 만듭니다. branch-name 이름의 브랜치를 만든 후 main-repo-branch-name의 path에 코드를 가져오는 작업입니다. 폴더 명을 헷갈리지 않기 위해 repository 이름 뒤에 postfix로 브랜치 이름을 설정하길 권장합니다.

Plaintext
git worktree add ../main-repo-branch-name -b branch-name
  1. [선택] 필요한 경우, 로컬 개발 환경을 초기화 진행합니다. 채널에서는 update proto, flyway migrate(jOOQ를 사용하기 때문) 등 로컬 개발을 진행하기 전에 필수로 해야할 작업이 있습니다.

Plaintext
cd .. & cd main-repo-branch-name & {로컬 개발 환경 초기화 스크립트 실행 명령어}
  1. Cursor에게 '서브 작업 명세서'와 함께 작업을 지시합니다.

4. 병렬로 진행할 두번째 브랜치의 작업의 명세를 작성합니다.

5. 명세서를 만족하는 구현을 완성하기 위한 sub task들을 Cursor와 함께 작성합니다.

6. 병렬 브랜치 작업을 위해, worktree를 생성 후 작업 명세서를 전달합니다.

  1. 3번의 작업을 다시 한번 진행하여 worktree를 생성합니다.

  2. Cursor에게 '서브 작업 명세서'와 함께 작업을 지시합니다.

7. 병렬로 코드 작업을 진행한다.

커서가 작업중인 코드 작업이 완료될 경우, 다음 서브 테스크 명세서와 함께 코드 작업을 지시합니다.

스레드 풀 개선 작업 두번째 sub task

예약 메세지 개발 작업 두번째 sub task

도입시 겪는 문제와 해법


1. E2E 테스트 병렬 실행으로 인한 문제 발생 가능성

1. 웹 서버가 같은 포트에 뜨는 문제

그림1과 2는 서로 다른 worktree입니다. 동시에 테스트를 실행하면 그림 1은 통과하되 그림 2는 서버 조차 뜨지 못했습니다. 그림 3과 같은 상황이라고 볼 수 있습니다. 이는 간단하게 해결할 수 있습니다. 테스트를 실행 할 때 웹서버가 올라오는 포트를 랜덤으로 설정하면 됩니다.

2. 테스트 DB가 이미 포트를 점유하고 있는 문제

테스트 DB 포트가 같은 것 또한 문제가 될 수 있습니다. 서로 다른 worktree에서 병렬로 실행했을 때 일부 테스트는 통과하고 일부 테스트는 성공합니다. 타이밍 이슈로 테스트가 부분적으로 통과하게 됩니다. 그림 3과 같은 상황입니다.

테스트용 DB가 랜덤 포트에서 뜨도록 설정하여 해결 할 수 있습니다. Testcontainer를 사용하는 경우엔 random port로 사용하는 설정을 이용하면 됩니다. 실제로 Testcontainer 공식 홈페이지에선 'From the host's perspective Testcontainers actually exposes this on a random free port. This is by design, to avoid port collisions that may arise with locally running software or in between parallel test runs.'라고 말하죠.

2. 잦은 작업 Context switching으로 인한 뇌 부하

다수의 브랜치 작업을 병렬로 진행할 경우 서로 다른 작업 Context를 짧은 시간에 다시 이해 해야 했습니다. A 브랜치의 worktree에서 커서를 이용하여 작업을 시킨 뒤 B 브랜치의 worktree에서 커서로 작업을 시키면 뇌에서 한번의 Context switching이 일어납니다. 그러다 A worktree에서 작업이 완료되면 이를 확인 하기 위해 다시 기획 내용과 설계한 순차 다이어그램을 상기 하기 위해 뇌에서 Context switching이 일어나죠. 이로 일한 뇌 피로도는 상당했습니다.

Linear와 Plan and Act rule을 이용하여 이를 해결할 수 있었습니다. 자세한 내용은 Context Engineering? 원래 하던거 아닌가?를 참고해주세요. 이곳에선 함축적인 내용만 담았습니다:)

Context Engineering? 원래 하던거 아닌가?

채널팀의 Linear MCP 적응기

Channel.io

Channel.io

Context Engineering? 원래 하던거 아닌가?

PLAN and ACT rule을 이용하여 작업 명세서와 서브 테스크 명세서를 완성

명세서와 계획서 같은 문서를 작성하는 행위는 '계획'에 해당됩니다. 코드를 작성하는 행위는 '실행'이 되죠. 이에 문서를 잘 작성하기 위해 계획과 실행을 명확히 분리하는 것이 좋습니다. 하지만 AI IDE를 이용할 땐 보통 이를 분리하기 어렵습니다. 설계를 위한 논의 중에 AI IDE는 종종 혹은 자주 코드를 반영하죠. 이에 보통 '채팅에서만 먼저 논의하자', '코드를 먼저 작성하지 말아줘' 혹은 '채팅에서만 적용된 코드를 보여줘'와 같은 프롬프트를 추가했었죠. 채널에선 이를 해결 하는 방법으로 PLAN and ACT cursor rule를 도입했습니다. 이 규칙을 도입하면 채팅 컨텍스트에서 'ACT'라고 명시적으로 말하기 전까진, 'PLAN' 모드이기 때문에, 코드 작업을 하지 않습니다. PLAN 모드에서 작업 명세서를 바탕하여 커서와 함께 서브 테스크 명세서(코드 작업 계획서)를 만들었고 이를 Linear에 저장했습니다.

PLAN and ACT rule은 always 모드로 적용 했습니다. always 모드를 사용하면 이 Repository를 적용하는 모든 개발자에게 적용되기에 조심스러웠지만, 빠르게 실험하고 검증하는 것이 중요하기에 팀과 논의 후 바로 적용했습니다.

아래는 채널에서 사용중인 PLAN and ACT rule입니다. Rule은 깃허브 오픈 소스에서 사용하는 것을 그대로 사용했습니다. 이대로 사용해도 아무 문제 없기에 추가 수정을 하지 않았습니다.

Plaintext
---
description: 
globs: 
alwaysApply: true
---
## Core Rules

You have two modes of operation:

1. Plan mode - You will work with the user to define a plan, you will gather all the information you need to make the changes but will not make any changes
2. Act mode - You will make changes to the codebase based on the plan

- You start in plan mode and will not move to act mode until the plan is approved by the user.
- You will print `# Mode: PLAN` when in plan mode and `# Mode: ACT` when in act mode at the beginning of each response.
- Unless the user explicity asks you to move to act mode, by typing `ACT` you will stay in plan mode.
- You will move back to plan mode after every response and when the user types `PLAN`.
- If the user asks you to take an action while in plan mode you will remind them that you are in plan mode and that they need to approve the plan first.
- When in plan mode always output the full updated plan in every response.

Linear를 이용한 Context engineering을 활용

작업 명세서는 개발자가 당연히 작성하겠지만, 서브 작업 명세서 혹은 코드 구현 계획서를 개발자가 직접 작성할 필요가 있을까요? 이를 작성하는 시간에 개발자가 직접 코드 작업을 하는 것이 낫지 않을까요?' AI IDE 등장 전에는 '그렇다'고 생각합니다. 하지만 현재는 AI IDE에게 코드 구현 계획서를 작성하라고 지시하면 됩니다. 코드 구현 계획서는 커밋 단위로 작성하는 것이 좋습니다. PR 1개를 만들 때 작업의 전체 내용을 포괄하는 코드 구현 계획서를 리니어 이슈(부모 이슈)에 담고, 그 계획을 달성하기 위해 완수 해야할 sub task들을 리니어 이슈에 작성하면 됩니다(서브 이슈). Sub task는 코드 구현 계획서이기에 커밋 단위가 될 수 있습니다. Sub task가 너무 많아질 일도 없습니다. 1개의 PR의 diff가 2~400자 이하인 것이 이상적인 것을 고려하면, Sub task은 5개를 잘 넘지 않습니다.

적용 tip


  1. Memory bank의 PLAN and ACT 모드와 함께 사용해야 강력합니다.

  2. Context engineering(with linear or jira or notion..)을 적극적으로 활용해주세요. 그래야 병렬로 진행되는 작업들에 대한 context를 잃지 않을 수 있습니다(채널톡 블로그에서 발행한 'Context Engineering? 원래 하던거 아닌가?'를 참고해주세요🙂)

  3. Development 브랜치에서 커서와 함께 작업하지 말고 Git worktree를 파서 작업하길 권장합니다. worktree는 Development 브랜치에서 만들어야 하는데, 해당 브랜치가 작업중이면 새 worktree를 만들기가 어렵습니다.

  4. 로컬 개발 환경 초기화가 필요하다면 이를 따로 스크립트화 하자. jOOQ(Java Object-Oriented Querying) 등을 이용할 경우 로컬에서 테스트를 실행하기 전에 jooq code generate가 필수적입니다.

맺음말


채널 팀에선 AI를 이용하여 불필요한 일을 줄이고 더 본질적인 문제를 해결하는데 집중할 수 있는 환경을 만들고 있어요. 이때 가장 중요한 것은 빠른 실험과 검증이라고 생각해요.

채널 팀과 함께 비즈니스 임팩트가 크고 본질적인 문제를 해결하기 위한 환경을 만들어 가고 싶다면 채용 공고를 확인해주세요!

We Make a Future Classic Product