
Claude Code의 /loop로 '공부 자료가 자동으로 늘어나는 리포지토리'를 만들었더니 1주일 만에 셰이더 89개가 생겨난 이야기
요약
Claude Code의 /loop 기능을 활용하여 1주일 만에 89개의 GLSL 셰이더 컴포넌트를 자동으로 생성한 사례를 소개합니다. 반복 실행 가능한 독립적 태스크를 설정하여 학습용 코드 리포지토리를 구축하는 방법과 최적의 루프 태스크 조건을 제안합니다.
핵심 포인트
- Claude Code의 /loop 기능은 지정된 명령을 일정 간격으로 반복 실행함
- 성공적인 루프를 위해 작업의 독립성, 누적 가치, 기계적 판정 가능성이 중요함
- 셰이더 생성, 구현, 커밋까지의 전 과정을 자동화하여 학습 자료를 확보함
- 세션 유지 동안만 작동하며 7일 후 자동 만료되는 특성이 있음
여러분은 Claude Code의 /loop를 이미 사용해 보셨나요?
/loop는 "지정한 프롬프트나 슬래시 명령(Slash Command)을 일정 간격으로 반복 실행해 주는" 기능입니다. 배포 완료 모니터링이나 PR 상태 체크와 같은 반복 작업을 Claude에게 맡길 수 있는 기능으로, Claude Code v2.1.72 이후부터 이용할 수 있습니다. 자세한 사양은 공식 문서에 정리되어 있습니다.
참고로, cron처럼 백그라운드에서 상주하는 방식이 아니라, Claude Code 세션을 열어두고 있는 동안에만 작동한다는 점에 주의하세요 (정기 태스크는 생성 후 7일이 지나면 자동으로 만료됩니다).
편리할 것 같다는 건 알겠습니다. 하지만 막상 사용하려고 하면 이렇게 되지 않나요?
"그래서, 무엇을 루프(Loop)시켜야 하지……?"
저도 처음에는 그랬습니다. 이 기사에서는 제가 실제로 돌려보며 "이것이야말로 /loop의 정답 패턴 중 하나다"라고 느낀 사용법 —— 공부용 샘플 코드를 자동으로 계속 늘려가는 방식 —— 을 실제 리포지토리와 설정 파일을 모두 보여드리며 소개하겠습니다.
이런 분들을 위해 작성했습니다.
- Claude Code로 loop 작업을 해보고 싶지만, 무엇을 시켜야 할지 모르겠는 사람
- 공부할 때 참고가 될 만한 코드(필사·독해 소재)를 늘리고 싶은 사람
Nuxt 4 + Three.js로 만든 GLSL 셰이더 갤러리 사이트에 /loop를 심었습니다.
/loop 20m /add-shader
단지 이것뿐입니다. "20분마다 /add-shader라는 커스텀 슬래시 명령을 실행한다"는 의미입니다.
결과는 다음과 같습니다.
- 1주일 만에 89개의 셰이더 컴포넌트가 자동으로 추가됨 (갤러리 전체로는 200개 초과)
- 1 커밋 = 1 셰이더로, 구현 → 갤러리 등록 → Storybook 스토리 생성 → lint/포맷팅 → 동작 확인 → commit까지 전 과정 자동화
- git log가 그대로 "GLSL 표현 사례집의 목차"가 됨
$ git log --oneline | head
12c5f7c feat: Geyser(간헐천) 셰이더 컴포넌트 추가
be4b59f feat: Halo(헤일로) 셰이더 컴포넌트 추가
...
간헐천, 헤일로(Halo), 단풍, 말미잘, 눈 결정……. 테마 선정도 Claude에게 맡겼지만, "기존 것과 겹치지 않는 테마를 골라라"라는 지시만으로 자연 현상, 광물, 생물, 우주 등 다채롭게 늘어납니다. 솔직히 아침에 일어나 커밋 로그를 살펴보는 것이 조금 즐거워질 정도입니다.
/loop에 적합한 태스크의 조건을 직접 돌려보며 느낀 순서대로 나열하겠습니다.
1. 1회분의 작업이 독립적으로 완결될 것
"셰이더를 1개 추가한다"는 이전 결과에 의존하지 않습니다. 한 번 실패해도 다음 루프에 영향을 주지 않습니다. 이것이 연쇄되는 태스크(리팩터링의 연속 등)라면, 한 번의 실패가 눈덩이처럼 불어나 전체를 망가뜨리게 됩니다.
2. 몇 번을 반복해도 가치가 쌓일 것
샘플 코드는 많으면 많을수록 공부 소재로서 가치가 올라갑니다. "같은 패턴으로 작성된 GLSL 구현이 89개 있다"는 것은, 완벽한 튜토리얼 1개와는 또 다른 종류의 가치가 있습니다. fbm 노이즈 사용법만 하더라도 불, 구름, 바위, 수면 등 여러 가지 "사용 방식"을 비교하며 읽을 수 있기 때문입니다.
3. 성공/실패를 기계적으로 판정할 수 있을 것
lint를 통과하는지, 페이지가 200 응답을 반환하는지, 셰이더 컴파일 에러가 발생하지 않는지. 인간의 주관적인 리뷰 없이도 "망가지지 않았음"을 보장할 수 있습니다.
역으로 말하면, 이 3가지 조건을 만족하는 태스크를 찾아낼 수 있다면 셰이더에 국한되지 않고 무엇이든 /loop의 소재가 됩니다 (기사 마지막에 아이디어 모음을 실었습니다).
/loop 20m /add-shader 한 줄을 지탱하고 있는 것은 다음 두 파일입니다.
three-nuxt/
├── CLAUDE.md # 리포지토리 규약 (매번 읽힌다는 전제의 지식)
└── .claude/
...
CLAUDE.md에는 모든 컴포넌트 공통의 구현 패턴을 적어두었습니다. 발췌하면 다음과 같습니다.
Gallery 컴포넌트 규약
app/components/Gallery/{Name}/index.vue 형식으로 배치한다.
각 컴포넌트의 구현 패턴 (모든 컴포넌트 공통):
...
여기가 공부 소재화의 핵심입니다. 타입을 고정해 둔 덕분에, 89개의 컴포넌트는 "차이점이 프래그먼트 셰이더 (Fragment Shader)뿐"이 됩니다. 즉, 읽을 때는 GLSL 부분에만 집중하면 됩니다. 필사(写経)할 때도 보일러플레이트 (Boilerplate)는 한 번만 익혀두면 전부 통용됩니다.
.claude/commands/add-shader.md
가 루프 1회당 수행할 작업의 전체 정의입니다. 구성은 다음과 같습니다.
# 새로운 GLSL 셰이더 컴포넌트를 1개 추가한다
## 1. 테마 선정
- 기존 엔트리를 확인하고, **아직 다뤄지지 않은 테마**를 1개 선택한다
...
포인트는 **"commit까지가 한 세트"**라고 명시한 점입니다. 이것이 없으면 루프가 돌 때마다 커밋되지 않은 변경 사항이 쌓여서, 어느 회차에서 충돌이 발생하며 붕괴합니다. 1회 = 1커밋으로 완결시키면, 각 회차가 독립되어 실패한 회차만 버릴 수 있게 됩니다.
이 부분이 가장 전달하고 싶은 내용입니다. /loop는 "돌리기 시작한 후에 지시문을 키워나가는" 것이었습니다.
이 리포지토리에는 "컴포넌트 이름에 대문자가 2곳 있으면 상세 페이지가 404가 된다"라는 기지의 버그가 있었습니다. 루프 도중에 수정할 시간은 없으므로, 우선 add-shader.md에 이렇게 적었습니다.
컴포넌트 이름은
대문자를 1곳만 포함하는 1단어로 한다 (예: Icefloe ○ / IceFloe ×)
버그 수정보다 먼저 "지뢰의 위치를 알려준다". 자동화에서는 이 순서가 더 즉효성이 있습니다.
도중에 상세 페이지에 lil-gui의 파라미터 조정 패널(속도·일시정지·색상 조정)을 추가했는데, 이는 "모든 컴포넌트가 THREE.Clock으로 시간을 관리하고 있다"는 것을 전제로 한 범용 설계였습니다.
그러자 예상대로, 어떤 회차에서 performance.now()를 사용한 독자적인 시간 관리 셰이더가 만들어질 뻔했습니다. 인간의 팀 개발과 마찬가지로, 적혀 있지 않은 규약은 존재하지 않는 규약입니다. 다음 내용을 지시문에 추가하여 해결했습니다.
시간 관리는 THREE.Clock을 사용한다. getElapsedTime()만 사용한다. performance.now()나 uTime += 0.01 등의 독자적인 시간 관리를 사용하면 속도 조정이 작동하지 않는다.
89번이나 돌리면 가만히 두었을 때 "파도"나 "오로라"만 생기게 됩니다. "기존 엔트리를 확인한 후 테마를 선택한다", "시각적으로 너무 유사한 테마는 피한다"라는 두 줄 덕분에 테마의 다양성이 유지되었습니다. 태그의 어휘도 기존 13종 중에서 선택하게 함으로써, "단 1건만 사용되는 태그"의 난립도 방지할 수 있었습니다.
1회당 20분 중 구현은 절반 정도이며, 나머지는 lint, 포맷팅, dev 서버에서의 동작 확인에 사용됩니다. 아깝게 느껴질 수 있지만, 무인으로 돌리는 루프에서는 "망가진 것을 쌓지 않는 것"이 최우선입니다. 검증을 얕게 해서 회전 속도를 높이는 것보다, 1회를 확실히 완결시키는 편이 최종적인 결과물은 더 많아집니다.
자동 생성된 리포지토리는 그대로 공부 소재가 됩니다. 저의 사용법은 이 세 가지입니다.
1. git log를 목차로 삼아 차이점(diff)을 읽는다
1커밋 = 1셰이더이므로, git show를 하는 것만으로 "이 테마는 이렇게 구현했다"를 차이점으로 읽을 수 있습니다.
git log --oneline | grep 雪
git show 7336522 # Snowflake의 구현 전체가 1커밋으로 보인다
2. Storybook으로 카탈로그처럼 살펴본다
모든 컴포넌트에 스토리가 붙어 있으므로, npm run storybook으로 200개가 넘는 셰이더를 일람으로 비교해 볼 수 있습니다. "이 표현 좋다" → 해당 파일의 GLSL을 읽는다, 라는 흐름이 최단 경로입니다.
3. GLSL 이디엄(Idiom)을 횡단 검색한다
타입이 통일되어 있으므로 grep이 잘 작동합니다. 예를 들어 fbm(Fractal Noise)을 사용하고 있는 구현을 전부 나열하여, 파라미터의 차이가 시각적으로 어떻게 작용하는지 비교할 수 있습니다.
grep -rl "float fbm" app/components/Gallery | head
생성된 코드에 일본어 주석으로 섹션 헤더가 붙어 있는 것도 은근히 효과적입니다 (이 또한 지시문(Instruction)에서 강제한 항목입니다). 예를 들어 간헐천 셰이더(Shader)에는 옐로스톤의 열천 온도와 미생물 매트(Microbial mat) 색상의 대응 관계가 주석으로 적혀 있어,
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기