티스토리 뷰
[9주차 과제]
1. TDD란 (내 포폴에 TDD 적용해보기)
2. CI/CD란 (Github Actions 통해서 배포 후 디스코드 채널로 알림 오도록 설정)
1. TDD(Test Driven Development, 테스트 주도 개발)
정의 : 소프트웨어 개발에 앞서 테스트를 먼저 작성하는 접근 방식
(프로덕션 코드를 작성하기 전에 테스트 코드를 먼저 작성하는 개발 방법론)
-> 테스트가 코드의 설계와 개발을 이끌어가는 방식
< 핵심 사이클: Red - Green - Refactor >
🔴 Red: 실패하는 테스트를 먼저 작성 (구현이 없으니 당연히 실패)
🟢 Green: 테스트를 통과시키는 최소한의 코드만 작성
🔵 Refactor: 테스트가 통과하는 상태에서 코드 구조 개선
-> 이 사이클을 짧은 호흡(보통 몇 분 단위)으로 반복
왜 하는가
- 버그 조기 발견
- 회귀(regression) 방지 → 테스트 스위트가 안전망 역할
- "테스트하기 쉬운 코드" = 자연스럽게 결합도 낮은 좋은 설계
- 테스트 코드가 곧 살아있는 명세(문서) 역할
// 회귀(Regression) : 원래 잘 되던 기능이 다시 망가지는 현상
// 테스트 스위트(Test Suite) : 여러 개의 테스트를 묶어놓은 집합(테스트 모음집)
TDD에서 회귀 방지가 가능한 이유:
- 기능을 만들 때마다 그 기능에 대한 테스트가 함께 작성됨
- 시간이 지나면 → 프로젝트에 수백 개의 테스트가 쌓임
- 새 코드를 추가한 후 모든 테스트를 한 번 돌려보면
만약 기존 기능 B가 깨졌다면 → B에 대한 테스트가 실패함 → 즉시 발견!
포트폴리오 적용
작은 기능 하나 잡아서, 테스트부터 쓰고, 통과시키고,
정리하는 사이클을 반복한 흔적을 코드와 커밋 히스토리에 남기기
#환경 세팅
Next.js에서 Jest가 안정적.
// Jest = JavaScript용 테스트 프레임워크
(Meta에서 만든 오픈소스 테스트 도구)
-> JavaScript/TypeScript로 짠 코드가 의도대로 동작하는지 자동으로 검증해주는 프로그램
테스트 대상: route.js (chat API) 입력 검증
1) 패키지 설치
npm install -D jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom @testing-library/user-event
// -D 플래그는 devDependencies(개발 의존성)에 설치한다는 뜻
(개발의존성은 개발할 때만 필요하고, 실제 서비스에는 필요 없는 패키지)
2) 설치 확인
-> package.json에서 5개 패키지 체크

3) Jest 설정 파일 만들기
루트(최상위)에 "jest.config.js"랑 "jest.setup.js" 파일 만들기
jest.config.js
-> Jest가 어떻게 동작할지 알려주는 설정 파일
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './',
});
const customJestConfig = {
setupFilesAfterEach: ['<rootDir>/jest.setup.js'],
testEnvironment: 'jest-environment-jsdom',
};
module.exports = createJestConfig(customJestConfig);
jest.setup.js
-> 각 테스트 실행 전에 공통으로 불러올 코드 적는 파일
import '@testing-library/jest-dom';
이 한줄로 같은 DOM 전용 매처를 모든 테스트에서 자동으로 사용 가능
// Matcher(매처) = 값을 어떻게 검증할지 정하는 함수
-> expect (실제값))매처 (기대값);
4) package.json에 테스트 스크립트 추가
package.json 파일 열고 Scripts에 아래 두 줄 추가(콤마 잘 붙여줘야함)
"test": "jest",
"test:watch": "jest --watch"

5) 환경 세팅 체크(Jest 정상 동작 체크)
프로젝트 루트에 __tests__ 폴더 만들고, 그 안에 sanity.test.js 파일 생성 후 아래 내용 입력
test('Jest가 정상 동작한다', () => {
expect(1 + 1).toBe(2);
});
// sanity test는 정상인지 체크하는 가장 기초적인 테스트(환경 동작 검증)
-> 터미널에서 npm test
PASS, 1 passed => 환경 세팅 완료

# TDD 사이클 시작 (Red → Green → Refactor 한 사이클)
시나리오
/api/chat 라우트에 잘못된 요청이 왔을 때 적절히 응답하는지 검증
-> messages 배열의 마지막 메시지 content가 빈 문자열이면 400 상태코드를 반환해야 한다
// ChatWidget.jsx에서 서버로 요청 보낼 때
fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({
messages: [{ role: 'user', content: '' }] // ← content가 비어있음
})
});
🔴 Red 단계
- __tests__/api/chat.test.js 파일 생성
- "message content가 빈 문자열이면 400" 테스트 코드 작성
- npm test 실행 → 실패 확인
🟢 Green 단계
- route.js에 검증 로직 추가
- npm test 실행 → 통과 확인
🔵 Refactor 단계
- 검증 로직 분리해서 깔끔하게
- npm test 다시 실행 → 여전히 통과
Red 단계)


Red에서 "기능 코드는 한 줄도 안 짰음"
route.js(실제 기능 파일)는 손도 안 대고, 테스트 파일만 새로 만듦
"기능 명세서를 코드로 미리 적어둠"
-> Red 단계는 본질적으로 "이런 기능을 만들 거야"라고 코드로 약속하는 단계
*비유
🔴 Red = 시험 문제를 출제 (정답은 모르는 상태)
🟢 Green = 그 시험 문제를 풀어서 정답 맞히기
Green 단계)
테스트 통과시키기.
1. API 라우트는 브라우저 환경(jsdom)이 아닌 Node.js 환경에서 돌아야함
테스트 파일 상단에 환경 지시자 추가
(node 환경에서 돌려달라고 Jest에게 파일별로 지시하는 주석)
/**
* @jest-environment node
*/
2. route.js에 아래 코드 추가
const lastMessage = messages[messages.length - 1] if (!lastMessage?.content?.trim()) { return Response.json({ error: 'Message content cannot be empty' }, { status: 400 }) }

Refactor 단계)
테스트가 통과하는 상태에서 코드를 더 깔끔하게 정리하는 단계(리팩토링)
-> 기능은 그대로 코드만 개선, 테스트는 계속 통과
원칙: 리팩토링은 Green 상태에서 시작하고 한 번에 하나씩만 바꾸기
리팩토링 후 반드시 테스트 다시 돌리기. 기능 추가하지 말기
const lastMessage = messages[messages.length - 1]
if (!lastMessage?.content?.trim()) {
return Response.json({ error: 'Message content cannot be empty' }, { status: 400 })
}
const history = messages.slice(0, -1).map(m => ({
role: m.role === 'assistant' ? 'model' : 'user',
parts: [{ text: m.content }],
}))
const lastInput = messages[messages.length - 1].content // ← 중복
마지막 한줄만 수정
-> const lastInput = lastMessage.content
// 위에서 만든 변수 재사용
이후 테스트, 여전히 패스하면 한 사이클 성공! githup push함.
// 코드의 일부를 바꾸더라도 테스트를 바로 하기 때문에
변경의 안정성을 바로 검증할 수 있음(안전망)

'AI스쿨 > 알토르과정' 카테고리의 다른 글
| [알토르] 9주차 추가과제 : SEO & AEO (4) | 2026.05.02 |
|---|---|
| [알토르] 9주차(2) : CI/CD(Github Action 적용 + 디스코드 알림) (0) | 2026.04.30 |
| [알토르] 8주차 추가과제 : JSON 응답 고정하고 추천 질문 받기 (2) | 2026.04.25 |
| [알토르] 8주차 과제 : Next.js에서 API 만들기 (0) | 2026.04.22 |
| [알토르] 7주차 : Flask API 서버 배포 및 Vercel 연동 (0) | 2026.04.19 |
