바이브 코딩(vibe coding)을 통한 개발 프로세스 개선
0. 들어가면서
아무래도 AI 관련된 기술들이 많이 등장하면서 이를 통해 어떻게 개발 효율성을 높일 수 있을지 많은 조직에서 고민하고 있는 것 같다. 현재 우리 팀도 AI를 사용해 개발 효율성을 높이기 위한 여러가지 시도를 해보고 있다. 바이브 코딩이라는 개념이 등장했을 때 조만간 개발자의 자리가 없어지진 않을까 걱정도 되었지만, 직접 바이브 코딩을 해보니 아직은 AI가 섬세한 수준의 개발은 어렵다는 생각이 들었다. 매우 구체적인 프롬프트를 작성하고 작업 단위를 아주 작게 쪼개면 가능할 것 같지만, 프롬프트를 작성할 시간에 개발자가 직접 코드를 작성하는 것이 빠르고 효율적이라고 생각한다.
서론이 길었다. 이번 글에선 코파일럿 에이전트(copliot agent)로 여러가지 시도를 해보면서 겪은 노하우나 프롬프트 작성법에 대한 내용을 일부 정리했다.
1. Approach
여러가지 테스트들을 통해 다음과 같은 인사이트(insight)를 얻었다.
- AI는 한번에 큰 작업을 하는 것에 능숙하지 못하다. 그럴싸한 결과를 내놓지만, 결과를 면밀히 살펴보면 결국 손 봐야하는 것이 많다.
- 프롬프트가 구체적이지 않다면 추론을 통해 의도하지 않은 구현을 한다.
큰 작업에 대해 매우 구체적인 프롬프트를 작성하는 것은 상당히 어려운 일이고, AI가 무지막지하게 쏟아낸 작업 내용을 리뷰하면서 수정하는 것도 개발자에겐 고역이었다. 우리는 사람이 실제로 하는 일(process)를 작은 단위의 작업(task)로 구분하기로 결정했다.
우리 팀의 웹 개발 프로세스를 크게 보면 다음과 같은 흐름을 갖는다.
- 사용자 스토리를 기반으로 프론트엔드 화면, 컴포넌트 등을 구현한다.
- 서버로 요청이 필요하다면 API 클라이언트를 구현한다.
- API 요청을 처리하기 위한 컨트롤러, 서비스, 레포지토리 계층을 구현한다.

위 흐름에서 각 단계를 자세히 들여다보면 다음과 작업을 수행한다.
- TDD 개발 방법론을 따라 각 기능들은 테스트, 구현, 리팩토링 순서를 따라 개발된다.
- 프론트엔드의 경우 피그마 작업물을 보고 화면, 컴포넌트에 디자인을 적용한다.

몇 차례 시행착오 끝에 테스트 작성
, 구현 코드 작성
과 같은 크기 수준의 작업은 AI가 수행할 떄 큰 결함 없다는 인사이트를 얻었다. AI가 이 수준의 작업을 수행했을 때 생성하는 결과의 크기는 개발자가 검토하기에 버겁지 않고, 결함이 적었기 때문에 코드 리뷰의 피로도가 낮았다.
프론트엔드 디자인을 반영하는 작업은 속도를 높이기 위해 피그마 MCP 서버를 사용하기로 했다. 이 부분도 몇 차례 테스트를 통해 피그마 MCP 서버로부터 얻은 정보로 직접 대상 컴포넌트에 디자인을 적용하는 것보다 임시 컴포넌트를 만든 후 이를 기반으로 대상 컴포넌트의 디자인을 적용하는 편이 완성도가 높다는 인사이트를 얻었다. 최종적으로 프론트엔드 개발 작업은 다음과 같이 변경됐다.

2. Make prompt file
사람의 일을 AI가 수행할 수 있는 수준의 작업으로 분할했다. 이 작업들은 매번 동일한 프롬프트를 사용할 것이다. 우리는 코파일럿을 사용하고 있다. 코파일럿은 동일한 프롬프트를 템플릿화해서 재사용할 수 있는 기능을 제공한다. 자주 사용되는 프롬프트는 프로젝트 루트 .github/prompts
디렉토리에 *.prompt.md
파일로 생성한다.
.github
├── copilot-instructions.md
└── prompts
├── design.prompt.md
├── figma.prompt.md
├── frontend-impl.prompt.md
├── frontend-refactoring.prompt.md
└── frontend-test.prompt.md
...
작성된 프롬프트는 VSCode, 인텔리제이(intellij)에서 /
를 통해 명령어처럼 사용할 수 있다.

이렇게 각 작업 단위를 위해 작성된 프롬프트들은 개발자가 현재 자신이 수행할 작업을 위해 사용한다. 개발자는 자신의 작업을 프롬프트를 통해 AI에게 대리 수행시킨다. 이후 AI 작업 결과를 리뷰한다. AI 작업 결과가 만족스럽다면 다음 프롬프트를 수행한다. 결과에 문제가 있다면 일부 수정 후 다음 작업을 수행한다. 개발자는 프롬프트를 선택적으로 수행한다. 예를 들어, 굳이 리팩토링이 필요 없는 상태라면 실행하지 않는다.
3. Set parameter in prompt
prompt
파일은 자주 사용하는 프롬프트를 재사용하기 위해 만든 파일이다. 동일한 프롬프트라면 이를 여러 케이스에 유연하게 사용하기 어려울 수 있다. 함수처럼 파라미터라는 개념을 도입했다.
## 입력
- (Required) `USER_STORY`: 사용자 스토리
- `BUSINESS_RULE`: 구현에 필요한 비즈니스 규칙
...
## 주의사항
- `Required` 항목은 반드시 입력되어야 합니다. 입력되지 않은 경우, 에이전트는 작업을 수행할 수 없습니다. 프롬프트를 실행을 중단하고, 누락된 항목을 사용자에게 알립니다.
프롬프트에 함수처럼 파라미터를 설정한다. 필수 값은 항상 입력 받아야 하므로 없는 경우 프롬프트를 도중에 중단한다. 프롬프트를 실행할 때 USER_STORY
항목을 입력하지 않는 경우 다음과 같은 에러가 발생한다.

프롬프트를 실행할 떄 코파일럿 채팅에 다음과 같이 작성한다.
/frontend-test
USER_STORT="""
# Given
사용자가 TODO 애플리케이션에 접속했다.
# When
사용자가 화면을 본다.
# Then
다음과 같은 항목들이 있는 것을 볼 수 있다.
- TODO List 타이틀
- 입력 가능한 폼
- 입력 창
- `추가` 버튼
- 이전에 입력된 TODO 리스트
"""
4. Example prompt
위에서 사용한 프롬프트 내용을 살펴보자. 아래 프롬프트는 테스트 코드를 작성하기 위한 지시 내용이다. 다음과 같은 내용이 포함된다.
- AI 에이전트의 역할에 대한 설명
- 프롬프트를 실행하기 위해 필요한 입력
- 구체적인 지시와 지시를 수행하기 위해 필요한 컨텍스트
- 프롬프트를 실행할 때 주의사항
당신은 시니어 프론트엔드 엔지니어입니다. 프론트엔드 테스트 코드를 작성하는 데 도움을 줍니다.
## 입력
- (Required) `USER_STORY`: 사용자 스토리
## 지시
- 주어진 `USER_STORY`를 바탕으로, 프론트엔드 테스트 코드를 작성하는 데 도움을 줍니다.
- 테스트 코드만 작성하고, 실제 컴포넌트나 모듈의 구현 코드는 작성하지 않습니다. 단, 테스트 코드 작성에 필요한 실제 컴포넌트 혹은 모듈이 없는 경우, `./src` 디렉토리에 새로운 파일을 추가하되 구현은 하지 않습니다.
- 테스트 코드는 React Testing Library와 Jest를 사용하여 작성합니다.
- 테스트 커버리지는 최소 80% 이상이 되도록 합니다.
- 모든 테스트는 독립적이어야 하며, 다른 테스트에 의존해서는 안 됩니다.
- TDD 방식을 따르고, 구체적인 지침은 [이 내용](../../docs/tdd-guideline.md)을 따릅니다.
- 정상 케이스에 대한 테스트를 작성하고, 필요에 따라 예외·경계값 케이스에 대한 테스트를 작성합니다.
- describe 와 it 을 사용하여 테스트를 논리적으로 정리합니다.
- 테스트를 지나치게 세분화하거나 과도하게 많이 만들지 않습니다.
- 예: 일반적으로 발생하지 않는 예외 상황에 대한 고려
- 테스트 파일명은 `<ComponentName>.test.tsx` 또는 `<ModuleName>.test.ts`로 작성합니다.
## 주의사항
- `Required` 항목은 반드시 입력되어야 합니다. 입력되지 않은 경우, 에이전트는 작업을 수행할 수 없습니다. 프롬프트를 실행을 중단하고, 누락된 항목을 사용자에게 알립니다.
- `./tests` 디렉토리에 테스트 코드를 생성합니다.
- `./src` 디렉토리에 포함된 코드는 **절대** 수정하지 않습니다.
- 구현할 `USER_STORY`에 기재된 이상의 기능이나 디자인은 절대 구현하지 않습니다.
- 디자인, 스타일, 레이아웃, 접근성에 관한 테스트는 작성하지 않습니다.
CLOSING
바이브 코딩을 수행하다보면 채팅 세션의 컨텍스트가 더러워지면서 AI가 만들어내는 결과가 좋지 않을 때가 있다. 이런 경우 새로운 채팅을 열어 새로운 세션에서 작업을 수행하면 결과가 개선된다. 다만 코파일럿은 새로운 채팅 세션을 열면 기존 대화의 컨테스트(context)를 잃어버린다. 이런 경우 이전 작업과의 컨텍스트가 끊어지면서 엉뚱한 결과를 만들 때도 있다. 현재는 각 프롬프트 사이에 컨텍스트를 유지하기 위한 몇 가지 아이디어를 시도해보고 있다.
아직은 실제 개발 프로세스에 적용하지 않은 단계이므로 가시적인 결과를 얻진 못했다. 다음 주부터 실제 개발 프로세스에 적용해보면서 프롬프트 개선 등의 작업을 수행할 생각이다. 좋은 인사이트를 얻는다면 블로그에 정리할 예정이다.
댓글남기기