04. 내 컴퓨터 안의 가상 서버 (Emulator & TDD)
"배포는 짜릿하지만 위험합니다. 내 컴퓨터에서 먼저 완벽하게 검토하세요."
실제 서버에 코드를 올렸을 때 에러가 나면 수정하기 어렵고 비용도 발생할 수 있습니다. Firebase 에뮬레이터를 통해 클라우드와 똑같은 환경을 내 컴퓨터에 만들고, 테스트 코드로 품질을 보장하는 법을 배웁니다.
1. Local Emulator: 완벽한 시뮬레이션
Firebase 에뮬레이터는 구글 클라우드 서버를 내 컴퓨터에 그대로 복제해 놓은 것과 같습니다.
🛠️ 에뮬레이터 환경 통합
프론트엔드와 백엔드 코드가 로컬 에뮬레이터를 바라보도록 설정합니다.
- 프론트엔드(React):
localhost:8080(DB),localhost:9099(Auth)에 연결. - 백엔드(FastAPI): 환경 변수
FIRESTORE_EMULATOR_HOST와GCLOUD_PROJECT를 설정하여 로컬 DB에 접속.
// frontend/src/firebase.ts
if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
console.log("🔧 Using Firebase Emulators");
connectAuthEmulator(auth, "http://127.0.0.1:9099");
connectFirestoreEmulator(db, "127.0.0.1", 8080);
}
⚠️ 데이터 오염 주의
환경 변수 설정 없이 스크립트를 실행하면 실제 운영(Production) DB에 데이터가 들어갈 수 있습니다. 에뮬레이터 UI(localhost:4000)에 데이터가 보이지 않는다면 설정을 다시 확인하세요.
2. Test Driven: AI를 활용한 테스트 자동화
"코드가 잘 돌아가겠지?"라는 추측 대신, 테스트 코드로 증명해야 합니다. AI는 복잡한 테스트 케이스를 짜는 데 아주 훌륭한 조수입니다.
🧪 TDD 개발 워크플로우 (3단계 원칙)
기본적으로 필요한 백엔드 기능(Functions)을 중심으로 테스트 코드를 작성하여 TDD 기반을 구축합니다. 나중에 프론트엔드 TDD와 연동하여 전체 개발 과정에 TDD를 활용하게 됩니다.
참고: 프론트엔드 테스트는?
이 챕터에서는 백엔드 로직의 무결성을 검증하는 데 집중합니다. React 컴포넌트나 UI 상호작용에 대한 테스트(Frontend TDD)는 6장 Capstone: AI Agent에서 다루며, 최종적으로 두 테스트가 합쳐져 완벽한 CI/CD 파이프라인을 구성합니다.
모든 백엔드 테스트는 [1. 초기화(Initialize) → 2. 시딩(Seed) → 3. 테스트(Test)]의 3단계 구성을 따릅니다.
- 초기화 (Initialize): 에뮬레이터 환경에서 이전 테스트의 잔류 데이터를 배제하고 깨끗한 상태로 시작합니다.
- 시딩 (Seed):
seed.py등을 실행하여 테스트에 필요한 기초 데이터를 주입합니다. - 테스트 (Test): 준비된 환경에서 실제 비즈니스 로직(Happy/Sad Path)을 검증합니다.
- 멱등성 (Idempotency): 위 과정을 통해 테스트는 언제 어디서 실행해도 같은 결과를 내야 합니다.
- 환경 분리: 반드시 Firebase 에뮬레이터 환경에서 실행하여 운영 데이터 오염을 방지합니다.
📂 테스트 디렉토리 구조
└── functions/tests/ # ✅ 테스트 코드 모음
├── conftest.py # 설정 및 공유 Fixture (에뮬레이터 설정, 자동 시딩 등)
├── test_api.py # 엔드포인트(API) 테스트 (requests 활용)
└── test_logic.py # 순수 비즈니스 로직 테스트 (DAL 직접 호출)
🚀 테스트 실행
🤖 AI에게 테스트 요청하는 방법 (Design First)
무작정 테스트 코드를 작성해달라고 하면 AI도 헷갈려합니다.
먼저 prd.md에 정의된 기능 명세를 바탕으로 함수의 뼈대(Scaffolding)를 만들고, 그 다음에 테스트를 요청하세요.
- Step 1. 기능 명세 기반 함수 껍데기 생성
"
prd.md를 참고해서 [기능명]에 필요한 백엔드 함수와 데이터 입출력 양식만 먼저 만들어줘. (함수 내용은pass로 비워둬도 좋아)" - Step 2. 테스트 코드 생성
"방금 만든 함수들을 검증할 수 있는
pytest코드를 작성해줘."
통합 프롬프트 예시
prd.md의 [기능명] 명세를 검증하고 싶어. 다음 단계로 개발해줘.
- 먼저
functions/main.py에 필요한 빈 함수(Empty Function)와 입출력 모델을 정의해줘. - 그 다음, 이 함수들이 정상 작동하는지 검증하는
pytest코드를tests/폴더에 작성해줘. - 테스트 실행 전
seed.py를 활용해 DB를 초기화하는 Fixture도 잊지 마.
3. Debugging: 데이터 흐름 추적하기
에뮬레이터의 꽃은 Emulator Suite UI입니다.
- Firestore Emulator: 데이터가 실시간으로 쌓이고 변하는 모습을 눈으로 확인합니다.
- Logs: FastAPI에서 출력하는
print나 에러 로그를 한곳에서 모아봅니다. - Authentication: 가짜 계정을 무제한으로 만들어 로그인 테스트를 진행합니다.
4. [Check] 배포 전 최종 점검 (Pre-flight Check)
테스트가 모두 통과했다면, 배포 직전 마지막 관문을 통과해야 합니다.
- Linting: 코드 스타일이 깔끔한가? (
flake8,eslint) - Environment Variables: 실제 서버용 API Key와 로컬용 주소가 섞이지 않았는가?
- Build Test:
npm run build를 했을 때 에러 없이 완료되는가?
5. 핵심 정리
| 용어 | 설명 | 비유 |
|---|---|---|
| Emulator Suite | Firebase의 모든 기능을 로컬에서 돌려주는 도구 | 가상 비행 시뮬레이터 |
| TDD (테스트 주도 개발) | 테스트 코드를 먼저 짜거나 병행하며 개발하는 방식 | 설계도대로 지어졌는지 검측하며 짓기 |
| Pytest | Python 코드를 테스트하기 위한 쉽고 강력한 프레임워크 | 자동 검사 장치 |
| Mocking | 실제 DB나 API 대신 가짜 데이터를 사용하는 기술 | 연습용 샌드백 |
준비 완료! 이제 우리 시스템은 '검증된 시스템'이 되었습니다. 다음 05장에서는 내가 수동으로 배포하지 않아도, 코드를 올리기만 하면 비서가 알아서 배포해 주는 24시간 자동 배포 시스템(CI/CD)을 구축해 보겠습니다!
실습 과제: 에뮬레이터를 켠 상태에서 AI가 짜준 테스트 코드를 실행(pytest)해 보고, 모든 테스트가 Green (Pass)이 뜨는 짜릿함을 경험해 보세요!