๊ฐ๋ ฅํ ํตํฉ ํ ์คํธ๋ฅผ ์ํด TypeScript๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ํ์ํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์ ์ ์๋ํฌ์๋ ํ์ ์์ ์ฑ๊ณผ ์ ๋ขฐ์ฑ์ ๋ณด์ฅํ์ธ์. ๋ ์์ ๊ฐ ์๋ ๊ฐ๋ฐ ํ๋ก์ธ์ค๋ฅผ ์ํ ์ค์ฉ์ ์ธ ๊ธฐ๋ฒ๊ณผ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์์๋ณด์ธ์.
TypeScript ํตํฉ ํ ์คํธ: ์๋ํฌ์๋ ํ์ ์์ ์ฑ ํ๋ณด
์ค๋๋ ๋ณต์กํ ์ํํธ์จ์ด ๊ฐ๋ฐ ํ๊ฒฝ์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ขฐ์ฑ๊ณผ ๊ฒฌ๊ณ ์ฑ์ ๋ณด์ฅํ๋ ๊ฒ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ ๋ ํ ์คํธ๋ ๊ฐ๋ณ ๊ตฌ์ฑ ์์๋ฅผ ๊ฒ์ฆํ๊ณ , ์๋ํฌ์๋ ํ ์คํธ๋ ์ ์ฒด ์ฌ์ฉ์ ํ๋ฆ์ ๊ฒ์ฆํ๋ ๋ฐ๋ฉด, ํตํฉ ํ ์คํธ๋ ์์คํ ์ ๋ค์ํ ๋ถ๋ถ ๊ฐ์ ์ํธ ์์ฉ์ ๊ฒ์ฆํ๋ ์ค์ํ ์ญํ ์ ํฉ๋๋ค. ์ฌ๊ธฐ์ TypeScript๋ ๊ฐ๋ ฅํ ํ์ ์์คํ ์ ํตํด ์๋ํฌ์๋ ํ์ ์์ ์ฑ์ ์ ๊ณตํจ์ผ๋ก์จ ํ ์คํธ ์ ๋ต์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค.
ํตํฉ ํ ์คํธ๋ ๋ฌด์์ธ๊ฐ์?
ํตํฉ ํ ์คํธ๋ ์ ํ๋ฆฌ์ผ์ด์ ๋ด์ ์๋ก ๋ค๋ฅธ ๋ชจ๋ ๋๋ ์๋น์ค ๊ฐ์ ํต์ ๋ฐ ๋ฐ์ดํฐ ํ๋ฆ์ ๊ฒ์ฆํ๋ ๋ฐ ์ค์ ์ ๋ก๋๋ค. ์ด๋ ๊ตฌ์ฑ ์์๋ฅผ ๊ฒฉ๋ฆฌํ๋ ์ ๋ ํ ์คํธ์ ์ฌ์ฉ์ ์ํธ ์์ฉ์ ์๋ฎฌ๋ ์ด์ ํ๋ ์๋ํฌ์๋ ํ ์คํธ ์ฌ์ด์ ๊ฐ๊ทน์ ๋ฉ์๋๋ค. ์๋ฅผ ๋ค์ด, REST API์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ฐ์ ์ํธ ์์ฉ ๋๋ ๋ถ์ฐ ์์คํ ์ ์๋ก ๋ค๋ฅธ ๋ง์ดํฌ๋ก์๋น์ค ๊ฐ์ ํต์ ์ ํตํฉ ํ ์คํธํ ์ ์์ต๋๋ค. ์ ๋ ํ ์คํธ์ ๋ฌ๋ฆฌ, ์ด์ ๋ ์ข ์์ฑ๊ณผ ์ํธ ์์ฉ์ ํ ์คํธํ๋ ๊ฒ์ ๋๋ค. ์๋ํฌ์๋ ํ ์คํธ์ ๋ฌ๋ฆฌ, ์ผ๋ฐ์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ๋ฅผ ์ฌ์ฉํ์ง๋ ์์ต๋๋ค.
ํตํฉ ํ ์คํธ์ TypeScript๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ ๋ฌด์์ธ๊ฐ์?
TypeScript์ ์ ์ ํ์ดํ์ ํตํฉ ํ ์คํธ์ ์ฌ๋ฌ ๊ฐ์ง ์ด์ ์ ์ ๊ณตํฉ๋๋ค:
- ์กฐ๊ธฐ ์ค๋ฅ ๊ฐ์ง: TypeScript๋ ์ปดํ์ผ ์์ ์ ํ์ ๊ด๋ จ ์ค๋ฅ๋ฅผ ์ก์๋ด์ด ํตํฉ ํ ์คํธ ์คํ ์ค์ ์ด๋ฌํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์๋๋ก ๋ฐฉ์งํฉ๋๋ค. ์ด๋ ๋๋ฒ๊น ์๊ฐ์ ํฌ๊ฒ ์ค์ด๊ณ ์ฝ๋ ํ์ง์ ํฅ์์ํต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ฐฑ์๋์ ๋ฐ์ดํฐ ๊ตฌ์กฐ ๋ณ๊ฒฝ์ด ์๋์น ์๊ฒ ํ๋ก ํธ์๋ ๊ตฌ์ฑ ์์๋ฅผ ์ค๋จ์ํค๋ ์ํฉ์ ์์ํด ๋ณด์ธ์. TypeScript ํตํฉ ํ ์คํธ๋ ๋ฐฐํฌ ์ ์ ์ด๋ฌํ ๋ถ์ผ์น๋ฅผ ๊ฐ์งํ ์ ์์ต๋๋ค.
- ์ฝ๋ ์ ์ง๋ณด์์ฑ ํฅ์: ํ์ ์ ์ด์์๋ ๋ฌธ์ ์ญํ ์ ํ์ฌ ๋ค์ํ ๋ชจ๋์ ์์ ์ ๋ ฅ ๋ฐ ์ถ๋ ฅ์ ๋ ์ฝ๊ฒ ์ดํดํ ์ ์๋๋ก ํฉ๋๋ค. ์ด๋ ํนํ ํฌ๊ณ ๋ณต์กํ ํ๋ก์ ํธ์์ ์ ์ง๋ณด์ ๋ฐ ๋ฆฌํฉํ ๋ง์ ๋จ์ํํฉ๋๋ค. ๋ช ํํ ํ์ ์ ์๋ฅผ ํตํด ์ ์ฌ์ ์ผ๋ก ๋ค๋ฅธ ๊ตญ์ ํ์ ๊ฐ๋ฐ์๊ฐ ๊ฐ ๊ตฌ์ฑ ์์์ ๋ชฉ์ ๊ณผ ํตํฉ ์ง์ ์ ์ ์ํ๊ฒ ํ์ ํ ์ ์์ต๋๋ค.
- ํ์ ๊ฐํ: ์ ์ ์๋ ํ์ ์ ๊ฐ๋ฐ์ ๊ฐ์ ์์ฌ์ํต ๋ฐ ํ์ ์ ์ด์งํ๋ฉฐ, ํนํ ์์คํ ์ ๋ค๋ฅธ ๋ถ๋ถ์ ์์ ํ ๋ ์ ์ฉํฉ๋๋ค. ํ์ ์ ๋ชจ๋ ๊ฐ์ ๋ฐ์ดํฐ ๊ณ์ฝ์ ๋ํ ๊ณต์ ๋ ์ดํด ์ญํ ์ ํ์ฌ ์คํด ๋ฐ ํตํฉ ๋ฌธ์ ์ ์ํ์ ์ค์ ๋๋ค. ์ด๋ ๋น๋๊ธฐ ํต์ ์ด ์ผ๋ฐ์ ์ธ ๊ธ๋ก๋ฒ ๋ถ์ฐ ํ์์ ํนํ ์ค์ํฉ๋๋ค.
- ๋ฆฌํฉํ ๋ง ์์ ๊ฐ: ์ฝ๋์ ๋ณต์กํ ๋ถ๋ถ์ ๋ฆฌํฉํ ๋งํ๊ฑฐ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๊ทธ๋ ์ด๋ํ ๋, TypeScript ์ปดํ์ผ๋ฌ๋ ํ์ ์์คํ ์ด ๋ ์ด์ ๋ง์กฑ๋์ง ์๋ ์์ญ์ ๊ฐ์กฐ ํ์ํฉ๋๋ค. ์ด๋ฅผ ํตํด ๊ฐ๋ฐ์๋ ๋ฐํ์ ๋ฌธ์ ๋ฅผ ํผํ๋ฉด์ ๋ฌธ์ ๋ฅผ ์์ ํ ์ ์์ด ํ๋ก๋์ ์์ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
TypeScript ํตํฉ ํ ์คํธ ํ๊ฒฝ ์ค์
ํตํฉ ํ ์คํธ์ TypeScript๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ๋ ค๋ฉด ์ ์ ํ ํ๊ฒฝ์ ์ค์ ํด์ผ ํฉ๋๋ค. ๋ค์์ ์ผ๋ฐ์ ์ธ ๊ฐ์์ ๋๋ค:
- ํ ์คํธ ํ๋ ์์ํฌ ์ ํ: Jest, Mocha ๋๋ Jasmine๊ณผ ๊ฐ์ด TypeScript์ ์ ํตํฉ๋๋ ํ ์คํธ ํ๋ ์์ํฌ๋ฅผ ์ ํํ์ธ์. Jest๋ ์ฌ์ฉ ํธ์์ฑ๊ณผ TypeScript์ ๋ํ ๋ด์ฅ ์ง์์ผ๋ก ์ธํด ์ธ๊ธฐ ์๋ ์ ํ์ ๋๋ค. Ava์ ๊ฐ์ ๋ค๋ฅธ ์ต์ ๋ ํ์ ์ ํธ๋์ ํ๋ก์ ํธ์ ํน์ ์๊ตฌ ์ฌํญ์ ๋ฐ๋ผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์ข ์์ฑ ์ค์น: ํ์ํ ํ ์คํธ ํ๋ ์์ํฌ์ ํด๋น TypeScript ํ์ดํ (์: `@types/jest`)์ ์ค์นํ์ธ์. ๋ํ ์ธ๋ถ ์ข ์์ฑ์ ์๋ฎฌ๋ ์ด์ ํ๋ ๋ฐ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ (์: ๋ชจํน ํ๋ ์์ํฌ ๋๋ ์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค)๋ ํ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, `npm install --save-dev jest @types/jest ts-jest`๋ฅผ ์ฌ์ฉํ๋ฉด Jest์ ํด๋น ํ์ดํ, ๊ทธ๋ฆฌ๊ณ `ts-jest` ์ ์ฒ๋ฆฌ๊ธฐ๊น์ง ์ค์น๋ฉ๋๋ค.
- TypeScript ๊ตฌ์ฑ: `tsconfig.json` ํ์ผ์ด ํตํฉ ํ ์คํธ์ ๋ง๊ฒ ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ์ฑ๋์๋์ง ํ์ธํ์ธ์. ์ฌ๊ธฐ์๋ ํธํ๋๋ JavaScript ๋ฒ์ ์ ๋ํ `target` ์ค์ ๊ณผ ์๊ฒฉํ ํ์ ๊ฒ์ฌ ์ต์ (`strict: true`, `noImplicitAny: true` ๋ฑ) ํ์ฑํ๊ฐ ํฌํจ๋ฉ๋๋ค. ์ด๋ TypeScript์ ํ์ ์์ ์ฑ ์ด์ ์ ์์ ํ ํ์ฉํ๋ ๋ฐ ์ค์ํฉ๋๋ค. ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ํด `esModuleInterop: true` ๋ฐ `forceConsistentCasingInFileNames: true`๋ฅผ ํ์ฑํํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์.
- ๋ชจํน/์คํ ํ ์ค์ : ์ธ๋ถ API์ ๊ฐ์ ์ข ์์ฑ์ ์ ์ดํ๊ธฐ ์ํด ๋ชจํน/์คํ ํ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์ธ๊ธฐ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก๋ `jest.fn()`, `sinon.js`, `nock`, `mock-require` ๋ฑ์ด ์์ต๋๋ค.
์์ : TypeScript์ Jest ์ฌ์ฉ
TypeScript์ Jest๋ฅผ ํตํฉ ํ ์คํธ์ ์ค์ ํ๋ ๊ธฐ๋ณธ์ ์ธ ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
// tsconfig.json
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitAny": true,
"sourceMap": true,
"outDir": "./dist",
"baseUrl": ".",
"paths": {
"*": ["src/*"]
}
},
"include": ["src/**/*", "test/**/*"]
}
// jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['/test/**/*.test.ts'],
moduleNameMapper: {
'^src/(.*)$': '/src/$1',
},
};
ํจ๊ณผ์ ์ธ TypeScript ํตํฉ ํ ์คํธ ์์ฑ
TypeScript๋ฅผ ์ฌ์ฉํ์ฌ ํจ๊ณผ์ ์ธ ํตํฉ ํ ์คํธ๋ฅผ ์์ฑํ๋ ค๋ฉด ๋ช ๊ฐ์ง ์ฃผ์ ๊ณ ๋ ค ์ฌํญ์ด ์์ต๋๋ค:
- ์ํธ ์์ฉ์ ์ง์ค: ํตํฉ ํ ์คํธ๋ ์๋ก ๋ค๋ฅธ ๋ชจ๋ ๋๋ ์๋น์ค ๊ฐ์ ์ํธ ์์ฉ์ ๊ฒ์ฆํ๋ ๋ฐ ์ค์ ์ ๋์ด์ผ ํฉ๋๋ค. ๋ด๋ถ ๊ตฌํ ์ธ๋ถ ์ ๋ณด๋ฅผ ํ ์คํธํ์ง ๋ง๊ณ , ๊ฐ ๋ชจ๋์ ์ ๋ ฅ๊ณผ ์ถ๋ ฅ์ ์ง์คํ์ธ์.
- ํ์ค์ ์ธ ๋ฐ์ดํฐ ์ฌ์ฉ: ์ค์ ์๋๋ฆฌ์ค๋ฅผ ์๋ฎฌ๋ ์ด์ ํ๊ธฐ ์ํด ํตํฉ ํ ์คํธ์ ํ์ค์ ์ธ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ธ์. ์ด๋ ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ, ๋ณํ ๋๋ ์ฃ์ง ์ผ์ด์ค ์ฒ๋ฆฌ์ ๋ํ ์ ์ฌ์ ์ธ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ๋ ๋ฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค. ๊ตญ์ ํ ๋ฐ ํ์งํ๋ฅผ ๊ณ ๋ คํ์ฌ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ์ธ์. ์๋ฅผ ๋ค์ด, ๋ค๋ฅธ ๊ตญ๊ฐ์ ์ด๋ฆ๊ณผ ์ฃผ์๋ก ํ ์คํธํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋์ง ํ์ธํ์ธ์.
- ์ธ๋ถ ์ข ์์ฑ ๋ชจํน: ์ธ๋ถ ์ข ์์ฑ (์: ๋ฐ์ดํฐ๋ฒ ์ด์ค, API, ๋ฉ์์ง ํ)์ ๋ชจํนํ๊ฑฐ๋ ์คํ ํ์ฌ ํตํฉ ํ ์คํธ๋ฅผ ๊ฒฉ๋ฆฌํ๊ณ ์ทจ์ฝํ๊ฑฐ๋ ์ ๋ขฐํ ์ ์๊ฒ ๋๋ ๊ฒ์ ๋ฐฉ์งํ์ธ์. `nock`๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ HTTP ์์ฒญ์ ๊ฐ๋ก์ฑ๊ณ ์ ์ด๋ ์๋ต์ ์ ๊ณตํ์ธ์.
- ์ค๋ฅ ์ฒ๋ฆฌ ํ ์คํธ: ํ๋ณต ๊ฒฝ๋ก๋ง ํ ์คํธํ์ง ๋ง๊ณ , ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ค๋ฅ ๋ฐ ์์ธ๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋์ง๋ ํ ์คํธํ์ธ์. ์ฌ๊ธฐ์๋ ์ค๋ฅ ์ ํ, ๋ก๊น ๋ฐ ์ฌ์ฉ์ ํผ๋๋ฐฑ ํ ์คํธ๊ฐ ํฌํจ๋ฉ๋๋ค.
- ์ ์คํ ์ด์ค์ ์์ฑ: ์ด์ค์ ์ ๋ช ํํ๊ณ ๊ฐ๊ฒฐํ๋ฉฐ ํ ์คํธ ์ค์ธ ๊ธฐ๋ฅ๊ณผ ์ง์ ์ ์ผ๋ก ๊ด๋ จ๋์ด์ผ ํฉ๋๋ค. ์คํจ ์ง๋จ์ ์ฝ๊ฒ ํ ์ ์๋๋ก ์ค๋ช ์ ์ธ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ฌ์ฉํ์ธ์.
- ํ ์คํธ ์ฃผ๋ ๊ฐ๋ฐ (TDD) ๋๋ ํ์ ์ฃผ๋ ๊ฐ๋ฐ (BDD) ๋ฐ๋ฅด๊ธฐ: ํ์๋ ์๋์ง๋ง, ์ฝ๋๋ฅผ ๊ตฌํํ๊ธฐ ์ ์ ํตํฉ ํ ์คํธ๋ฅผ ์์ฑํ๊ฑฐ๋ (TDD) ์์๋๋ ๋์์ ์ฌ๋์ด ์ฝ์ ์ ์๋ ํ์์ผ๋ก ์ ์ํ๋ฉด (BDD) ์ฝ๋ ํ์ง๊ณผ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค.
์์ : TypeScript์ Jest๋ฅผ ์ฌ์ฉํ์ฌ REST API ํตํฉ ํ ์คํธ
๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ๋ REST API ์๋ํฌ์ธํธ๊ฐ ์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. TypeScript์ Jest๋ฅผ ์ฌ์ฉํ์ฌ ์ด ์๋ํฌ์ธํธ์ ๋ํ ํตํฉ ํ ์คํธ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
// src/api/user.ts
import { db } from '../db';
export interface User {
id: number;
name: string;
email: string;
country: string;
}
export async function getUser(id: number): Promise<User | null> {
const user = await db.query<User>('SELECT * FROM users WHERE id = ?', [id]);
if (user.length === 0) {
return null;
}
return user[0];
}
// test/api/user.test.ts
import { getUser, User } from 'src/api/user';
import { db } from 'src/db';
// ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ๋ชจํน (์ ํธํ๋ ๋ชจํน ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๊ต์ฒด)
jest.mock('src/db', () => ({
db: {
query: jest.fn().mockResolvedValue([
{
id: 1,
name: 'John Doe',
email: 'john.doe@example.com',
country: 'USA',
},
]),
},
}));
describe('getUser', () => {
it('should return a user object if the user exists', async () => {
const user = await getUser(1);
expect(user).toEqual({
id: 1,
name: 'John Doe',
email: 'john.doe@example.com',
country: 'USA',
});
expect(db.query).toHaveBeenCalledWith('SELECT * FROM users WHERE id = ?', [1]);
});
it('should return null if the user does not exist', async () => {
(db.query as jest.Mock).mockResolvedValueOnce([]); // ์ด ํ
์คํธ ์ผ์ด์ค์ ๋ํ ๋ชจํน ์ฌ์ค์
const user = await getUser(2);
expect(user).toBeNull();
});
});
์ค๋ช :
- ์ด ์ฝ๋๋ ์ฌ์ฉ์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ ์ํ๋ `User` ์ธํฐํ์ด์ค๋ฅผ ์ ์ํฉ๋๋ค. ์ด๋ ํตํฉ ํ ์คํธ ์ ์ฒด์์ ์ฌ์ฉ์ ๊ฐ์ฒด๋ฅผ ๋ค๋ฃฐ ๋ ํ์ ์์ ์ฑ์ ๋ณด์ฅํฉ๋๋ค.
- `db` ๊ฐ์ฒด๋ `jest.mock`์ ์ฌ์ฉํ์ฌ ๋ชจํน๋์ด ํ ์คํธ ์ค์ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ก์ธ์คํ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํ ์คํธ๊ฐ ๋ ๋น ๋ฅด๊ณ ์์ ์ ์ด๋ฉฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ ๋ ๋ฆฝ์ ์ผ๋ก ๋ฉ๋๋ค.
- ํ ์คํธ๋ `expect` ์ด์ค์ ์ ์ฌ์ฉํ์ฌ ๋ฐํ๋ ์ฌ์ฉ์ ๊ฐ์ฒด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ ๋งค๊ฐ๋ณ์๋ฅผ ๊ฒ์ฆํฉ๋๋ค.
- ํ ์คํธ๋ ์ฑ๊ณต ์ฌ๋ก (์ฌ์ฉ์ ์กด์ฌ)์ ์คํจ ์ฌ๋ก (์ฌ์ฉ์ ๋ถ์ฌ)๋ฅผ ๋ชจ๋ ๋ค๋ฃน๋๋ค.
TypeScript ํตํฉ ํ ์คํธ๋ฅผ ์ํ ๊ณ ๊ธ ๊ธฐ๋ฒ
๊ธฐ๋ณธ ์ธ์๋ ๋ช ๊ฐ์ง ๊ณ ๊ธ ๊ธฐ๋ฒ์ ์ฌ์ฉํ์ฌ TypeScript ํตํฉ ํ ์คํธ ์ ๋ต์ ๋์ฑ ํฅ์์ํฌ ์ ์์ต๋๋ค:
- ๊ณ์ฝ ํ ์คํธ: ๊ณ์ฝ ํ ์คํธ๋ ์๋ก ๋ค๋ฅธ ์๋น์ค ๊ฐ์ API ๊ณ์ฝ์ด ์ค์๋๋์ง ํ์ธํฉ๋๋ค. ์ด๋ ํธํ๋์ง ์๋ API ๋ณ๊ฒฝ์ผ๋ก ์ธํ ํตํฉ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. Pact์ ๊ฐ์ ๋๊ตฌ๋ฅผ ๊ณ์ฝ ํ ์คํธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. UI๊ฐ ๋ฐฑ์๋ ์๋น์ค์์ ๋ฐ์ดํฐ๋ฅผ ์๋นํ๋ ๋ง์ดํฌ๋ก์๋น์ค ์ํคํ ์ฒ๋ฅผ ์์ํด ๋ณด์ธ์. ๊ณ์ฝ ํ ์คํธ๋ *์์๋๋* ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ํ์์ ์ ์ํฉ๋๋ค. ๋ฐฑ์๋๊ฐ ์์์น ๋ชปํ๊ฒ ์ถ๋ ฅ ํ์์ ๋ณ๊ฒฝํ๋ฉด ๊ณ์ฝ ํ ์คํธ๊ฐ ์คํจํ์ฌ ๋ฐฐํฌ ์ ์ UI๋ฅผ ์ค๋จ์ํค๋ ๋ณ๊ฒฝ ์ฌํญ์ ํ์ ์๋ฆฝ๋๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ
์คํธ ์ ๋ต:
- ์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค: SQLite (`:memory:` ์ฐ๊ฒฐ ๋ฌธ์์ด ์ฌ์ฉ) ๋๋ H2์ ๊ฐ์ ์๋ฒ ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐ์ ์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ํ ์คํธ ์๋๋ฅผ ๋์ด๊ณ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ค์ผ์ํค์ง ์๋๋ก ํฉ๋๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ง์ด๊ทธ๋ ์ด์ : Knex.js ๋๋ TypeORM ๋ง์ด๊ทธ๋ ์ด์ ๊ณผ ๊ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ง์ด๊ทธ๋ ์ด์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง๊ฐ ํญ์ ์ต์ ์ํ์ด๋ฉฐ ์ ํ๋ฆฌ์ผ์ด์ ์ฝ๋์ ์ผ๊ด๋๋๋ก ํฉ๋๋ค. ์ด๋ ์ค๋๋๊ฑฐ๋ ์๋ชป๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง๋ก ์ธํ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
- ํ ์คํธ ๋ฐ์ดํฐ ๊ด๋ฆฌ: ํ ์คํธ ๋ฐ์ดํฐ ๊ด๋ฆฌ ์ ๋ต์ ๊ตฌํํฉ๋๋ค. ์ฌ๊ธฐ์๋ ์๋ ๋ฐ์ดํฐ ์ฌ์ฉ, ์์ ๋ฐ์ดํฐ ์์ฑ ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๋ ์ท ๊ธฐ์ ์ฌ์ฉ์ด ํฌํจ๋ ์ ์์ต๋๋ค. ํ ์คํธ ๋ฐ์ดํฐ๊ฐ ํ์ค์ ์ด๊ณ ๊ด๋ฒ์ํ ์๋๋ฆฌ์ค๋ฅผ ํฌํจํ๋์ง ํ์ธํ์ธ์. ๋ฐ์ดํฐ ์์ฑ ๋ฐ ์๋ฉ์ ์ง์ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ (์: Faker.js) ์ฌ์ฉ์ ๊ณ ๋ คํ ์ ์์ต๋๋ค.
- ๋ณต์กํ ์๋๋ฆฌ์ค ๋ชจํน: ๋งค์ฐ ๋ณต์กํ ํตํฉ ์๋๋ฆฌ์ค์ ๊ฒฝ์ฐ, ์ข ์์ฑ ์ฃผ์ ๋ฐ ํฉํ ๋ฆฌ ํจํด๊ณผ ๊ฐ์ ๊ณ ๊ธ ๋ชจํน ๊ธฐ๋ฒ์ ์ฌ์ฉํ์ฌ ๋ ์ ์ฐํ๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ๋ชจํน์ ๋ง๋๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์.
- CI/CD์์ ํตํฉ: TypeScript ํตํฉ ํ ์คํธ๋ฅผ CI/CD ํ์ดํ๋ผ์ธ์ ํตํฉํ์ฌ ๋ชจ๋ ์ฝ๋ ๋ณ๊ฒฝ ์ ์๋์ผ๋ก ์คํ๋๋๋ก ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํตํฉ ๋ฌธ์ ๊ฐ ์กฐ๊ธฐ์ ๊ฐ์ง๋๊ณ ํ๋ก๋์ ์ ๋๋ฌํ๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค. Jenkins, GitLab CI, GitHub Actions, CircleCI, Travis CI์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ด ๋ชฉ์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์์ฑ ๊ธฐ๋ฐ ํ ์คํธ (ํผ์ฆ ํ ์คํธ๋ผ๊ณ ๋ ํจ): ์์คํ ์ ๋ํด ์ฐธ์ด์ด์ผ ํ๋ ์์ฑ์ ์ ์ํ ๋ค์ ํด๋น ์์ฑ์ ๊ฒ์ฆํ๊ธฐ ์ํด ์๋ง์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์๋์ผ๋ก ์์ฑํ๋ ์์ ์ด ํฌํจ๋ฉ๋๋ค. fast-check์ ๊ฐ์ ๋๊ตฌ๋ฅผ TypeScript์ ์์ฑ ๊ธฐ๋ฐ ํ ์คํธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ํจ์๊ฐ ํญ์ ์์๋ฅผ ๋ฐํํด์ผ ํ๋ ๊ฒฝ์ฐ, ์์ฑ ๊ธฐ๋ฐ ํ ์คํธ๋ ์๋ฐฑ ๋๋ ์์ฒ ๊ฐ์ ์์ ์ ๋ ฅ๋ฅผ ์์ฑํ๊ณ ์ถ๋ ฅ์ด ์ค์ ๋ก ํญ์ ์์์ธ์ง ๊ฒ์ฆํฉ๋๋ค.
- ๊ฐ์์ฑ ๋ฐ ๋ชจ๋ํฐ๋ง: ํ ์คํธ ์คํ ์ค ์์คํ ๋์์ ๋ํ ๋ ๋์ ๊ฐ์์ฑ์ ํ๋ณดํ๊ธฐ ์ํด ํตํฉ ํ ์คํธ์ ๋ก๊น ๋ฐ ๋ชจ๋ํฐ๋ง์ ํตํฉํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ฌธ์ ๋ฅผ ๋ ๋น ๋ฅด๊ฒ ์ง๋จํ๊ณ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์๋ณํ ์ ์์ต๋๋ค. Winston ๋๋ Pino์ ๊ฐ์ ๊ตฌ์กฐํ๋ ๋ก๊น ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ์ ๊ณ ๋ คํ์ธ์.
TypeScript ํตํฉ ํ ์คํธ๋ฅผ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
TypeScript ํตํฉ ํ ์คํธ์ ์ด์ ์ ๊ทน๋ํํ๋ ค๋ฉด ๋ค์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด์ธ์:
- ํ ์คํธ๋ฅผ ์ง์ค์ ์ด๊ณ ๊ฐ๊ฒฐํ๊ฒ ์ ์ง: ๊ฐ ํตํฉ ํ ์คํธ๋ ๋จ์ผ์ ์ ์ ์๋ ์๋๋ฆฌ์ค์ ์ง์คํด์ผ ํฉ๋๋ค. ์ดํดํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ด๋ ค์ด ์ง๋์น๊ฒ ๋ณต์กํ ํ ์คํธ๋ฅผ ์์ฑํ์ง ๋ง์ธ์.
- ์ฝ๊ธฐ ์ฝ๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ํ ์คํธ ์์ฑ: ๋ช ํํ๊ณ ์ค๋ช ์ ์ธ ํ ์คํธ ์ด๋ฆ, ์ฃผ์ ๋ฐ ์ด์ค์ ์ ์ฌ์ฉํ์ธ์. ์ผ๊ด๋ ์ฝ๋ฉ ์คํ์ผ ์ง์นจ์ ๋ฐ๋ผ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ํฅ์์ํค์ธ์.
- ๊ตฌํ ์ธ๋ถ ์ ๋ณด ํ ์คํธ ๋ฐฉ์ง: ๋ชจ๋์ ๋ด๋ถ ๊ตฌํ ์ธ๋ถ ์ ๋ณด ๋์ ๊ณต๊ฐ API ๋๋ ์ธํฐํ์ด์ค๋ฅผ ํ ์คํธํ๋ ๋ฐ ์ง์คํ์ธ์. ์ด๋ ๊ฒ ํ๋ฉด ํ ์คํธ๊ฐ ์ฝ๋ ๋ณ๊ฒฝ์ ๋ ํ๋ ฅ์ ์ผ๋ก ๋์ํ ์ ์์ต๋๋ค.
- ๋์ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง ๋ฌ์ฑ: ๋ชจ๋ ์ค์ํ ๋ชจ๋ ๊ฐ์ ์ํธ ์์ฉ์ด ์ฒ ์ ํ ํ ์คํธ๋๋๋ก ๋์ ํตํฉ ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ๋ชฉํ๋ก ํ์ธ์. ์ฝ๋ ์ปค๋ฒ๋ฆฌ์ง ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ํ ์คํธ ์ค์ํธ์ ๊ฒฉ์ฐจ๋ฅผ ์๋ณํ์ธ์.
- ์ ๊ธฐ์ ์ผ๋ก ํ ์คํธ ๊ฒํ ๋ฐ ๋ฆฌํฉํ ๋ง: ํ๋ก๋์ ์ฝ๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ํตํฉ ํ ์คํธ๋ ์ ๊ธฐ์ ์ผ๋ก ๊ฒํ ๋ฐ ๋ฆฌํฉํ ๋งํ์ฌ ์ต์ ์ํ๋ก ์ ์ง๋ณด์ ๊ฐ๋ฅํ๊ณ ํจ๊ณผ์ ์ผ๋ก ์ ์งํด์ผ ํฉ๋๋ค. ์ค๋ณต๋๊ฑฐ๋ ์ค๋๋ ํ ์คํธ๋ฅผ ์ ๊ฑฐํ์ธ์.
- ํ ์คํธ ํ๊ฒฝ ๊ฒฉ๋ฆฌ: Docker ๋๋ ๊ธฐํ ์ปจํ ์ด๋ํ ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ ๋จธ์ ๋ฐ CI/CD ํ์ดํ๋ผ์ธ์์ ์ผ๊ด๋ ๊ฒฉ๋ฆฌ๋ ํ ์คํธ ํ๊ฒฝ์ ๋ง๋์ธ์. ์ด๋ ๊ฒ ํ๋ฉด ํ๊ฒฝ ๊ด๋ จ ๋ฌธ์ ๋ฅผ ์ ๊ฑฐํ๊ณ ํ ์คํธ์ ์ ๋ขฐ์ฑ์ ๋ณด์ฅํฉ๋๋ค.
TypeScript ํตํฉ ํ ์คํธ์ ๊ณผ์
TypeScript ํตํฉ ํ ์คํธ๋ ์ด์ ์ ์ ๊ณตํ์ง๋ง ๋ช ๊ฐ์ง ๊ณผ์ ๋ฅผ ์ ์ํ ์ ์์ต๋๋ค:
- ํ๊ฒฝ ์ค์ : ์ฌ๋ฌ ์ข ์์ฑ ๋ฐ ์๋น์ค๋ฅผ ์ฒ๋ฆฌํ ๋ ํ์ค์ ์ธ ํตํฉ ํ ์คํธ ํ๊ฒฝ์ ์ค์ ํ๋ ๊ฒ์ด ๋ณต์กํ ์ ์์ต๋๋ค. ์ ์คํ ๊ณํ๊ณผ ๊ตฌ์ฑ์ด ํ์ํฉ๋๋ค.
- ์ธ๋ถ ์ข ์์ฑ ๋ชจํน: ๋ณต์กํ API ๋๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ฒ๋ฆฌํ ๋ ์ ํํ๊ณ ์์ ์ ์ธ ์ธ๋ถ ์ข ์์ฑ ๋ชจํน์ ๋ง๋๋ ๊ฒ์ ์ด๋ ค์ธ ์ ์์ต๋๋ค. API ์ฌ์์์ ๋ชจํน์ ์์ฑํ๊ธฐ ์ํด ์ฝ๋ ์์ฑ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์.
- ํ ์คํธ ๋ฐ์ดํฐ ๊ด๋ฆฌ: ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ธํธ ๋๋ ๋ณต์กํ ๋ฐ์ดํฐ ๊ด๊ณ๋ฅผ ์ฒ๋ฆฌํ ๋ ํ ์คํธ ๋ฐ์ดํฐ ๊ด๋ฆฌ๊ฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฉ ๋๋ ์ค๋ ์ท ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ์ธ์.
- ๋๋ฆฐ ํ ์คํธ ์คํ: ์ธ๋ถ ์ข ์์ฑ์ด ํฌํจ๋๋ ๊ฒฝ์ฐ ํตํฉ ํ ์คํธ๋ ์ ๋ ํ ์คํธ๋ณด๋ค ๋๋ฆด ์ ์์ต๋๋ค. ํ ์คํธ๋ฅผ ์ต์ ํํ๊ณ ๋ณ๋ ฌ ์คํ์ ์ฌ์ฉํ์ฌ ํ ์คํธ ์คํ ์๊ฐ์ ์ค์ด์ธ์.
- ๊ฐ๋ฐ ์๊ฐ ์ฆ๊ฐ: ํตํฉ ํ ์คํธ๋ฅผ ์์ฑํ๊ณ ์ ์ง๋ณด์ํ๋ ๊ฒ์ ํนํ ์ด๊ธฐ์๋ ๊ฐ๋ฐ ์๊ฐ์ ์ถ๊ฐ๋ ์ ์์ต๋๋ค. ์ฅ๊ธฐ์ ์ธ ์ด์ ์ ๋จ๊ธฐ ๋น์ฉ์ ์ด๊ณผํฉ๋๋ค.
๊ฒฐ๋ก
TypeScript ํตํฉ ํ ์คํธ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ขฐ์ฑ, ๊ฒฌ๊ณ ์ฑ ๋ฐ ํ์ ์์ ์ฑ์ ๋ณด์ฅํ๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฒ์ ๋๋ค. TypeScript์ ์ ์ ํ์ดํ์ ํ์ฉํ๋ฉด ์ค๋ฅ๋ฅผ ์กฐ๊ธฐ์ ๊ฐ์งํ๊ณ , ์ฝ๋ ์ ์ง๋ณด์์ฑ์ ๊ฐ์ ํ๋ฉฐ, ๊ฐ๋ฐ์ ๊ฐ์ ํ์ ์ ๊ฐํํ ์ ์์ต๋๋ค. ๋ช ๊ฐ์ง ๊ณผ์ ๊ฐ ์์ง๋ง, ์๋ํฌ์๋ ํ์ ์์ ์ฑ๊ณผ ์ฝ๋์ ๋ํ ์์ ๊ฐ ํฅ์์ ์ด์ ์ ํฌ์ํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ํตํฉ ํ ์คํธ๋ฅผ ๊ฐ๋ฐ ์ํฌํ๋ก์ ์ค์ํ ๋ถ๋ถ์ผ๋ก ๋ฐ์๋ค์ด๊ณ ๋ ์ ๋ขฐํ ์ ์๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ ์ฝ๋๋ฒ ์ด์ค์ ์ด์ ์ ๋๋ฆฌ์ญ์์ค.
์ ๊ณต๋ ์์ ๋ฅผ ์คํํ๋ฉด์ ์์ํ๊ณ ํ๋ก์ ํธ๊ฐ ๋ฐ์ ํจ์ ๋ฐ๋ผ ์ ์ง์ ์ผ๋ก ๋ ๊ณ ๊ธ ๊ธฐ๋ฒ์ ํตํฉํ์ธ์. ์์คํ ์ ๋ค์ํ ๋ชจ๋ ๊ฐ์ ์ํธ ์์ฉ์ ์ ํํ๊ฒ ๋ฐ์ํ๋ ๋ช ํํ๊ณ ๊ฐ๊ฒฐํ๋ฉฐ ์ ์ ์ง๋ณด์๋๋ ํ ์คํธ์ ์ง์คํ๋ ๊ฒ์ ์์ง ๋ง์ธ์. ์ด๋ฌํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด ์ฌ์ฉ์์ ์๊ตฌ๋ฅผ ์ถฉ์กฑํ๋ ๊ฐ๋ ฅํ๊ณ ์ ๋ขฐํ ์ ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์์ผ๋ฉฐ, ์ฌ์ฉ์๋ ์ด๋์ ์๋ ์๊ด์์ต๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ฑ์ฅํ๊ณ ๋ฐ์ ํจ์ ๋ฐ๋ผ ํ์ง๊ณผ ์ ๋ขฐ๋์ ๋์ ์์ค์ ์ ์งํ๊ธฐ ์ํด ํ ์คํธ ์ ๋ต์ ์ง์์ ์ผ๋ก ๊ฐ์ ํ๊ณ ๊ฐ์ ํ์ธ์.