본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 26. 11:19

템플릿에서 프로덕션 수준까지: Go 사이드 프로젝트를 위한 AI 네이티브 개발 흐름

요약

Go 백엔드 템플릿과 'qrspi'라는 구조화된 AI 워크플로우를 결합하여 사이드 프로젝트를 프로덕션 수준으로 빠르게 구축하는 방법을 소개합니다. 헥사고날 아키텍처와 엄격한 의존성 규칙을 준수하며 AI를 활용해 개발 효율을 극대화하는 프로세스에 집중합니다.

핵심 포인트

  • qrspi(질문-조사-구조화-계획-구현) AI 워크플로우 활용
  • 헥사고날 아키텍처 기반의 Go 백엔드 템플릿 사용
  • depguard를 통한 엄격한 패키지 의존성 및 아키텍처 규칙 강제
  • 기능 포트(Capability Ports)를 통한 기능 간 결합도 최소화

저는 다음 사이드 프로젝트가 — 헥사고날 아키텍처 (hexagonal architecture), sqlc, depguard, 통합 테스트 (integration tests) 등 — 마치 직장에서 배포하는 코드처럼 보이기를 원했습니다. 하지만 첫 번째 도메인 로직 (domain logic)을 작성하기도 전에 스캐폴딩 (scaffolding)에 세 번의 저녁 시간을 허비하는 일반적인 사이드 프로젝트의 비용을 치르고 싶지는 않았습니다. 그래서 저는 이를 두 번에 걸쳐 구축했습니다. 먼저, 몇 달 동안 다듬어 온 Go 백엔드 템플릿을 포크 (fork)했습니다. 그다음, 제가 qrspi라고 부르는 구조화된 AI 워크플로우 — 질문 (question) → 조사 (research) → 구조화 (structure) → 계획 (plan) → 구현 (implement) — 를 통해 그 위에 모든 기능을 구현했습니다.

제품 자체는 의도적으로 평범합니다. 바로 QR 코드 생성기입니다. URL을 붙여넣으면 스캔 가능한 PNG와 /r/:token 리다이렉트(redirect)를 반환하며, 링크별 스캔 횟수와 소프트 삭제 (soft-delete) 킬 스위치 기능을 갖추고 있습니다. 흥미로운 부분, 즉 리뷰어가 살펴봐 주었으면 하는 부분은 이것을 만들어낸 프로세스 (process) 입니다.

Repo: linkc0829/go-qrcode-generator. 이 포스트에서 언급된 모든 결과물은 그곳에 커밋되어 있습니다.

1단계: 템플릿을 선택하고, 그 규칙을 준수하기

0단계는 실제로 무엇을 기반으로 구축할지 선택하는 것이었습니다. 저는 몇 가지 Go 백엔드 템플릿을 후보로 선정했고, Claude와 함께 각 템플릿을 검토하며 아키텍처를 압박 테스트 (pressure-test)한 끝에, 한동안 다듬어 왔던 linkc0829/go-backend-template을 선택했습니다.

이 템플릿은 기능 우선(feature-first) 방식의 헥사고날 Go 백엔드입니다. 각 기능은 internal/<feature>/ 아래의 단일 패키지에 존재하며, 해당 패키지 내부에는 domain.go, service.go, ports.go 및 어댑터 (adapters)가 별도의 파일로 나란히 위치합니다. Go 패키지 경계가 곧 헥사곤 (hexagon)의 가장자리입니다.

이 규칙을 유지하게 만드는 핵심은 .golangci.yml에 설정된 depguard입니다. 다음과 같은 경우 빌드가 실패합니다:

  • domain.go가 표준 라이브러리 (stdlib) 및 공유 값 객체 (shared value objects) 이외의 것을 임포트 (import)할 때
  • service.go가 드라이버 (driver)나 웹 프레임워크 (web framework)에 접근할 때
  • handler_*.go가 레포지토리 (repo)나 캐시 (cache)를 직접 건드릴 때
  • 한 기능이 다른 기능을 임포트할 때

마지막 규칙이 가장 큰 가치를 발휘합니다. 기능 간 의존성(Cross-feature dependencies)은 **기능 포트 (capability ports)**를 통해 강제됩니다. 즉, 기능 A가 필요한 기능의 이름을 딴 인터페이스를 정의하면, internal/bootstrap/wire.go에 있는 컴포지션 루트 (composition root)가 이를 충족하기 위해 기능 B의 서비스를 주입(inject)합니다. 각 기능은 서로의 존재를 전혀 알지 못합니다.

이것은 제가 실제로 감수해야 했던 첫 번째 결정이었습니다. 템플릿에는 데모용 user, order, payment 슬라이스(slice)가 포함되어 있습니다. 하지만 제 프로젝트에는 주문(order)도 결제(payment)도 없습니다. 규칙은 다음과 같습니다.

  • 토큰은 96비트 crypto/rand를 사용하여 base64url로 인코딩합니다. 이로 인해 반복되는 (사용자, URL) 쌍에 대한 멱등성 (idempotency)은 상실되지만, 결정론적 토큰 유출 (deterministic-token leak) 공격 표면을 방지할 수 있습니다.
  • CDN 계층은 제외되었습니다. 브라우저는 MinIO의 익명 download 버킷 정책을 사용하여 PNG를 직접 가져옵니다. 이는 에지 캐시 (edge cache)를 제외하면 S3+CloudFront와 동일한 아키텍처 구조입니다.
  • 소프트 삭제 (Soft delete) 및 PUT/DELETE 엔드포인트는 이후의 슬라이스 (slice)에서 다룹니다.

이러한 편차(deviations)를 사전에 기록하는 과정이 설계를 정직하게 만드는 부분입니다. 또한 이는 포트폴리오 검토자의 업무를 수월하게 만드는 부분이기도 합니다. 검토자는 단순히 무엇이 구축되었는지만 보는 것이 아니라, 무엇을 왜 희생했는지를 볼 수 있기 때문입니다.

3단계: qrspi — 실제 구축을 수행하는 워크플로우

워크플로우 아이디어는 Research-Plan-Implement (RPI)에서 시작되었습니다. QRSPI는 커뮤니티 논의에서 얻어 이 프로젝트에 맞게 조정한 RPI의 8단계 확장 버전입니다.

사양(spec)이 문서화되면, 모든 기능은 동일한 8단계를 거칩니다. 각 단계는 특정 기술(skill)을 기반으로 하는 슬래시 명령어이며, 각 단계는 결과물(artifact)을 thoughts/qrspi/<date>-<slug>/에 기록합니다:

  1. /qrspi:1_question — 티켓을 중립적인 연구 질문으로 분해합니다. 아직 의견은 배제합니다.
  2. /qrspi:2_research — 코드베이스를 읽어 질문에 답합니다. 사실(facts)만을 다룹니다.
  3. /qrspi:3_design어떻게(how) 할지 논의하기 전에 어디로(where) 갈지를 논의합니다. 여기서 트레이드오프 (trade-offs)가 드러납니다.
  4. /qrspi:4_structure — 테스트 체크포인트가 포함된 수직 슬라이스 (vertical slices)의 개요를 작성합니다.
  5. /qrspi:5_plan — 전술적인 구현 계획이며, 저의 작업 문서입니다.
  6. /qrspi:6_worktree — 메인 체크아웃 상태를 깨끗하게 유지하기 위한 격리된 git 워크트리 (worktree)를 사용합니다.
  7. /qrspi:7_implement — 각 체크포인트에서 검증하며 계획을 단계별로 실행합니다.
  8. /qrspi:8_pr — 설계 컨텍스트를 리뷰 단계까지 전달하는 PR (Pull Request)을 생성합니다.

MinIO 기능 구현 사례를 보면 디스크에 전체 과정이 모두 나타납니다. MCP를 통해 Notion 소스에서 가져온 ticket.md, 그리고 이어서 questions.md, research.md, design.md, structure.md, plan.md가 생성됩니다. 각 파일은 이전 파일의 내용을 바탕으로 구축됩니다. 구현(Implementation)이 시작될 때쯤이면, 에이전트(Agent)는 추측하는 것이 아니라 제가 이미 동의한 계획을 실행하고 있습니다.

후속 작업이었던 Redis 리다이렉트 캐시(Redis redirect cache)도 동일한 방식으로 배포되었습니다. 계획 단계에서 읽기 집약적인(read-heavy) 형태를 명시했고, 매 스캔마다 Postgres에 부하를 주는 것을 방지하기 위해 쓰기 지연(write-behind) 클릭 수 버퍼를 선택했으며, 캐시 불변성(cache invariants)을 명시적으로 정의했습니다. 설계 단계에서 흥미로운 질문들을 이미 해결했기 때문에, 구현 과정은 거의 기계적인 작업에 가까웠습니다.

이것이 얻는 것과 치르는 대가

비용은 실재합니다. 각 기능마다 5~6개의 마크다운(Markdown) 설계 산출물 파일이 수반됩니다. 1인 개발자의 사이드 프로젝트라면, 자유로운 스케치 단계에서는 용납하기 힘든 오버헤드(Overhead)일 것입니다.

얻는 것:

  • 차이점(Diff)을 검토할 수 있습니다. 모든 커밋은 작고, 범위가 제한적이며, 설계 결정 사항으로 추적 가능합니다.
  • 아키텍처(Architecture)가 유지됩니다. depguard가 느린 표류(slow-drift) 위반 사항(예: 핸들러가 리포지토리에 직접 접근하거나, 기능 A가 기능 B를 임포트하는 경우)이 발생하는 즉시 잡아내며, 이는 3개월 뒤가 아닌 발생 시점에 이루어집니다.
  • 에이전트가 2,000행(LOC) 이상의 코드에서도 유용함을 유지합니다. 대부분의 AI 코딩 흐름은 코드베이스가 커짐에 따라 모델이 맥락을 놓치기 때문에 성능이 저하됩니다. design.mdplan.md에 맥락(Plot)을 기록해 두는 것은 다음 세션이 중심을 잃지 않도록 잡아줍니다.
  • 포트폴리오의 핵심은 결과물이 아닌 '과정'입니다. 누구나 QR 코드 생성기를 배포할 수 있습니다. 하지만 아키텍처, 트레이드오프(Trade-offs), 그리고 사양(Spec)으로부터의 이탈 사항까지 모두 디스크에 기록하며 배포하는 것은 완전히 다른 차원의 신호(Signal)를 전달합니다.

템플릿은 GitHub에 있으며, qrspi 아티팩트(artifacts)는 코드와 함께 커밋됩니다. 단일 기능이 티켓(ticket)에서 풀 리퀘스트(PR)로 어떻게 흐르는지 보고 싶다면, MinIO 슬라이스가 가장 깔끔한 예시입니다. docs/adr/에 있는 아키텍처 ADR(Architecture Decision Records)은 두 가지 근본적인 결정 사항을 다룹니다: 기능 우선 헥사고날(feature-first hexagonal) 아키텍처, 그리고 ORM 대신 sqlc를 사용하는 것입니다.

다음 단계는 메트릭(metrics) 슬라이스(Prometheus + 리다이렉트 지연 시간(redirect latency)을 위한 Grafana 대시보드)와 사양(spec)의 전체 CRUD 인터페이스(surface)를 완성하기 위한 적절한 삭제(deletion) 후속 작업입니다. 두 작업 모두 qrspi를 통해 진행될 것입니다. 그것이 핵심입니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0