๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Dev

(8)
NestJS์—์„œ createMock์œผ๋กœ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ• ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์„๊นŒ...? ๐Ÿค”   ๋‹จ์œ„ ํ…Œ์ŠคํŠธ(Unit Test)๋ฅผ ์ž‘์„ฑํ•˜๋‹ค๋ณด๋ฉด ๊ฐ€์žฅ ๋‹ต๋‹ตํ•œ ๋ถ€๋ถ„์€ ์—ญ์‹œ ์˜์กด์„ฑ๋“ค์„ ๋ชจ์˜(mocking)ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.๋ฐฑ์—”๋“œ์—์„œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋ฉด ์ข‹์„๋งŒํ•œ ๊ฒƒ์€ ์—ญ์‹œ ์„œ๋น„์Šค ๋ ˆ์ด์–ด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.์ €๋Š” NestJS์—์„œ ์™ธ๋ถ€ API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์•Œ๋ฆผ์„ ์ „์†กํ•˜๋Š” ์„œ๋น„์Šค(NotificationService)๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.์ด ์„œ๋น„์Šค์˜ ํ•จ์ˆ˜๋“ค์„ ํ…Œ์ŠคํŠธํ•˜๋ ค๋ฉด ์™ธ๋ถ€ API๋ฅผ ์‹ค์ œ๋กœ ์—ฐ๊ฒฐํ•˜์ง€ ์•Š๊ณ , ๋งˆ์น˜ ์—ฐ๊ฒฐํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ชจํ‚นํ•˜๋Š” ๊ณผ์ •์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง & ํ…Œ์ŠคํŠธ ์ฝ”๋“œ 1. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง NotificationService๋Š” ConfigService, HttpService, LoggerService ์„ธ ๊ฐœ์˜ ์˜์กด์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋””์Šค์ฝ”๋“œ ..
[TypeORM] bigint๊ฐ€ string์œผ๋กœ ๋ณ€ํ™˜๋  ๋•Œ ๋ฌธ์ œ ์ƒํ™ฉ  TypeORM ๊ณต์‹ ๋ฌธ์„œ์—์„œ๋„ ๋‚˜์™€์žˆ๋“ฏ์ด, ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋งŒ๋“ค ๋•Œ bigint๋กœ ์ปฌ๋Ÿผ ํƒ€์ž…์„ ์ง€์ •ํ•˜๋ฉด ์—”ํ‹ฐํ‹ฐ๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ๋Š” string์œผ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. (PostgreSQL ๊ธฐ์ค€)ํ•˜์ง€๋งŒ ์ด ๊ฐ’์„ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ๋ณ€ํ™˜ํ•˜๋Š” ๋กœ์ง์„ ๋„ฃ๊ธฐ๋Š” ๊ท€์ฐฎ์œผ๋‹ˆ, ์—”ํ‹ฐํ‹ฐ๋กœ ๋ณ€ํ™˜ํ•œ ์‹œ์ ์— ์ด๋ฏธ number ๋ผ๋ฉด ์‚ฌ์šฉํ•˜๊ธฐ ํŽธํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.Javascript์—์„œ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” "์•ˆ์ „ํ•œ" ์ •์ˆ˜์˜ ๋ฒ”์œ„๋Š” -9,007,199,254,740,991 ~ 9,007,199,254,740,991 ์ž…๋‹ˆ๋‹ค.ํ•˜์ง€๋งŒ PostgreSQL bigint์˜ ๋ฒ”์œ„๋Š” -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807๋กœ ๋” ํฌ๊ธฐ ๋•Œ๋ฌธ์— string์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.totalAmount ๊ฐ’..
[TypeORM] ์™œ ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค ํ”„๋กœํผํ‹ฐ๋ฅผ private์œผ๋กœ ํ•  ์ˆ˜ ์—†์„๊นŒ? ๋ฌธ์ œ ์ƒํ™ฉ TypeORM ์‚ฌ์šฉ ์ค‘ Entity ํด๋ž˜์Šค์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ private์œผ๋กœ ๋ณ€๊ฒฝํ–ˆ๋”๋‹ˆ ์ด๋Ÿฐ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. "Property "id" was not found in "Expense". Make sure your query is correct."์ฒ˜์Œ์—๋Š” ํ”„๋กœํผํ‹ฐ ์ด๋ฆ„ ์•ž์— ์–ธ๋”์Šค์ฝ”์–ด๋ฅผ ๋ถ™์—ฌ์„œ ๋งคํ•‘์ด ์•ˆ ๋˜๋Š” ๊ฑด๊ฐ€ ํ–ˆ๋Š”๋ฐ, ํ”„๋กœํผํ‹ฐ๋ฅผ public์œผ๋กœ ํ•ด์•ผ๋งŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๊ฐ์ฒด๊ฐ€ ์ž๋™์œผ๋กœ ๋งคํ•‘๋˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค.JPA๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์—”ํ‹ฐํ‹ฐ์˜ ๋ชจ๋“  ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋ฅผ private์œผ๋กœ ์„ ์–ธํ•˜๊ณ  getter & setter๋ฅผ ๋‘์–ด ์บก์Аํ™”๋ฅผ ํ•˜์—ฌ, ์—”ํ‹ฐํ‹ฐ์— ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ด์€ public ๋ฉ”์„œ๋“œ๋ฅผ ๋‘์–ด ์„œ๋น„์Šค์—์„œ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด ๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„์˜ ์ •์„(?)์ด๋ผ๊ณ  ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค... TypeORM์—์„œ๋„ ์ด์™€ ..
๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์ „๋žต ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ๋ž€?๋ฌด์ค‘๋‹จ ๋ฐฐํฌ(Zero-Downtime Deployment)๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•  ๋•Œ ์„œ๋น„์Šค ์ค‘๋‹จ ์—†์ด ์ƒˆ๋กœ์šด ๋ฒ„์ „์„ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” ์ง€์†์ ์ธ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๋ฉด์„œ, ์ƒˆ๋กœ์šด ๋ฒ„์ „์˜ ์•ˆ์ •์„ฑ์„ ์ ์ง„์ ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์ฃผ์š” ์ „๋žต 3๊ฐ€์ง€1. ๋ธ”๋ฃจ-๊ทธ๋ฆฐ ๋ฐฐํฌ (Blue-Green Deployment)๊ณผ์ •๋‘ ๊ฐœ์˜ ๋™๋“ฑํ•œ ํ™˜๊ฒฝ(๋ธ”๋ฃจ/๊ทธ๋ฆฐ)์„ ํ™˜๊ฒฝ์„ ์ด์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ธ”๋ฃจ๋Š” ํ˜„์žฌ ์šด์˜ ์ค‘์ธ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์ด๊ณ , ๊ทธ๋ฆฐ์€ ์ƒˆ๋กœ์šด ๋ฒ„์ „์„ ๋ฐฐํฌํ•  ํ™˜๊ฒฝ์ž…๋‹ˆ๋‹ค. ๋ธ”๋ฃจ ํ™˜๊ฒฝ์ด ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ์ƒํ™ฉ์—์„œ, ๊ทธ๋ฆฐ ํ™˜๊ฒฝ์— ์ƒˆ๋กœ์šด ๋ฒ„์ „์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค.๋ฐฐํฌ๊ฐ€ ์™„๋ฃŒ๋˜๊ณ  ๋‚˜๋ฉด, ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ๋‚˜ ์›น์„œ๋ฒ„๋ฅผ ํ†ตํ•ด ํŠธ๋ž˜ํ”ฝ์„ ๋ธ”๋ฃจ ํ™˜๊ฒฝ์—์„œ ๊ทธ๋ฆฐ ํ™˜๊ฒฝ์œผ๋กœ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค.์ดํ›„ ๋ธ”๋ฃจ ํ™˜๊ฒฝ์€ ํ•„์š”์— ๋”ฐ๋ผ ..
[TypeORM] TypeORM์—์„œ ํŠธ๋žœ์žญ์…˜ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ• TypeORM 0.3 ์ด์ƒ ๋ฒ„์ „์„ ๊ธฐ์ค€์œผ๋กœ ํŠธ๋žœ์žญ์…˜์„ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. TransactionํŠธ๋žœ์žญ์…˜์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ํ•œ๊บผ๋ฒˆ์— ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์ž‘์—… ๋‹จ์œ„๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค.ํŠธ๋žœ์žญ์…˜์˜ ์ค‘์š”ํ•œ ํŠน์ง• ์ค‘ ํ•˜๋‚˜๋Š” ํŠธ๋žœ์žญ์…˜์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ชจ๋‘ ๋ฐ˜์˜๋˜๋“ ์ง€, ์•„๋‹ˆ๋ฉด ์ „ํ˜€ ๋ฐ˜์˜๋˜์ง€ ์•Š์•„์•ผ ํ•˜๋ฉฐ ์ž‘์—…์ด ๋ถ€๋ถ„์ ์œผ๋กœ ์‹คํ–‰๋˜๊ฑฐ๋‚˜ ์ค‘๋‹จ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. (ACID ์ค‘ Atomicity, ์›์ž์„ฑ) DataSource & EntityManager / QueryRunnerTypeORM์—์„œ๋Š” DataSource & EntityManager ๋˜๋Š” QueryRunner๋ฅผ ํ†ตํ•ด ํŠธ๋žœ์žญ์…˜์„ ์ƒ์„ฑํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๊ธฐ์— ์•ž์„œ, TypeORM์—์„œ์˜ DataSource, EntityManager, ..
REST ์›์น™๊ณผ REST API ์„ค๊ณ„ ๋ฐฉ๋ฒ• "๊ทธ๋Ÿฐ REST API๋กœ ๊ดœ์ฐฎ์€๊ฐ€"๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.   REST๋ž€?REpresentational State Transfer์˜ ์•ฝ์ž์ž…๋‹ˆ๋‹ค.์›น ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์˜ ์Šคํƒ€์ผ ์ค‘ ํ•˜๋‚˜๋กœ, ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.์ธํ„ฐ๋„ท์—์„œ ์–ด๋–ป๊ฒŒ ์ •๋ณด๋ฅผ ๊ณต์œ ํ•  ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•œ ํ•ด๋‹ต์œผ๋กœ 1991๋…„ ์›น(Web)์ด ๋“ฑ์žฅํ–ˆ์Šต๋‹ˆ๋‹ค. ์›น์€ HTML์ด๋ผ๋Š” ํ˜•์‹์œผ๋กœ ์ •๋ณด๋ฅผ ํ‘œํ˜„ํ•˜๊ณ , ์ •๋ณด๋“ค์— ๋Œ€ํ•œ ์‹๋ณ„์ž๋กœ URI๋ฅผ ์„ ํƒํ•˜๊ณ , HTTP๋ผ๋Š” ํ”„๋กœํ† ์ฝœ๋กœ ์ •๋ณด๋ฅผ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.2000๋…„ Roy T. Fielding์€ ๊ธฐ์กด์˜ ์›น์„ ๋ง๊ฐ€ํŠธ๋ฆฌ์ง€ ์•Š๊ณ  HTTP๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์„์ง€์— ๋Œ€ํ•œ ๋…ผ๋ฌธ์„ ๋ฐœํ‘œํ–ˆ๊ณ , ์ด๊ฒƒ์ด REST ์˜€์Šต๋‹ˆ๋‹ค.REST API๋ž€?REST API๋Š” REST ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋”ฐ๋ฅด๋Š” API๋กœ,..
์—๋Ÿฌ์ฝ”๋“œ ์„ค๊ณ„ ๋ฒค์น˜๋งˆํ‚น & NestJS์—์„œ ์—๋Ÿฌ ์‘๋‹ต ์ปค์Šคํ…€ ๋ฐฉ๋ฒ• ๋ฌธ์ œ์ƒํ™ฉ Nest.js์—์„œ ๊ธฐ๋ณธ ์—๋Ÿฌ ์‘๋‹ต ํ˜•์‹์€ ์œ„์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์‘๋‹ต์„ ์ฃผ๋ฉด ํ˜‘์—…์— ์–ด๋ ค์›€์ด ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.์ผ๋‹จ ์—๋Ÿฌ๊ฐ€ ์–ด๋А API์—์„œ ๋ฐœ์ƒํ–ˆ๋Š”์ง€, ์–ธ์ œ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ์•Œ๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.ํ•˜๋‚˜์˜ ์ƒํƒœ ์ฝ”๋“œ์— ๋Œ€ํ•ด์„œ๋„ ์„ธ๋ถ€์ ์œผ๋กœ ๋ถ„๋ฅ˜ํ•˜๊ธฐ ์œ„ํ•œ ์—๋Ÿฌ ์ฝ”๋“œ๋„ ํ•„์š”ํ•ด๋ณด์ž…๋‹ˆ๋‹ค. ๋ฒค์น˜๋งˆํ‚น๋‹ค๋ฅธ ๊ธฐ์—…๋“ค์—์„œ๋Š” ์–ด๋–ค ์—๋Ÿฌ ์ฝ”๋“œ ์ฒด๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ  ์šด์˜ ์ค‘์ธ์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. 1. NAVER WORKS Developers๋งํฌ : https://developers.worksmobile.com/kr/docs/error-codesHTTP ์ƒํƒœ ์ฝ”๋“œ์™€ ๋ณ„๋„์˜ ์—๋Ÿฌ ์ฝ”๋“œ ์ฒด๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ , ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ์‘๋‹ต ๋ณธ๋ฌธ์— ํฌํ•จ์‹œ์ผœ์ฃผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.๋™์ผํ•œ ์ƒํƒœ ์ฝ”๋“œ์— ๋Œ€ํ•ด์„œ ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ์—๋Ÿฌ ์ฝ”๋“œ๋ฅผ ์ง€์ •ํ•ด๋†“์•˜๋‹ค๋Š” ์ ์—์„œ ์–ด๋–ค ์—๋Ÿฌ์ธ์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์‰ฌ์›Œ..
[Jest] Jest ํ•จ์ˆ˜ ์‹คํ–‰ ์ˆœ์„œ Jest Globalsํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ ์ค‘ ํ•˜๋‚˜์ธ Jest์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ „์—ญ ๊ฐ์ฒด์™€ ํ•จ์ˆ˜๋“ค์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.  beforeAllํŒŒ์ผ ์•ˆ์˜ ๊ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ, promise๊ฐ€ ์ดํ–‰(fulfilled)๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.์—ฌ๋Ÿฌ ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ „์—ญ ์ƒํƒœ๋ฅผ ์„ค์ •(set up)ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.beforeEachํŒŒ์ผ ์•ˆ์˜ ๊ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ, promise๊ฐ€ ์ดํ–‰(fulfilled)๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.๊ฐ ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ „์—ญ ์ƒํƒœ๋ฅผ ์žฌ์„ค์ •(reset)ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.afterAllํŒŒ์ผ ์•ˆ์˜ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ์™„๋ฃŒ๋œ ํ›„ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ promi..