[바이브코딩]AI와 함께 만드는 청약 뉴스레터 서비스

클로드 코드를 이용한 바이브코딩 실전 사례 #1

by 대협

그동안 AI 코딩을 배우면서 하나하나 만들었던 바이브코딩 프로젝트의 작품들을 다시한번 버전업을 하는 방식으로 검토하고 이전에 말했던 context Engineering, SDD, TDD 기준에 맞추어 배운 지식을 활용하여 보다 품질 좋은 서비스를 만들어보고자 이번주부터 도전을 시작한다. 작년 5월부터 시작한 작업들이며 거의 50개 가량의 프로젝트라서 시간은 오래 걸릴 수 있지만 이제는 클로드코드가 있으니 일에 대한 부담감은 정말 줄어서 이런 도전이 가능하다는 것 자체가 정말 신선하다. 어느 정도 꾸준히 할 수 있을지는 모르지만 차근차근 한발 한발 나아가며 그 기록을 이곳에 남기고자 한다.



아이디어의 시작
"사무실 직원들이 매일 청약홈을 들여다본다"

요즘 사무실에서 흔히 볼 수 있는 광경이 있다. 점심시간이면 젊은 직원들이 청약홈(applyhome.co.kr)에 접속해서 분양 정보를 검색하고, 특별공급 자격을 확인하고, 청약 일정을 캘린더에 적어놓는 모습이다. 서울과 수도권의 아파트 가격이 여전히 높은 상황에서, 청약은 많은 직장인들에게 내 집 마련의 거의 유일한 희망이 되었다.이 모습을 지켜보며 한 가지 생각이 떠올랐다. (이 시기가 '25년 6월이었는데 지금은 정부 정책이 많이 바뀌어서 집값이 안정되며 그때보다는 덜하지만 여전히 많은 분들의 관심사중 하나가 집마련임에는 불변하지 않는 욕망이자 진리이다.)"이 청약 정보를 자동으로 크롤링해서 엑셀로 만들고, 매일 아침 이메일로 보내면 어떨까?" 단순히 데이터를 전달하는 것을 넘어, AI가 분석 리포트까지 작성해주는 뉴스레터 서비스라면 정말 유용하지 않을까?

이 아이디어는 몇 가지 핵심 요소로 구체화되었다.

공공데이터포털 API를 활용한 청약홈 분양 정보 자동 수집

수집된 데이터를 엑셀 파일로 깔끔하게 정리

GPT-4o-mini를 활용한 AI 분석 리포트 자동 생성

이메일 + Slack 멀티채널 발송

GitHub Actions를 이용한 매일 아침 자동 실행

전 과정 무료 (OpenAI API 비용 월 $0.5 미만)

Gemini_Generated_Image_tgshv3tgshv3tgsh.png

그리고 이 프로젝트를 Claude AI와 함께 개발하기로 했다. AI와 대화하며 명세를 작성하고, 토론을 통해 의사결정을 하고, TDD 방식으로 한 줄 한 줄 코드를 만들어나가는 과정 자체가 하나의 새로운 개발 경험이 될 것이라 기대했다.

개발 방법론

SDD(명세주도개발) + TDD(테스트주도개발)

이 프로젝트에서는 두 가지 개발 방법론을 결합하여 사용했다. 코드를 작성하기 전에 반드시 명세를 먼저 작성하는 SDD와, 구현 전에 테스트를 먼저 작성하는 TDD이다.

SDD: 명세주도개발이란?

SDD(Spec-Driven Development)는 모든 개발을 SPEC → PLAN → TASK → 실행 순서로 진행하는 방법론이다. 각 프로젝트의 docs/ 디렉토리에 세 개의 문서를 생성하고 유지한다.

핵심 원칙은 다음과 같다.

SPEC이 없으면 코드를 작성하지 않는다.

PLAN이 없으면 구현을 시작하지 않는다.

SPEC과 PLAN 단계에서는 토론을 통해 의사결정 사항을 확정한다.

TASK의 각 항목은 완료 즉시 체크한다.

요구사항 변경 시 SPEC → PLAN → TASK 순서로 역추적하여 갱신한다.

TDD: 테스트주도개발이란?

TDD는 Red → Green → Refactor 사이클을 반복하는 개발 방법이다.

Red 단계에서는 아직 구현되지 않은 기능의 테스트를 먼저 작성한다. 당연히 테스트는 실패한다. Green 단계에서는 테스트를 통과하는 최소한의 코드를 구현한다. Refactor 단계에서는 테스트가 통과하는 상태를 유지하며 코드를 정리한다.

이 프로젝트에서는 외부 API 호출을 mock으로 대체하여 테스트 독립성을 확보했고, 실제 API를 호출하는 통합 테스트는 @pytest.mark.integration 마커로 분리했다. 최종적으로 63개의 단위 테스트와 4개의 통합 테스트, 총 67개의 테스트를 작성했다.

Gemini_Generated_Image_37an0n37an0n37an.png
SPEC 작성 — 토론으로 결정하는 의사결정


프로젝트를 시작하기 전, Claude AI와 함께 7개의 의사결정 사항을 토론했다. AI가 일방적으로 결정하는 것이 아니라, 각 항목에 대해 선택지와 트레이드오프를 제시하고 개발자가 최종 판단하는 방식이었다.

의사결정 1: 데이터 소스

청약홈에서 데이터를 가져오는 방법은 세 가지가 있었다. 공공데이터포털 API, 청약홈 직접 크롤링, 둘 다 병행. 안정성과 합법성을 고려하여 공공데이터포털 API를 선택했다. 일 호출 한도 40,000건으로 충분했고, JSON 형식의 구조화된 응답을 받을 수 있었다.

의사결정 2: 수집 데이터 범위

청약 정보에는 APT 분양, 오피스텔, 무순위, 특별공급 등 다양한 유형이 있었다. 사무실 직원들이 주로 관심을 갖는 것은 APT 분양이었기에, APT 분양(민간+공공)과 무순위/잔여세대를 핵심 수집 대상으로 결정했다.

의사결정 3: 수신자 관리 방식

초기에는 사무실 동료 몇 명에게만 보내는 것이 목표였기에, config/recipients.yaml 파일에 수신자를 하드코딩하는 고정 수신자 방식을 선택했다. 향후 구독자가 늘어나면 DB 기반 구독 관리로 전환할 수 있도록 설계했다.

의사결정 4: 발송 채널

이메일(Gmail SMTP), Slack(Incoming Webhook), 카카오톡(나에게 보내기) 세 채널을 선택했다. Gmail SMTP는 가장 범용적이고, Slack은 사무실에서 바로 확인할 수 있으며, 카카오톡은 모바일에서 빠르게 확인할 수 있다는 장점이 있었다.

다만 카카오톡은 개발 과정에서 Redirect URI 등록 이슈로 보류되었다. 카카오 개발자 콘솔의 UI가 변경되어 Redirect URI 등록 메뉴를 찾기 어려웠고, 이는 실제 개발에서 흔히 겪는 외부 서비스 연동의 어려움을 보여주는 사례가 되었다.

의사결정 5: 콘텐츠 형태

단순 데이터 전달이 아닌, GPT-4o-mini가 작성하는 AI 분석 리포트를 포함하기로 했다. HTML 이메일 본문에 분석 리포트를 삽입하고, 엑셀 파일을 첨부하는 형태다. 리포트는 수도권(서울, 경기, 인천) 중심으로 분석하되, 비수도권 공고는 간략히 요약하는 방식으로 결정했다.

의사결정 6: 실행 환경

GitHub Actions를 선택했다. 서버가 필요 없고, 월 2,000분 무료 한도 내에서 충분히 운영 가능했다. 매일 KST 08:30에 cron으로 자동 실행되고, 수동 실행도 지원한다.

의사결정 7: 프로젝트명

housing-subscribe-alert. 직관적으로 청약 구독 알림 서비스임을 나타낸다.

Gemini_Generated_Image_f804enf804enf804.png

이렇게 7개 의사결정을 마치고, 추가로 API 탐색 관련 세부 사항(Phase 0 분리 여부, 엑셀과 리포트 결합 여부, 카카오 토큰 갱신 시점, 테스트 전략)까지 5개 추가 토론을 거쳐 SPEC.md를 완성했다.

PLAN 수립 — 6개 Phase로 나누기


SPEC이 확정된 후, 전체 개발을 6개 Phase로 나누었다. 각 Phase는 명확한 목표와 산출물을 가지며, 이전 Phase의 결과물에 의존한다.

Gemini_Generated_Image_v7pr7cv7pr7cv7pr.png

아키텍처 설계

전체 데이터 흐름은 다음과 같다.

Gemini_Generated_Image_jrsl95jrsl95jrsl.png

모듈 의존관계

모든 모듈은 config.py를 공통으로 의존하고, DB 모델을 통해 데이터를 주고받는다. 채널(email, slack, kakao)은 서로 독립적이어서 하나가 실패해도 나머지는 계속 동작한다. 이 독립성은 실제 운영에서 매우 중요한 설계 결정이었다.

테스트 전략

테스트를 단위 테스트와 통합 테스트로 구분했다. 단위 테스트는 mock을 사용하여 외부 의존성 없이 실행되고, 통합 테스트는 @pytest.mark.integration 마커를 붙여 실제 API 호출이나 이메일 발송이 필요할 때만 실행한다.

# 단위 테스트 (CI용)
pytest tests/ -v -m "not integration"
# 통합 테스트 (로컬 수동)
pytest tests/ -v -m integration

실전 트러블슈팅

이 트러블슈팅 과정에서 얻은 교훈은, 로컬 환경에서 완벽해 보이는 코드도 실제 운영 환경(웹메일 클라이언트, GitHub Actions, 외부 API)에서는 예상치 못한 문제를 만날 수 있다는 것이다. TDD가 로직의 정확성을 보장해주지만, 통합 테스트와 실제 발송 테스트가 없었다면 이런 문제들을 발견하지 못했을 것이다.

스크린샷 2026-03-21 오후 5.03.01.png
회고 — AI와 협업한 개발의 의미

SDD + TDD의 효과

SPEC → PLAN → TASK 순서로 문서를 먼저 작성한 것은 큰 효과가 있었다. 코드를 작성하기 전에 전체 그림이 잡혀 있었기에, Phase 간 모듈 의존관계가 명확했고, 나중에 되돌아가서 수정할 일이 거의 없었다.

TDD는 리팩토링의 안전망이 되었다. 이메일 HTML을 inline style로 전면 수정할 때, 63개 테스트가 모두 통과하는 것을 확인하며 자신감을 가지고 변경할 수 있었다. 또한 mock 패턴을 일관되게 사용하여 외부 API 없이도 모든 로직을 검증할 수 있었다.

AI와 협업의 특징

Claude AI와의 협업에서 가장 인상적이었던 것은 토론 과정이었다. SPEC 단계에서 7개 의사결정 사항에 대해 선택지와 트레이드오프를 제시받고, 개발자가 최종 판단을 내리는 구조는 매우 효과적이었다.

AI는 코드를 빠르게 작성할 수 있었지만, "수도권은 서울, 경기, 인천만이다"와 같은 도메인 지식이나, 사람에게 보기좋은 디자인 판단은 개발자만이 할 수 있었다. 이런 역할 분담이 좋은 결과를 만들어냈다.

토요일 연재
이전 10화AI 시대의 테스트와 품질