채용 공고를 사이드 프로젝트로 바꾸는 파이프라인 만들기

경험을 토대로 AI를 활용하여 작성한 글 입니다.

이직을 준비하면서 사이드 프로젝트의 주제를 정하는 방식을 바꿨다. 만들고 싶은 걸 만드는 대신, 채용 공고의 필수/우대 조건에서 주제를 가져오기로 했다. "대용량 데이터 UI 구현 경험"이 우대사항에 있으면 그걸 주제로 잡는 식이다.

문제는 혼자서 기획, 디자인, 개발, 테스트를 매번 도는 게 쉽지 않다는 것이었다. 그래서 역할별로 서브에이전트를 만들고 단계별로 돌리기로 했다. planner, designer, qa, interviewer 네 개를 만들고 각각을 /sp-plan 같은 슬래시 커맨드로 실행하는 구조였다.

만들어놓고 실제로 돌려보니, 파이프라인이라고 부르기 민망한 곳이 여러 군데 있었다.

서브에이전트는 대화 맥락을 공유하지 않는다

가장 먼저 부딪힌 건 이거였다. planner가 기획한 내용을 designer가 알 방법이 없다. 서브에이전트는 각자 새 맥락에서 시작하기 때문에, 앞 단계에서 무슨 결정을 했는지 전달되지 않는다.

그래서 산출물을 파일로 강제했다.

docs/00-requirement.md   증명할 역량        (커맨드가 생성)
docs/01-prd.md           기획              planner
docs/02-design.md        화면 설계          designer
docs/03-qa-report.md     검증 결과          qa
docs/04-interview.md     면접 대비          interviewer

번호 순으로 쌓고, 각 단계는 앞 문서를 반드시 읽고 시작한다. 이 파일들이 유일한 인수인계 수단이라는 걸 각 에이전트 정의에 명시했다.

여기까지는 흔한 구조다. 진짜 문제는 그다음이었다.

문서는 이어지는데 의미가 안 이어졌다

돌려보고 나서 산출물을 읽어보니 이상했다. 공고에는 "대용량 데이터 Chart/UI 구현 경험"이라고 적혀 있고, PRD에는 "가상 스크롤을 적용한 목록 화면"이 있었다. 문서상으로는 연결돼 있다.

그런데 왜 그 회사가 그 문구를 적었는지가 어디에도 없었다.

회사가 "대용량 데이터 Chart/UI"를 우대사항에 적을 때 확인하려는 건 라이브러리 사용법이 아니다. 렌더링 병목의 원인을 계측으로 특정하고 근거 있게 제거할 수 있느냐다. 그 판단이 빠진 채로 "공고 문구 → 프로젝트 기능"으로 바로 점프하니, 결과물이 "기능 만들기"로 전락하고 있었다.

원인을 추적해보니 두 군데가 끊겨 있었다.

  • 공고를 입력받는 커맨드는 조건을 역량 카탈로그의 항목명에 매핑만 했다. 의도를 추론하는 단계가 아예 없었다
  • planner는 증명 기준 표와 핵심 기능 목록을 각각 따로 만들었다. 둘을 잇는 열이 없어서 "이 기능이 어느 역량을 증명하는가"가 문서 어디에도 남지 않았다

역량 추적표

다섯 개 열짜리 표 하나를 만들고, 이걸 파이프라인 전체의 축으로 삼았다.

공고 요구사항실제 확인하려는 역량프로젝트 기능검증할 내용측정 방법
대용량 데이터 Chart/UI렌더링 병목을 계측으로 특정하고 제거하는가10만 건 뉴스 시각화필터 지연, 힙 메모리, 리렌더 횟수Performance 패널, 최적화 전후 비교

핵심은 두 번째 열이다. 기술 이름이 아니라 판단 능력으로 쓴다. "React를 쓸 줄 아는가"는 도구 이름을 반복한 것이라 실패다. 이 열이 비면 나머지가 전부 의미를 잃는다.

표를 완성한 뒤에는 양방향 검사를 강제했다.

  • 모든 핵심 기능은 추적표의 최소 한 행에 대응해야 한다. 어느 행에도 안 걸리면 Out of Scope로 내린다
  • 모든 행은 최소 한 기능으로 구현되어야 한다. 기능이 없는 행은 증명할 수단이 없다는 뜻이다

첫 번째 규칙이 예상 밖으로 유용했다. 스코프가 새는 걸 막는 가장 강력한 장치가 됐다. "있으면 좋을 것 같은데" 하는 기능이 나올 때마다 "그럼 어느 행을 증명하냐"고 물으면 대부분 조용히 빠진다.

이렇게 하니 각 커맨드의 성격이 명확해졌다. 전부 같은 표를 소비하고 생산한다.

커맨드추적표와의 관계
/sp-new공고에서 의도를 추론해 표의 1·2열을 만든다
/sp-plan도메인을 정하고 3열(프로젝트 기능)을 채워 표를 완성한다
/sp-design표의 행에 대응하는 화면만 상세히 설계한다
/sp-build행 단위로 구현하고 측정한다
/sp-qa행 단위로 달성/미달을 판정한다
/sp-interview행마다 면접 질문을 만든다

표의 한 행이 곧 면접 답변 하나가 되는 구조다.

손으로 때우고 있던 것들

구조를 잡고 나서도 매번 수동으로 하는 일이 남아 있었다. 하나씩 없앴다.

커맨드 이름을 못 외운다

새 프로젝트를 시작하는 건 자주 있는 일이 아니다. 그러다 보니 매번 "뭐였지" 하면서 커맨드 목록을 뒤졌다.

단일 진입점 /sp 하나를 만들었다. 인자 없이 실행하면 현재 디렉터리의 docs/ 상태를 읽고 다음 단계를 판정한다.

📍 reactive-canvas-lab

  진행: 00 ✅  01 ✅  02 ⬜(선택)  구현 2/6행  03 ⬜  04 ⬜

  다음 단계: 추적표 #3 구현  →  /sp-build

프로젝트 밖에서 실행하면 전체 목록과 각각의 진행도를 보여준다. 인자로 공고 URL을 주면 새 프로젝트 생성으로 넘긴다. 외울 게 하나로 줄었다.

덤으로 알게 된 것도 있다. docs/를 못 찾았을 때 원래는 "/sp-new를 먼저 실행하세요"라고 안내했는데, 실제로는 프로젝트가 이미 있고 실행 위치만 틀린 경우가 대부분이었다. 커맨드는 어디서든 인식되지만 문서 경로는 현재 디렉터리 기준이라 그렇다. 이제는 ~/projects/*/docs/를 먼저 뒤져보고 cd를 안내한다.

제약 조건을 손으로 채우고 있었다

공고를 입력하면 요구사항 문서가 만들어지는데, 기간·투입 시간 같은 제약 조건은 주석으로 비워두고 "알아서 채우세요"로 끝냈다. 그래서 매번 에디터를 열어 손으로 채웠다.

이게 왜 문제인지는 다음 단계에서 드러났다. 기간과 투입 시간은 planner가 스코프를 자르는 유일한 근거다. 비어 있으면 PRD가 과대 산출되고 결국 다시 써야 한다.

주석으로 남기는 대신 물어보게 바꿨다. 선택지를 총 시간으로 환산해서 보여주는 게 핵심이다. "2주 × 15h"보다 "총 30시간 — 기능 2~3개가 한계"가 훨씬 현실감이 있다. 답을 받으면 추적표 행 수가 그 시간에 현실적인지도 바로 판단해서 경고를 남긴다.

문서는 다 만들어졌는데 package.json이 없었다

이게 제일 어이없는 발견이었다. 설계까지 끝내고 나면 docs/ 아래 문서 세 개가 쌓이는데, 정작 프로젝트가 없다. 빈 디렉터리에 마크다운만 있는 상태로 방치된다.

파이프라인을 다시 훑어보니 원인이 명확했다.

  • 프로젝트 생성 커맨드에는 "스캐폴딩은 하지 않는다"고 적어뒀고
  • planner의 도구 목록은 Read, Write, Glob, Grep, WebSearch, WebFetch
  • designer는 Read, Write, Glob, Grep

설치를 실행할 수 있는 주체가 파이프라인에 아예 없었다. 각자의 역할을 좁게 정의하다 보니 아무도 담당하지 않는 구간이 생긴 것이다.

/sp-build를 새로 만들었다. 순서를 이렇게 잡았다.

스캐폴딩 → 계측 하네스 → baseline 구현 → 측정 → 추적표 행 단위 루프

계측 하네스를 기능보다 먼저 만드는 게 중요하다. 나중에 붙이면 이미 늦고, 측정할 수 없으면 이 프로젝트는 아무것도 증명하지 못한다. baseline(최적화 전 순진한 구현)도 먼저 만들어 먼저 재둔다. 나중에는 재현할 수 없기 때문이다. 비교값 없는 최적화는 "그래서 얼마나 빨라졌나요"에 답할 수 없다.

한 가지 더. 이 커맨드는 서브에이전트로 만들지 않았다. 구현은 사용자와의 왕복이 필요한데 서브에이전트는 사용자에게 질문할 수 없다. 메인 세션에서 직접 수행하도록 했다.

측정이 파이프라인 끝에서 증발하고 있었다

추적표의 측정 방법 열을 보니 전부 이런 식이었다.

Performance 패널 녹화, Memory 스냅샷, Elements 노드 카운트

전부 DevTools 수동 조작이다. 이대로 두면 어떻게 되는지 따라가 봤다.

qa → "직접 재세요" → 측정값 빈칸 → 전 행 '미달' 판정
   → interviewer가 수치 없이 진행 → 이력서 문장에 숫자가 없음

파이프라인 최종 산출물이 목적을 달성하지 못하는 경로였다. 애초에 이 프로젝트를 하는 이유가 "빨라졌습니다"가 아니라 측정값을 들고 설명하기 위해서인데.

planner가 측정 방법을 정할 때 자동 측정 가능한 형태를 1순위로 쓰도록 강제했다. React Profiler의 onRender 콜백으로 렌더 횟수를 세거나, PerformanceObserver로 long task를 수집하거나, performance.measure로 구간을 재거나, Playwright + CDP로 트레이싱하는 식이다. DevTools 수동 조작은 보조 근거로만 남긴다. qa도 자동 측정을 먼저 시도하고, 수동으로 넘길 때는 왜 자동화가 불가능한지 이유를 함께 적도록 했다.

디자인이 구현을 잡아먹지 않게

designer는 화면마다 상태 5종, 반응형 3종, 라이트/다크 토큰을 균등하게 요구하고 있었다. 그런데 만들려는 게 캔버스 에디터라면 모바일 대응과 다크 모드는 추적표 어느 행에도 기여하지 않으면서 시간만 먹는다.

디자인을 아예 선택 단계로 내렸다. 없어도 구현은 진행된다. 그리고 방어 장치를 넣었다.

  • 총 예산의 30% 상한 — 넘으면 설계를 줄이고 다시 계산한다
  • 반응형·다크 모드는 선택 역량일 때만 명세. 아니면 데스크톱 고정 한 줄로 끝
  • 상태 5종은 추적표 대응 화면에만. 나머지는 로딩·에러 둘만
  • 문서 맨 위에 시간 부족 시 버리는 순서 섹션 — 구현자가 가장 먼저 읽는 자리에 둔다

마지막 항목이 마음에 든다. 설계 문서가 스스로 "나는 여기까지 버려도 된다"고 선언하게 만드는 셈이다.

구현은 누가 하는가

처음엔 "핵심 역량 구현부는 사용자가 직접 작성한다"는 규칙을 넣어뒀다. AI가 대신 짜면 면접 꼬리 질문에서 무너진다고 생각해서였다.

돌아보면 이 규칙은 문제를 잘못 짚고 있었다. 실무는 이미 구현을 상당 부분 도구에 맡기고 개발자가 구조 결정과 리뷰를 맡는 쪽으로 옮겨갔고, 제한된 시간에 손으로 짜면 추적표를 절반도 못 채운다.

진짜 문제는 "AI가 짰다"가 아니라 감독했다는 증거가 없다는 것이었다. 실무의 감독에는 PR 리뷰 코멘트나 설계 문서 같은 이력이 남지만, 사이드 프로젝트에는 그게 없다.

그래서 감독이 산출물을 남기도록 바꿨다.

  1. 추적표 행마다 구현 전에 선택지를 두 개 이상 제시하고 결정을 받는다. 코드부터 쓰지 않는다
  2. 무엇을 골랐는지가 아니라 무엇을 버렸고 왜 버렸는지docs/decisions.md에 남긴다
  3. 구현 즉시 측정하고, 목표에 못 미치면 원인 가설을 세우고 검증하는 왕복을 반복한다

3번이 실질적인 장치다. 수치가 안 나오면 왜 안 나오는지 파고들 수밖에 없고, 그 과정에서 코드를 실제로 이해하게 된다.

최종 방어선도 바꿨다. "직접 짠다"에서 **"설명할 수 없는 코드는 프로젝트에 남기지 않는다"**로. 설명이 안 되는 부분은 지우거나, 이해될 때까지 파고들거나, 더 단순한 방식으로 바꾼다.

커맨드는 고쳐가며 쓰는 것

이번에 고친 것들을 workflow-log.md에 남기기 시작했다. 무엇이 막혔고 어떻게 고쳤는지를 한 줄씩 쌓는다.

처음엔 단순히 기억용이었는데, 쓰다 보니 이게 그 자체로 산출물이라는 걸 알게 됐다. 실제로 요즘 공고에는 "agentic AI 도구를 개인 활용을 넘어 팀의 개발 워크플로우로 정착시킨 경험" 같은 우대사항이 붙는다. 그런 경험은 이런 기록이 있어야 증명된다. 도구를 썼다는 말은 누구나 할 수 있지만, 무엇이 막혀서 어떻게 고쳤는지는 실제로 해본 사람만 쓸 수 있다.

그래서 /sp 안내문에 아예 규칙으로 넣었다. 파이프라인을 돌리다 막히면 그 자리에서 커맨드를 고치고 로그에 남긴다. 커맨드는 마크다운 파일이라 고치면 다음 실행부터 반영된다. 미루면 같은 문제를 계속 손으로 때우게 된다.

남은 이야기

정리하고 보니 이번 작업의 본질은 자동화가 아니었다. 없앤 수동 작업 네 개는 전부 **"누구도 담당하지 않는 구간"**이었다. 커맨드 이름 기억하기, 제약 조건 채우기, 프로젝트 설치하기, 성능 재기 — 각 에이전트의 역할을 깔끔하게 나누다 보니 그 사이에 아무도 안 맡은 틈이 생겼고, 그 틈을 매번 사람이 메우고 있었다.

역할을 나눌 때는 경계면을 같이 설계해야 한다는 걸 배웠다. 그리고 그 경계면이 잘 이어졌는지는 문서가 순서대로 쌓였는지로는 알 수 없다. 판단의 근거가 이어졌는지를 봐야 한다. 역량 추적표를 만들기 전까지는 문서가 다섯 개 다 있어도 "이 기능이 왜 여기 있는가"에 아무도 답할 수 없었다.

아직 이 파이프라인으로 프로젝트를 끝까지 돌려보진 않았다. 다음 글은 실제로 돌려보고 나서 어디가 또 끊겼는지 쓰게 될 것 같다.