Skip to content

DongSeonYoo/ExchangeWatch

Repository files navigation

Exchange Watch Backend

์‹ค์‹œ๊ฐ„ ํ™˜์œจ ์ถ”์  ๋ฐ AI ๊ธฐ๋ฐ˜ ๋ถ„์„ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฐฑ์—”๋“œ ๋ ˆํฌ.

Exchange Watch๋Š” ์ „ ์„ธ๊ณ„ ํ™˜์œจ ์ •๋ณด๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ˆ˜์ง‘ํ•˜๊ณ , ์‚ฌ์šฉ์ž์˜ ๊ด€์‹ฌ ํ†ตํ™”์Œ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋ฉฐ, ์ผ๊ฐ„ ์ด๋ ฅ ์ง‘๊ณ„ ๋ฐ ์•Œ๋ฆผ๊นŒ์ง€ ์ œ๊ณตํ•˜๋Š” ํ’€์Šคํƒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž…๋‹ˆ๋‹ค (์ด ์ €์žฅ์†Œ๋Š” ๋ฐฑ์—”๋“œ๋งŒ).

๐Ÿ’ก ์ฃผ์š” ๊ธฐ๋Šฅ (Features)

  • ์ „ ์„ธ๊ณ„ ์ฃผ์š” ํ†ตํ™”์˜ ์‹ค์‹œ๊ฐ„ ํ™˜์œจ ์ˆ˜์ง‘ ๋ฐ ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ ์ œ๊ณต (WebSocket + SSE)
  • ๊ด€์‹ฌ ํ†ตํ™”์Œ ๋“ฑ๋ก ๋ฐ ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง
  • ์™ธ๋ถ€ API ํ˜ธ์ถœ์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•œ Redis ๊ธฐ๋ฐ˜ ์บ์‹ฑ ๋ฐ ์—ญ์‚ฐ ์ตœ์ ํ™”
  • ์ผ๊ฐ„ ํ™˜์œจ ๋ฐ์ดํ„ฐ๋ฅผ OHLC ํ˜•ํƒœ๋กœ ์ž๋™ ์ง‘๊ณ„ํ•˜์—ฌ ์ด๋ ฅ ์ €์žฅ
  • ๋ชฉํ‘œ ๊ฐ€๊ฒฉ ๋„๋‹ฌ ์‹œ ์•Œ๋ฆผ ์ „์†ก ๊ธฐ๋Šฅ (FCM ์—ฐ๋™ ์ง„ํ–‰์ค‘)
  • ํ™˜์œจ ์ด๋ ฅ ๋ฐ์ดํ„ฐ ์กฐํšŒ ๋ฐ ์ฐจํŠธ ์‹œ๊ฐํ™” ์ง€์›
  • ๋‹จ์œ„/ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฐ–์ถ˜ ์•ˆ์ •์ ์ธ ์„œ๋น„์Šค ๋ชฉํ‘œ

ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

exchange-watch/
โ”œโ”€โ”€ apps/
โ”‚   โ”œโ”€โ”€ backend/          # NestJS ๋ฐฑ์—”๋“œ API ์„œ๋ฒ„
โ”‚   โ””โ”€โ”€ frontend/         # Next.js ํ”„๋ก ํŠธ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
โ”œโ”€โ”€ packages/
โ”‚   โ””โ”€โ”€ shared/           # ๊ณต์œ  ํƒ€์ž… ๋ฐ ์œ ํ‹ธ๋ฆฌํ‹ฐ
โ””โ”€โ”€ package.json          # ์›Œํฌ์ŠคํŽ˜์ด์Šค ์„ค์ •

โš™๏ธ ๊ธฐ์ˆ  ์Šคํƒ

๋ฐฑ์—”๋“œ (NestJS)

๋ฒ”์ฃผ ๊ธฐ์ˆ  ์‚ฌ์šฉ์ฒ˜
Language TypeScript ์ •์  ํƒ€์ž… ๊ธฐ๋ฐ˜์œผ๋กœ ์•ˆ์ •์„ฑ๊ณผ ๊ฐ€๋…์„ฑ ํ™•๋ณด
Framework NestJS ๋ชจ๋“ˆ ๊ธฐ๋ฐ˜ ๊ตฌ์กฐ, DI๊ธฐ๋ฐ˜ ์„ค๊ณ„, ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ณ ์ ์šฉ
Realtime Websocket ์™ธ๋ถ€ API๋กœ๋ถ€ํ„ฐ (Websocket)์‹ค์‹œ๊ฐ„ ํ™˜์œจ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘
DB PostgreSQL ์ •๊ทœํ™”๋œ ์ด๋ ฅ ๋ฐ์ดํ„ฐ ์ €์žฅ ๋ฐ ๊ด€์‹ฌ ํ†ตํ™” ๋ฆฌ์ŠคํŠธ, ์œ ์ € ์ •๋ณด ๋ฐ ๋””๋ฐ”์ด์Šค ํ† ํฐ ๊ด€๋ฆฌ, ์•Œ๋ฆผ
ORM Prisma type-safeํ•œ DB์ ‘๊ทผ ๋ฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ž๋™ํ™” ๋ฐ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ๋ถ„๋ฆฌ
Cache Redis ์ˆ˜์ง‘๋œ ์‹ค์‹œ๊ฐ„ ํ™˜์œจ ์บ์‹ฑ ๋ฐ ์™ธ๋ถ€ API ํ˜ธ์ถœ ์ตœ์†Œํ™”
Messaging Redis Pub/Sub ํด๋ผ์ด์–ธํŠธ ๊ด€๋ฆฌ ๋ฐ Redis Pub/Sub์„ ํ†ตํ•œ ๋ณ€๋™๋œ ํ†ตํ™”์Œ๋งŒ ์‹ค์‹œ๊ฐ„ ๋ถ€๋ถ„ ์ „์†ก
AI OpenAI, Agentica ํ™˜์œจ ๋ถ„์„ ๋ฐ ์ธ์‚ฌ์ดํŠธ ์ƒ์„ฑ
Infra Docker, Docker Compose ๋กœ์ปฌ, ํ…Œ์ŠคํŠธ, ๋ฐฐํฌ ํ™˜๊ฒฝ ์ผ๊ด€์„ฑ ํ™•๋ณด
Test Jest, Supertest ๋‹จ์œ„/ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ๋ฐ ์™ธ๋ถ€ ์˜์กด์„ฑ ํ…Œ์ŠคํŠธ

๐Ÿงฑ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜


์‹ค์‹œ๊ฐ„ ํ™˜์œจ ์ˆ˜์ง‘

แ„‰แ…ตแ†ฏแ„‰แ…ตแ„€แ…กแ†ซ แ„’แ…ชแ†ซแ„‹แ…ฒแ†ฏ แ„‰แ…ฎแ„Œแ…ตแ†ธ แ„€แ…ฎแ„Œแ…ฉ แ„ƒแ…กแ„‹แ…ตแ„‹แ…ฅแ„€แ…ณแ„…แ…ขแ†ท
  1. CoinAPI WebSocket์„ ํ†ตํ•ด ๊ธฐ์ค€ ํ†ตํ™” ํ™˜์œจ ๋ฐ์ดํ„ฐ ์ˆ˜์‹ 
  2. ์ˆ˜์‹  ์ฆ‰์‹œ ExchangeRateReceivedEvent ์ด๋ฒคํŠธ ๋ฐœ์ƒ
  3. Redis์— ์ €์žฅ ์ „, ์ง์ „ ํ™˜์œจ๊ณผ ๋น„๊ตํ•˜์—ฌ ๋ณ€๋™ ์—ฌ๋ถ€ ํ™•์ธ
  4. ๋ณ€๋™์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ Redis์— ์ €์žฅ + Redis Pub/Sub ์ฑ„๋„์— publish
  5. ํด๋ผ์ด์–ธํŠธ๋Š” REST ๋˜๋Š” SSE๋ฅผ ํ†ตํ•ด Redis์—์„œ ์ตœ์‹  ํ™˜์œจ ์ˆ˜์‹ 

์„ค๊ณ„ ์˜๋„

  • WebSocket โ†’ Redis โ†’ SSE ๊ตฌ์กฐ๋กœ ์‹ค์‹œ๊ฐ„์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ๋™์‹œ์— ๊ฐ€์ ธ๊ฐ
  • ์ˆ˜์ง‘๊ณผ ์‘๋‹ต์„ ๋ถ„๋ฆฌํ•˜์—ฌ API ํ˜ธ์ถœ ์‹œ ์™ธ๋ถ€ ํ†ต์‹  ์—†์ด ์บ์‹œ์—์„œ ์‘๋‹ต
  • ์ด๋ฒคํŠธ ์ค‘์‹ฌ ํ๋ฆ„์œผ๋กœ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์‰ฌ์šด ๊ตฌ์กฐ
  • ์™ธ๋ถ€ API๋ฅผ ์„œ๋ฒ„ 1ํšŒ ์—ฐ๊ฒฐ๋กœ๋งŒ ์ˆ˜์‹ , ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ๋Š” Redis๋งŒ ์กฐํšŒํ•จ (์ตœ์ข… ๋ชฉํ‘œ)
  • ์ด์ „ ๊ฐ’๊ณผ์˜ ๋น„๊ต๋ฅผ ํ†ตํ•ด ๋ณ€๋™์ด ์žˆ์„ ๋•Œ๋งŒ Pub/Sub ๋ฐœ์ƒ โ†’ ๋ถˆํ•„์š”ํ•œ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐฉ์ง€

์ผ์ผ ํ™˜์œจ ์ง‘๊ณ„

แ„‹แ…ตแ†ฏแ„‹แ…ตแ†ฏแ„’แ…ชแ†ซแ„‹แ…ฒแ†ฏแ„Œแ…ตแ†ธแ„€แ…จแ„ƒแ…กแ„‹แ…ตแ„‹แ…ฅแ„€แ…ณแ„…แ…ขแ†ท

> ํ•˜๋ฃจ์— ํ•œ ๋ฒˆ, ์™ธ๋ถ€ API๋ฅผ ํ˜ธ์ถœํ•ด ์ „์ผ ์ˆ˜์ง‘๋œ ํ™˜์œจ๋“ค์„ ์ •์ œ๋œ OHLC ๋ฐ์ดํ„ฐ๋กœ ์ง‘๊ณ„ํ•˜๊ณ  DB์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

  1. ๋งค์ผ 00:05 (UTC)์— Cron ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ์ง‘๊ณ„ ํ”„๋กœ์„ธ์Šค ์‹คํ–‰
  2. ๊ธฐ์ค€ ํ†ตํ™” ๊ธฐ์ค€์œผ๋กœ Fluctuation API๋ฅผ ํ˜ธ์ถœํ•ด ์ „์ผ ๋ณ€๋™ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘
  3. exchange_rates_daily ํ…Œ์ด๋ธ”์— ์ €์žฅ

์„ค๊ณ„ ์˜๋„

  • ์ฐจํŠธ์šฉ ๋ฐ์ดํ„ฐ๋Š” ์‹ค์‹œ๊ฐ„ ์ˆ˜์ง‘์ด ์•„๋‹Œ, ์ผ๊ด€๋œ ์ง‘๊ณ„ ๊ธฐ์ค€์œผ๋กœ ๊ด€๋ฆฌ
  • Fluctuation API๋Š” ํ•˜๋ฃจ 1ํšŒ๋งŒ ํ˜ธ์ถœ โ†’ ์™ธ๋ถ€ API์š”์ฒญ ์ตœ์†Œํ™”
  • ์‹ค์‹œ๊ฐ„ ๊ตฌ์กฐ์™€ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์–ด ๋ฌธ์ œ ๋ฐœ์ƒ ์‹œ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์— ์˜ํ–ฅ ์—†์Œ

SSE ์š”์ฒญ ๊ตฌ์กฐ

SSEแ„’แ…ณแ„…แ…ณแ†ท แ„ƒแ…กแ„‹แ…ตแ„‹แ…ฅแ„€แ…ณแ„…แ…ขแ†ท

> ํด๋ผ์ด์–ธํŠธ๋Š” ๊ธฐ์ค€ ํ†ตํ™”๋ฅผ ์ง€์ •ํ•˜์—ฌ SSE(Server-Sent Events)๋กœ ์‹ค์‹œ๊ฐ„ ํ™˜์œจ์„ ๊ตฌ๋…

> ์„œ๋ฒ„๋Š” Redis Pub/Sub ์ฑ„๋„์„ ํ†ตํ•ด ํ™˜์œจ ๋ณ€๋™์ด ๊ฐ์ง€๋œ ๊ฒฝ์šฐ์—๋งŒ ํด๋ผ์ด์–ธํŠธ์— ์‹ค์‹œ๊ฐ„ ํ‘ธ์‹œํ•ฉ๋‹ˆ๋‹ค.

  1. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ธฐ์ค€ ํ†ตํ™”๋ฅผ ์ง€์ •ํ•˜์—ฌ SSE ๊ตฌ๋… ์š”์ฒญ
  2. ์„œ๋ฒ„๋Š” Redis Pub/Sub ์ฑ„๋„์„ ๊ตฌ๋… (latest-rate-pub:KRW)
  3. ์™ธ๋ถ€ WebSocket์œผ๋กœ ์ˆ˜์‹ ๋œ ํ™˜์œจ์ด ๋ณ€๋™๋œ ๊ฒฝ์šฐ์—๋งŒ Redis์— ์ €์žฅ + Pub ์ฑ„๋„์— publish
  4. SSE ์ŠคํŠธ๋ฆผ์„ ํ†ตํ•ด ํ•ด๋‹น ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ๋งŒ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ „์†ก

์„ค๊ณ„ ์˜๋„

  • WebSocket ์—†์ด ๋ธŒ๋ผ์šฐ์ € ์นœํ™”์ ์ธ ์‹ค์‹œ๊ฐ„ ๊ตฌ์กฐ ๊ตฌํ˜„
  • ๋ณ€๋™์ด ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ด๋ฒคํŠธ ์ „ํŒŒ โ†’ ํŠธ๋ž˜ํ”ฝ ์ตœ์†Œํ™”
  • Redis Pub/Sub์„ ํ†ตํ•ด ์„œ๋ฒ„ ์ธ์Šคํ„ด์Šค ๊ฐ„ ํ™•์žฅ์—๋„ ๋Œ€์‘ ๊ฐ€๋Šฅ
  • ๊ธฐ์ค€ ํ†ตํ™”๋ณ„ ์ฑ„๋„ ๋ถ„๋ฆฌ๋กœ ๊ด€์‹ฌ ๋ฐ์ดํ„ฐ๋งŒ ํšจ์œจ์ ์œผ๋กœ ์ „์†ก

  • ์ด๋ฏธ ์ €์žฅ๋œ OHLC ๋ฐ์ดํ„ฐ๋Š” ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉ โ†’ ์‘๋‹ต ์†๋„ ํ™•๋ณด

๊ธฐ์ˆ ์  ๋„์ „๊ณผ ํ•ด๊ฒฐ

1. 930๊ฐœ ํ†ตํ™”์Œ ์บ์‹ฑ ๋ฌธ์ œ -> ์—ญ์‚ฐ ์ตœ์ ํ™” ๊ตฌ์กฐ๋กœ ํ•ด๊ฒฐ

  • ์ดˆ๊ธฐ์—๋Š” ๋ชจ๋“  ํ†ตํ™”์Œ(31 * 30 = 930)์„ Redis์— ์ €์žฅํ•˜๋ ค๊ณ  ํ–ˆ์ง€๋งŒ
  • ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰๊ณผ Pub/Sub ํŠธ๋ž˜ํ”ฝ์ด ๋น„ํšจ์œจ์ ์ด๋ผ๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๊ณ ,
  • ๊ธฐ์ค€ ํ†ตํ™”(KRW)๋ฅผ ๊ธฐ์ค€์œผ๋กœ 30๊ฐœ๋งŒ ์ €์žฅํ•˜๊ณ , ๋‚˜๋จธ์ง€๋Š” ์š”์ฒญ ์‹œ ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ์—ญ์‚ฐ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝ
  • redis Hash ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ณ€๋™๋ฅ ์ด ์กด์žฌํ•˜์ง€ ์ตœ์‹  ํ™˜์œจ์„
  • ์ตœ์‹  ํ™˜์œจ ์ˆ˜์ง‘ ์‹œ, ๋ณ€๋™๋ฅ ์ด (๊ต‰์žฅํžˆ)๋ฏธ๋ฏธํ•˜๋‹ค๋ฉด timestamp๋งŒ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด redis hash์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ฑ„ํƒํ•ด ์žฆ์€ ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ์— ๋Œ€ํ•œ ์„ฑ๋Šฅ์„ ์ปค๋ฒ„ํ•˜์˜€์Šต๋‹ˆ๋‹ค โ†’ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๋Œ€ํญ ์ ˆ๊ฐ, API ์‘๋‹ต ์†๋„ ๊ธฐ์กด๋Œ€๋น„ 80% ํ–ฅ์ƒ

๋“ค์–ด๊ฐ€๊ธฐ ์ „์—, ์—ญ์‚ฐ ์ตœ์ ํ™” ๊ตฌ์กฐ๋Š” ์—ญ์‚ฐ์‹œ ์ •ํ™•๋„์˜ ํ•œ๊ณ„์„ฑ๋•Œ๋ฌธ์— ์ฒ ํšŒํ•˜์˜€์Œ ๊ด€๋ จ ์ด์Šˆ

1-2. ์—ญ์‚ฐ ์ตœ์ ํ™” ์˜ˆ์‹œ

  • ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—, ์šฐ๋ฆฌ ์„œ๋ฒ„๋Š” KRW/30๊ฐœ์˜ ํ†ตํ™”์Œ = ์ด 30๊ฐœ์˜ ๋‹จ์ผํ†ตํ™”์Œ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค (N์ดˆ๋งˆ๋‹ค ์ˆ˜์ง‘ ๋ฐ ์—…๋ฐ์ดํŠธ).
  • ๋งŒ์•ฝ ์‚ฌ์šฉ์ž๊ฐ€ USD/EUR์˜ ํ†ตํ™”์Œ์„ ์š”์ฒญํ•œ๋‹ค๋ฉด?

์ตœ์‹  ํ™˜์œจ ์—ญ์‚ฐ ์˜ˆ์‹œ

# Redis์— ์ €์žฅ๋œ ๊ฐ’ (์šฐ๋ฆฌ๋Š” ํ•ญ์ƒ ๋“ค๊ณ ์žˆ์Šต๋‹ˆ๋‹ค)
KRW โ†’ USD = 0.000699
KRW โ†’ EUR = 0.000616

# ์š”์ฒญ: USD/EUR
rate = 0.000616 / 0.000699 โ‰ˆ 0.8813

๋ณ€๋™๋ฅ  ์—ญ์‚ฐ ์˜ˆ์‹œ

# ๋ณ€๋™๋ฅ  ์—ญ์‚ฐ
KRW โ†’ EUR ๋ณ€๋™๋ฅ : +1.20%
KRW โ†’ USD ๋ณ€๋™๋ฅ : +0.85%

USD โ†’ EUR ๋ณ€๋™๋ฅ  โ‰ˆ 1.20% - 0.85% = 0.35%

2. ์™ธ๋ถ€ API ์œ ์—ฐ์„ฑ ๋ฌธ์ œ -> ๋„๋ฉ”์ธ ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜ ๊ตฌ์กฐ๋กœ ํ•ด๊ฒฐ

  • ๋‹ค์–‘ํ•œ ํ™˜์œจ API๋ฅผ ๊ธฐ๋Šฅ๋ณ„๋กœ ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ๊ณ ,
  • API๋งˆ๋‹ค ์‘๋‹ต ํฌ๋งท๊ณผ ๊ธฐ๋Šฅ ๋ฒ”์œ„๊ฐ€ ๋‹ฌ๋ผ, ์ง์ ‘ ์„œ๋น„์Šค์— ์—ฐ๊ฒฐํ•˜๋ฉด ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„์ง€๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Œ
  • ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์„œ๋น„์Šค์—์„œ ํ•„์š”ํ•œ ๋™์ž‘(์˜ˆ: getCurrentRate, getFluctuationData ๋“ฑ)์„ ๋ช…์‹œํ•œ ๊ณตํ†ต ์ธํ„ฐํŽ˜์ด์Šค(IExchangeRateExternalAPI)๋ฅผ ์ •์˜
  • ๋ชจ๋“  ์™ธ๋ถ€ API๋Š” ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋”ฐ๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๊ณ , ExternalApiModule์—์„œ ๊ฐˆ์•„๋ผ์šฐ๋Š” ์‹์œผ๋กœ(DI) ์›ํ•˜๋Š” API๋ฅผ ์ฃผ์ž…ํ•ด์„œ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค๊ณ„ โ†’ ๊ธฐ๋Šฅ ํ™•์žฅ, ํ…Œ์ŠคํŠธ์šฉ Mock ์ฃผ์ž…, API ๊ต์ฒด ๋“ฑ ๋ชจ๋“  ์ƒํ™ฉ์—์„œ ์œ ์—ฐํ•˜๊ฒŒ ๋Œ€์‘ ๊ฐ€๋Šฅ

3. ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์ฒ˜๋ฆฌ ๊ตฌ์กฐ ๋„์ž…

  • ์‹ค์‹œ๊ฐ„ ํ™˜์œจ ์ˆ˜์‹ (WebSocket)๊ณผ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง(์•Œ๋ฆผ ๋น„๊ต, ์ €์žฅ)์ด ์„œ๋กœ๋ฅผ ์ฐธ์กฐํ•˜๋ฉด์„œ, ExternalWebSocketGateway โ†” ExchangeRateService ๊ฐ„ ์ˆœํ™˜ ์˜์กด์„ฑ ๋ฐœ์ƒ
  • ๋‹จ์ˆœํžˆ forwardRef()๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜๋„ ์žˆ์—ˆ์ง€๋งŒ, ์ด๋Š” ๊ตฌ์กฐ์  ํ•ด๊ฒฐ์ด ์•„๋‹˜
  • ๋Œ€์‹  WebSocket ๊ฒŒ์ดํŠธ์›จ์ด๋Š” ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ , ๋‚ด๋ถ€์ ์œผ๋กœ ExchangeRateReceivedEvent๋ฅผ ๋ฐœํ–‰ํ•˜๋„๋ก ์„ค๊ณ„ ๋ณ€๊ฒฝ
  • ExchangeRateService๋Š” ์ด ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•˜์—ฌ, Redis ์ €์žฅ ๋ฐ ์•Œ๋ฆผ ๋กœ์ง์„ ์ฒ˜๋ฆฌ

โ†’ ๊ฒฐ๊ณผ์ ์œผ๋กœ

  • WebSocket ๋ชจ๋“ˆ๊ณผ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋ชจ๋“ˆ ๊ฐ„ ๊ฒฐํ•ฉ ์ œ๊ฑฐ
  • ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ ์ˆ˜์‹  โ†’ ๋‚ด๋ถ€ ๋กœ์ง ์ฒ˜๋ฆฌ ํ๋ฆ„์ด ๋‹จ๋ฐฉํ–ฅ์ด ๋จ
  • ํ…Œ์ŠคํŠธ, ์œ ์ง€๋ณด์ˆ˜, ํ™•์žฅ์„ฑ์ด ๋ชจ๋‘ ๊ฐœ์„ ๋จ

4. ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ๋ถ„๋ฆฌ ๋ฐ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ๊ตฌ์„ฑ

  • ์„œ๋น„์Šค ๋กœ์ง์€ mock ๊ธฐ๋ฐ˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ์ถฉ๋ถ„ํžˆ ์ปค๋ฒ„๋˜์ง€๋งŒ, Controller, Repository ๋‹จ์€ ํ…Œ์ŠคํŠธ ์ธํ”„๋ผ์™€ ํ•จ๊ป˜ ๊ฒ€์ฆํ•  ํ•„์š”๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค
  • ๊ทธ๋Ÿฌ๋‚˜ ํ…Œ์ŠคํŠธ ์ค‘ PostgreSQL/Redis ์˜์กด์„ฑ ์ถฉ๋Œ, ๋ฐ์ดํ„ฐ ์˜ค์—ผ ๋ฌธ์ œ ๋ฐœ์ƒ
  • ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ์™„์ „ํžˆ ๊ฒฉ๋ฆฌ์‹œ์ผœ ๊ตฌ์„ฑ:
  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” Jest๋กœ ์„œ๋น„์Šค ๋ ˆ์ด์–ด๋งŒ mockํ•˜์—ฌ ๋น ๋ฅด๊ฒŒ ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๋งŒ ์‹คํ–‰
  • docker-compose๋ฅผ ์ด์šฉํ•˜์—ฌ ์‹ค์ œ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ๊ณผ ๋™์ผํ•œ PostgreSQL/Redis ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰
  • ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์ „ Prisma migrate reset์œผ๋กœ ๋งค ํ…Œ์ŠคํŠธ๋งˆ๋‹ค DB ์Šคํ‚ค๋งˆ ์ดˆ๊ธฐํ™”
  • NestJS ๋ชจ๋“ˆ์„ ํ…Œ์ŠคํŠธ ์ „์šฉ์œผ๋กœ ๋ถ„๋ฆฌ ๊ตฌ์„ฑ (test-prisma.module.ts, test-redis.module.ts, test-cls.module.ts, test-config.module.ts)

โ†’ ๊ฒฐ๊ณผ์ ์œผ๋กœ

  • ๋น ๋ฅด๊ณ  ์•ˆ์ •์ ์ธ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ๊ตฌ์ถ•
  • ๊ตฌ์กฐ ๋ฆฌํŒฉํ† ๋ง/๋ณ€๊ฒฝ์—๋„ ์ž์‹  ์žˆ๊ฒŒ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ฐ˜์„ ๋งˆ๋ จ

About

Real-time Exchange Rate Check Server ๐Ÿš€

Resources

Stars

Watchers

Forks

Contributors

Languages