개발 블로그
아티클 5 분 소요

가드레일이 코드보다 먼저다 — 1인 운영의 메타 레이어

column automation 1인운영 llm-pipeline

결론부터

1인 운영의 자동화에서 결과의 품질을 결정하는 건 만든 코드가 아니라, 그 위에 깐 메타 레이어다. 디자인 토큰, 린트, QA 검증, 점수표, 비판 메모리 같은 것들. 코드는 다섯째 자리수, 메타 레이어는 첫째 자리수다.

회사 코드라면 동료의 PR 리뷰가 메타 레이어를 대신해 준다. 1인 운영에서는 그 자리가 비어 있고, 그 빈자리를 가드레일로 채우지 않으면 매일 다른 곳에서 망가진 결과물이 누적된다.

1인의 비대칭성

회사 코드와 1인 코드는 가드레일에 대한 요구가 다르다.

회사에선 평균적으로 두세 명이 같은 코드를 본다. PR 리뷰, 릴리즈 체크리스트, QA, 운영 모니터링이 직렬로 깔려 있어서 한 사람이 놓친 걸 다음 사람이 잡는다. 한 사람이 메타 레이어를 부실하게 깔아도, 시스템 전체로는 어느 정도 안전망이 있다.

1인 운영은 다르다. 매일 자동으로 굴러가는 파이프라인 — idea-cycles처럼 매일 새벽 5시에 한 편 만들어 푸시하거나, daily-feed처럼 하루 두 번 뉴스를 정리해 발행하거나 — 에서는 매번 사람이 결과를 본 뒤에 푸시하는 방식이 안 된다. 사람의 시간이 배율을 따라가지 못한다. 그러면 자동화가 만든 결과물을 사람 대신 검토할 누군가가 필요한데, 그 자리에 들어가는 게 메타 레이어다.

가드레일이 결과를 만든다 — 두 시리즈의 증거

idea-cycles의 마지막 회고에서 도달한 결론은 명확했다.

  • 토큰 룰(public/tokens.css + lint:design) — 매일 다른 LLM 출력 30+편을 한 사이트처럼 묶어준 단 하나의 가드레일.
  • Stage 5 QA(Playwright MCP) — 콘솔 에러·모바일 가로 스크롤·이벤트 리스너 누락 같은 "정적 분석으로 안 잡히는 위반"을 커밋 전에 끊어낸다.
  • Picker 5축 점수Stage 0 recent_critiques 메모리 — 무엇을 만들지가 어떻게 만들지보다 첫째 자리수다.

이 셋이 깔리기 전과 후의 결과물 품질 차이는 사이클 한 편 단위가 아니라 30편 누적 단위로 보면 명확했다. 한 편이 잘 나오는 건 운으로도 가능한데, 30편이 같은 톤으로 묶이고 모바일에서 다 동작하는 건 운으로 안 된다.

telegram-claude-bot 시리즈의 마지막 회고도 같은 모양이었다.

  • Dashboard를 더 일찍 — 디버깅 시간을 갈아 넣은 자리에 dashboard 한 번 들여다보는 걸로 끝나는 케이스가 대부분이었다.
  • MarkdownV2 escape를 처음부터 라이브러리로 — inline string replace로 시작했다가 잔버그를 다섯 번 패치한 뒤에야 모듈로 분리. 처음부터 분리했으면 한 번에 끝났다.
  • MCP 서버 spawn 시 env 명시 — 부모 환경의 일부만 상속하는 SDK 동작을 모르고 한참 헤맸다. entry에 env={...}를 명시했더라면 사라진 디버깅 시간.

세 항목 모두 메타 레이어를 너무 늦게 깔았다는 한 줄로 묶인다.

"Implementer를 먼저 잘 만들고 싶은 충동"이 두 프로젝트 모두에서 강했다. 한 편을 잘 만들고 싶은 마음. 하지만 매일 굴리는 파이프라인은 한 편의 품질이 아니라 N편의 누적 품질로 평가된다. 누적 품질을 결정하는 건 메타 레이어다.

메타 레이어를 먼저 깔아야 하는 이유

가드레일을 나중에 까는 건 가능하다. 다만 비용이 다르다.

가드레일이 처음부터 있으면, 그 위에서 만들어지는 모든 결과물이 룰을 따른다. 위반은 만들어지지 않는다. 가드레일이 나중에 추가되면, 이미 만들어진 결과물에 줄줄이 위반이 떠 있다 — 그걸 일일이 고치거나, 룰을 약화시키거나, 둘 중 하나를 골라야 한다. 둘 다 좋은 길이 아니다.

특히 LLM 파이프라인에서 그렇다. LLM은 룰을 우회하는 데 창의적이라, 길을 닫지 않으면 // eslint-disable 류의 우회를 만들어낸다. 우회 자체를 옵션에서 제거해야 한다. 그러려면 룰을 만들고 → 자동 검증을 붙여야 한다. 그것도 처음부터.

다른 이유 — 가드레일은 만든 사람의 의도를 미래의 자기에게 전달하는 매개체다. 디자인 토큰 파일은 "이 색상만 써라"고 매일 외치고, 린트는 그걸 자동으로 강제한다. 6개월 뒤에 같은 코드를 만지는 사람(=나 자신, 컨텍스트가 빠진)이 토큰 파일을 보면 "아, 이 팔레트만 쓰는 거구나"가 즉시 전달된다. 가드레일은 미래의 나에 대한 메모리이기도 하다.

어디부터 시작할까

새 자동화 프로젝트를 시작한다면 순서를 이렇게 잡겠다.

  1. 단일 진실원 정의 — 행동 규칙이 어디에 있는지 한 파일에 박는다. cycle-prompt.md처럼 자연어로 둬도 좋고, JSON schema로 둬도 좋다. "이 파일을 보면 동작이 보인다"가 되는 곳을 만든다.
  2. 가드레일 — 디자인 토큰 같은 룰 + 그 룰을 자동 검증하는 린트. 이 단계까지 깔리기 전엔 implementation을 만들지 않는다.
  3. 검증 단계 — 결과물이 정말 동작하는지 한 번 확인하는 단계. 정적 분석으론 안 잡히는 영역(브라우저에서 실제 띄워봐야 보이는 것들)을 잡는 칼.
  4. 선택 단계 — "무엇을 만들지" 결정하는 곳에 점수표·메모리·hard cap을 박는다. 이게 가장 중요하다.
  5. 그 다음에야 implementation.

이 순서가 거꾸로 가면 — implementation부터 시작하면 — 매일 다른 걸 만들고, 다른 걸 부순다. 가드레일이 깔리기 전의 결과물은 가드레일이 깔린 뒤에 줄줄이 위반으로 잡힐 운명이다.

회사 코드에서도 이 순서는 유효하지만, 가드레일이 부실해도 동료가 일부를 메워준다. 1인 운영에서는 그 메우는 자리가 비어 있다.

닫는 글

코드를 쓰기 전에 룰을 쓰자. 룰을 쓴 뒤에 그 룰을 자동으로 검증하는 린트를 쓰자. 린트를 쓴 뒤에 결과물을 검증하는 QA를 쓰자. 그 다음에 무엇을 만들지 고르는 곳에 점수표를 쓰자. 그 다음에야 implementation을 쓰자.

순서가 맞으면 1인 운영도 30편의 누적 품질에서 회사 코드와 비교 가능한 자리에 도달한다. 순서가 틀리면 한 편 한 편의 우연한 운에 의존한 결과물이 매일 쌓일 뿐이다.