
프론트엔드 개발을 혼자서 해낼 수 있었던 이야기 - IBM Bob과 MCP로 실현하는 초고속 개발 워크플로우【제1회】
요약
IBM Bob과 MCP를 활용하여 AI가 스스로 코드를 작성할 수 있는 최적의 환경(Harness)을 구축하고, 프론트엔드 개발 워크플로우를 혁신한 사례를 다룹니다. 단순한 프롬프트 작성을 넘어 AI가 판단할 필요가 없도록 규칙과 토대를 설계하는 'Harness Engineering'의 중요성을 강조합니다.
핵심 포인트
- AI에게 코드를 맡기기 전, AI가 헤매지 않을 토대(Harness)를 설계하는 것이 핵심
- IBM Bob과 MCP를 활용한 시스템화된 개발 워크플로우 구축
- 프롬프트 의존도를 낮추기 위해 규칙, 모드, 외부 도구 연동을 통한 레일 설치
- Next.js 15, TypeScript 기반의 현대적 프론트엔드 개발 환경 적용
「프론트엔드, 혼자서 할 수 있겠어?」
프로젝트를 시작할 때 그런 질문을 받았을 때, 솔직히 불안함이 더 컸다. 기술 선정도, 환경 구축도, 규약 만들기도, 화면 구현도, 전부 스스로 챙겨야 한다.
그로부터 4주. 정신을 차려보니 테스트와 접근성 (Accessibility)을 보장하면서 하루에 1페이지 페이스로 화면을 만들 수 있게 되어 있었다.
무엇이 효과적이었나. 한 마디로 말하자면, 「AI에게 코드를 쓰게 하는 것」이 아니라, 「AI가 헤매지 않을 토대를 먼저 만드는 것」에 시간을 썼기 때문이라고 생각한다.
이 기사는 그 토대 구축에 관한 이야기다. 사용한 것은 IBM Bob과 MCP (Model Context Protocol)이지만, 도구 그 자체보다 「어떻게 시스템화했는가」에 무게를 두고 작성한다. 좋았던 점뿐만 아니라, 막혔던 부분도 솔직하게 적을 예정이다.
이 기사는 시리즈의 제1회입니다. 제2회에서는 여기서 만든 토대 (.bob 설정)를 그대로 Claude Code로 가져갔을 때 어떤 일이 일어났는지에 대한 이행 편을 예정하고 있습니다.
- 소수 인원, 혹은 혼자서 프론트엔드를 맡고 있는 사람
- AI 코딩을 「보완」에서 한 단계 더 나아가 개발 워크플로우 그 자체에 통합하고 싶은 사람
- Next.js / React / TypeScript 등으로 개발하고 있는 사람
IBM Bob의 자세한 사용법 자체는 다른 기사에 맡기겠다. 여기서는 「생각하는 방식」과 「실제로 했던 일」을 중심으로 한다.
먼저 전제를 솔직하게 적어둔다.
팀은 2명이었다. 다만, 다른 한 명은 프론트엔드 경험이 적은 멤버였고, 담당한 것은 헤더 주변의 일부였다. 환경 구축, 기술 선정, 코딩 규약, AI 워크플로우 설계, 그리고 대부분의 화면 구현은 내가 담당했다. 「헤더 이외에는 거의 혼자」라는 것이 실태에 가깝다.
이를 뒤집어 말하면, 나의 역할은 도중에 「코드를 쓰는 사람」이 아니게 되었다. AI가 올바르게 작동하기 위한 발판 (Harness)을 설계하는 사람으로 바뀌어 있었다. 규칙, 모드, 워크플로우, 외부 도구 연동. 이것들을 정비하면 구현 자체는 AI에게 맡길 수 있는 시간이 단번에 늘어난다. 최근 자주 들리는 「Harness Engineering」이라는 단어가 나의 체감과 가장 가깝다.
개발은 애자일 (Agile) 방식으로, 1 스프린트(Sprint)에 4주간 진행되었다. 6월부터 개발 페이즈가 시작되었다. 다만, 백엔드 API가 아직 갖춰지지 않았기 때문에, 첫 스프린트에서 할 일은 「API 연동」과 「CI/CD 구축」을 제외하면 실질적으로 「화면 선행 구현」이었다.
결과적으로 그 화면 주변은 1주일 정도 만에 형태를 갖추었다. Figma에서 화면 정보를 가져와 사양서로 옮기고, 임시 디자인 토큰 (Design Token)을 준비하여 그대로 구현에 들어간다. 이 흐름을 탈 수 있었던 것이 컸다.
토대 이야기에 들어가기 전에, 무엇 위에서 돌아가고 있는지만 공유해 두겠다.
| 영역 | 채택한 것 |
|---|---|
| 프레임워크 | Next.js 15 (App Router) |
| ... |
비교적 최신 구성이지만, 후술할 ADR에서 선정 이유를 남겨두었다.
AI 코딩이라고 하면, 무심코 「똑똑한 지시를 내려서 좋은 코드를 얻어낸다」는 발상이 되기 쉽다. 처음에는 나도 그랬다.
하지만 매번 훌륭한 프롬프트 (Prompt)를 쓰는 것은 지속 가능하지 않다. 지시의 질에 결과물이 좌우되고, 사람이 바뀌면 결과도 바뀐다. 팀에 전개할 수 없다.
생각을 바꿨다. AI가 매번 좋은 판단을 하게 만드는 것이 아니라, 판단하지 않아도 될 부분까지 전제를 굳히는 것. 즉, 레일을 깔아두는 것이다.
레일에 해당하는 것이 IBM Bob에서 말하는 다음 4가지다.
기술 선정은 나의 지견과 다른 프로젝트의 상황을 베이스로 하면서, AI를 대화 상대 (Wall-hitting partner)로 사용했다.
예를 들어 「Next.js 15의 App Router와 Remix를 이번 요구사항에 맞춰 비교해서 ADR 초안을 작성해줘」라고 던진다. 그러면 비교 관점과 초안이 돌아온다. 그것을 스스로 취사선택하여 최종적으로 ADR (Architecture Decision Record)로 남긴다.
ADR로 남기는 것이 은근히 효과적이었다. 나중에 「왜 이것을 선택했는가」라는 질문을 받아도 문서를 보여주면 끝난다. AI에게도 이 문서 자체가 판단 재료가 된다.
# ADR-001: Next.js 15 App Router 채택
## 상황
프론트엔드 프레임워크의 선정이 필요함.
...
선정하기 전에 PoC(Proof of Concept)도 직접 진행했다. React Aria Components로 접근성(Accessibility) 대응이 얼마나 현실적인지, Biome에 맞춰 운영할 수 있는지, Vitest와 Storybook의 조합은 어떤지. 이 단계는 "AI에게 맡기기"보다는 "직접 만져보며 확인하기" 단계였다. 토대를 만드는 사람이 확신을 갖지 못하면 레일을 깔 수 없다.
코딩 규약(Coding Convention)을 만드는 것은 새로운 규칙을 발명하는 작업이 아니었다. 머릿속에 있는 "대충 이렇게 하고 있다"를 전부 언어로 만드는 작업이었다.
사람 상대라면 "분위기를 파악해서"로 통할 일도 AI에게는 통하지 않는다. 반대로 말하면, 명문화만 되어 있다면 AI는 놀라울 정도로 충실하게 지켜준다.
우선순위도 명확히 했다.
- 프레임워크 공식 가이드라인
- React / TypeScript / WCAG 2.1 AA
- 프로젝트 고유 규약
- 팀 내 관습
그 위에 핵심 원칙은 욕심내지 않고 몇 가지로 압축했다(이 "압축한" 이유는 후반부 실패담에서 쓰겠다).
그중에서도 가장 효과가 컸던 것이 기능(Feature) 간의 직접 의존을 금지하는 규칙이다. 이는 구두로 말해도 지켜지지 않기 때문에, Biome 규칙을 통해 기계적으로 에러가 나도록 설정했다.
- // 금지: 다른 기능의 내부를 직접 import하는 것
- import { SomeType } from '@feature-b/types' // @feature-a 내부에서
+ // OK: 공통화된 것을 사용
...
{
"linter": {
"rules": {
...
"규약은 AI가 아니라, 먼저 Linter가 지키게 한다". 이것이 은근히 효과적이다. AI도 사람도 결국 CI(Continuous Integration)에서 막히기 때문에 도망갈 수 없다.
처음에는 "무엇이든 할 수 있는 개발 모드"를 하나 만들었다. 이것은 실패였다. 무엇이든 할 수 있으면 오히려 동작을 예측할 수 없다. 리뷰를 부탁했는데 코드를 마음대로 고쳐버리는 식의 일이 발생한다.
그래서 역할을 하나로 좁힌 모드로 나누었다.
- 컴포넌트 개발 담당: TypeScript 파일만 편집할 수 있음
- 리뷰 담당: 읽기 전용. 편집 권한을 주지 않음
- 공통화 어드바이저: "이것을 공통화해야 하는가"만을 판단함
포인트는 권한 자체를 제한하는 것이다. 리뷰 담당에게 편집 권한을 주지 않으면, 리뷰 중에 멋대로 코드가 바뀌는 사고는 일어나지 않는다. 역할을 말로 부탁하는 것이 아니라, 할 수 있는 일을 구조로 묶는 것이다.
slug: code-review
name: Code Review
roleDefinition: |
...
잘 작동하는 작업 절차는 Skill로 고정했다. 매번 같은 흐름으로 움직이게 된다.
컴포넌트 개발에서는 Storybook을 기점으로 한 TDD(Test-Driven Development) 절차를 Skill로 만들었다. 흐름은 다음과 같다.
사람이 절차서를 보며 수행하던 것을 그대로 AI의 절차서로 만든 이미지다. 새로운 컴포넌트를 요청하면 이 흐름을 매번 따른다. 그래서 결과물의 입도가 일정하다. 명명 규칙(Naming)도 테스트 관점도 사람에 따라 흔들리지 않는다.
실제로 "Button 컴포넌트를 만들어줘"라고 요청하면 다음과 같이 진행된다.
실제 실행 로그(클릭하여 전개)
Bob: React Aria MCP: 연결 성공
Bob: Storybook MCP: 연결 성공
Bob: 사양서를 확인합니다
...
체감상으로는 컴포넌트 하나를 수작업으로 할 때 30분 정도 걸리던 것이, 확인 과정을 포함해도 몇 분 만에 형태를 갖추게 되었다. 테스트와 Storybook이 반드시 따라오기 때문에 후속 공정의 리뷰도 상당히 가벼워진다.
AI는 똑똑하지만, 지식은 학습 시점에 멈춰 있다. 라이브러리의 API는 변한다. 그 간극을 메우는 것이 MCP였다.
이번에 연결한 것은 주로 4가지다.
| MCP | 가져오는 정보 |
|---|---|
| React Aria MCP | 컴포넌트의 API와 접근성 요구사항. onPress인지 onClick인지, 사용할 수 있는 상태 변형(Variant)은 무엇인지 |
| ... |
특히 Figma MCP는 화면의 선행 구현에서 효과적이었다. 디자인에서 레이아웃과 값을 가져와 사양서에 반영하고, (아직 정식 디자인 토큰이 없었기에) 임시 토큰을 준비하여 구현에 들어간다. 이 일련의 과정을 매일 1페이지 분량씩 돌렸다.
여기까지 토대가 구축되면 하루의 흐름은 대략 다음과 같다.
화려한 것은 없다. 다만 매번 같은 레일 위를 달리고 있기 때문에 고민하는 시간이 거의 없다. "다음에 무엇을 해야 하더라"가 사라지면 개발이 이렇게 빨라질 수 있는가, 하는 것이 솔직한 감상이었다.
여기까지 읽으면 만능처럼 보일 수도 있지만, 그렇지는 않다. 오히려 처음에는 시행착오가 더 많았다. 숨기지 않고 적겠다.
잔량(Budget)이 금방 줄어든다.
Bob에는 이용 한도가 있어, 무거운 처리를 돌리면 잔량이 눈에 띄게 줄어든다. "일단 전부 다 해줘"와 같은 큰 요청을 던지면 순식간에 한도를 잡아먹는다. 결국 태스크를 작게 나누어 필요한 부분만 맡기는 것이 비용 측면에서도 정답이었다.
무거운 요청은 로딩이 끝나지 않을 때가 있다. 대량의 파일을 가로지르는 무거운 프롬프트(Prompt)라면, 응답이 돌아오지 않고 로딩이 계속되는 상황이 몇 번 있었다. 대책은 마찬가지로, 컨텍스트(Context)를 좁혀서 작게 부탁하는 것이다. 한 번에 전부 다 시키려 하지 말 것.
베이스 모델(Base Model)의 한계에 부딪힌다. 이용 중인 모델의 특성상, 모호한 지시나 어려운 설계 판단에서는 상상했던 결과물이 나오지 않을 때가 있었다. 여기서 효과를 본 것이 사양서(Specification)다. 전제 조건을 문서로 미리 전달해 두면 출력의 정밀도가 확실히 올라간다. "좋은 지시를 쓰는 것"보다 "전제를 읽히는 것"이 더 안정적이다.
MCP가 다운되면 작업이 멈춘다. 외부 연동에 너무 의존하면, 연결되지 않는 날에는 작업 전체가 멈춘다. 그래서 사양서를 사전에 준비하고, MCP는 어디까지나 보조라는 위치로 설정했다.
규칙은 너무 과하게 만들면 역효과를 낸다. 처음에는 규칙을 너무 세세하게 작성해서 AI가 오히려 갈팡질팡하기 시작했다. 핵심 원칙을 몇 개로 압축하고, 세부 사항은 각 모드(Mode) 측에 맡기니 안정되었다. "전부 쓰는 것"보다 "효과적인 것만 쓰는 것".
모두 돌이켜보면 "한 번에 욕심내지 않는다"라는 한 점으로 수렴한다. 토대 구축도, 운용도.
이러한 진행 방식은 자신의 머릿속에만 있어서는 의미가 없다. 경험이 적은 멤버와 둘이서 모브 프로그래밍(Mob Programming)을 하며 실제로 헤더를 함께 만들었다.
흥미로웠던 점은, 레일이 깔려 있으면 경험이 적어도 "그럴싸한 결과물을 만들어낼 수 있다"는 것이었다. 모드를 전환하며 절차에 따라 요청하면, 명명(Naming)도 테스트도 규칙에 맞는 결과물이 나온다. 리뷰에서의 지적도 자연스럽게 줄어든다.
"베테랑의 암묵지(Tacit Knowledge)를 시스템으로 변환하여 팀에 배포한다". AI 활용의 가장 큰 묘미는 의외로 여기에 있을지도 모른다.
정량적으로 "몇 % 절감"이라고 당당하게 말할 수 있을 만큼 정밀하게 측정하지는 않았다. 다만 체감상으로는,
- 컴포넌트 1개가 수작업으로 30분 걸리던 것이 몇 분 만에 형태를 갖춤
- 테스트와 Storybook이 반드시 따라오기 때문에 리뷰가 눈에 띄게 가벼워짐
- 화면 1페이지가 이전 감각으로는 2일 치 작업이었던 것이 하루 만에 돌아감
정도의 변화는 있었다.
그리고 무엇보다, "혼자서 괜찮을까"라는 초기의 불안이 4주 만에 거의 사라졌다. 정확히는 2인 팀이지만, 토대 설계와 대부분의 구현을 혼자 담당해도 파탄 나지 않았다. 이는 내가 손을 빠르게 움직이게 되었기 때문이 아니다. AI가 헤매지 않을 레일을 까는 데 시간을 썼기 때문이라고 생각한다.
- AI에게 "좋은 코드를 쓰게 하는 것"보다, "헤매지 않을 토대(규칙·모드·Skills·MCP)를 구축하는 것"에 투자하면 개발은 안정적이고 빨라진다
- 규칙은 명문화하고, 가능하다면 Linter가 지키게 한다. 역할은 권한별 구조로 제한한다
- 성공한 절차는 Skill로 고정하여 일회성으로 끝나지 않게 한다
- MCP로 "최신의 정답"을 끌어오되, 너무 의존하지 않도록 보험(사양서)도 갖춘다
- 만능은 아니다. 잔량·무거운 처리·모델의 한계에 부딪힌다. 작게 나누는 것이 결국 가장 빠르다
역할이 "코드를 쓰는 사람"에서 "AI가 일할 수 있는 환경을 만드는 사람"으로 변해가는 감각은, 앞으로의 프론트엔드 개발에서 점점 더 당연한 일이 될 것이라 느낀다.
제2회는 여기서 만든 .bob 설정을 그대로 Claude Code의 .claude로 가져갔을 때 어떻게 되었는지, 그 이행 편을 쓸 예정이다.
결론부터 말하자면, 설정이 거의 그대로 작동했다. 이는 "워크플로우 설계가 특정 도구에 종속되지 않았다"는 것의 반증이기도 하다. 그 부분을 다음 회차에서 자세히 다루겠다.
여기까지 읽어주셔서 감사합니다. 마찬가지로 소수 인원으로 프론트엔드를 운영하시는 분들께 참고가 된다면 기쁘겠습니다. 질문이나 "우리는 이렇게 하고 있다"라는 이야기가 있다면 꼭 댓글로 알려주세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기