Skip to main content
์ƒ์„ฑ๋œ Namespace Service๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํƒ€์ž… ์•ˆ์ „ํ•˜๊ฒŒ API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ด…๋‹ˆ๋‹ค.

Service ์‚ฌ์šฉ ๊ฐœ์š”

Namespace ํ˜ธ์ถœ

UserService.getUser() ๊ฐ„๊ฒฐํ•œ ๋ฌธ๋ฒ•

ํƒ€์ž… ์•ˆ์ „

์ž๋™ ์™„์„ฑ ์ปดํŒŒ์ผ ๊ฒ€์ฆ

Subset ์ง€์›

ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ์„ฑ๋Šฅ ์ตœ์ ํ™”

TanStack Query

useUser Hook ์ž๋™ ์บ์‹ฑ

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

Service Import

์ƒ์„ฑ๋œ Service๋Š” services.generated.ts์—์„œ Namespace๋กœ export๋ฉ๋‹ˆ๋‹ค.
๋‹จ์ผ ํŒŒ์ผ import์˜ ์žฅ์ :
  1. ์ผ๊ด€์„ฑ: ๋ชจ๋“  Service๊ฐ€ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌ๋จ
  2. ๊ฐ„ํŽธํ•œ import: ํŒŒ์ผ ๊ฒฝ๋กœ ์ฐพ์„ ํ•„์š” ์—†์Œ
  3. ์ž๋™ ์—…๋ฐ์ดํŠธ: pnpm generate ์‹œ ์ž๋™์œผ๋กœ ๋™๊ธฐํ™”
  4. ๋ช…ํ™•ํ•œ ๋„ค์ด๋ฐ: Namespace๋กœ ๊ทธ๋ฃนํ™”๋˜์–ด ์ถฉ๋Œ ์—†์Œ

๊ธฐ๋ณธ API ํ˜ธ์ถœ

Service์˜ ์ •์  ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
ํŠน์ง•:
  • await์œผ๋กœ ๋น„๋™๊ธฐ ํ˜ธ์ถœ
  • ์‘๋‹ต์€ ์ž๋™์œผ๋กœ ํŒŒ์‹ฑ๋จ (fetch ํ•จ์ˆ˜ ๋‚ด๋ถ€ ์ฒ˜๋ฆฌ)
  • ํƒ€์ž…์ด ์™„์ „ํžˆ ๋ณด์žฅ๋จ
  • Subset ํŒŒ๋ผ๋ฏธํ„ฐ ํ•„์ˆ˜ (getUser ๋“ฑ)
Namespace ๊ธฐ๋ฐ˜ ๊ตฌ์กฐ: - โŒ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค: new UserService() ๋ถˆํ•„์š” - โœ… ์ •์  ํ•จ์ˆ˜: UserService.getUser() ์ง์ ‘ ํ˜ธ์ถœ - ๋ชจ๋“  ํ•จ์ˆ˜๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ๋™์ž‘

Subset ์‹œ์Šคํ…œ ์ดํ•ดํ•˜๊ธฐ

Sonamu์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ธ Subset ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค.
Subset์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ :
  1. ์„ฑ๋Šฅ: ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ์กฐํšŒํ•˜์—ฌ ๋„คํŠธ์›Œํฌ ๋น„์šฉ ์ ˆ๊ฐ
  2. ํƒ€์ž… ์•ˆ์ „: ๊ฐ Subset๋งˆ๋‹ค ์ •ํ™•ํ•œ ํƒ€์ž… ๋ฐ˜ํ™˜
  3. ๋ช…์‹œ์„ฑ: ์–ด๋–ค ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•œ์ง€ ์ฝ”๋“œ์—์„œ ๋ช…ํ™•ํžˆ ํ‘œํ˜„

React์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ

TanStack Query Hook (๊ถŒ์žฅ)

๊ฐ€์žฅ ๊ฐ„ํŽธํ•œ ๋ฐฉ๋ฒ•์€ ์ž๋™ ์ƒ์„ฑ๋œ TanStack Query Hook์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
TanStack Query Hook์˜ ์žฅ์ :
  • ์ž๋™ ์บ์‹ฑ (๊ฐ™์€ userId ์žฌ์‚ฌ์šฉ)
  • ์ž๋™ ์žฌ๊ฒ€์ฆ (ํฌ์ปค์Šค ์‹œ, ์žฌ์—ฐ๊ฒฐ ์‹œ)
  • ๋กœ๋”ฉ/์—๋Ÿฌ ์ƒํƒœ ์ž๋™ ๊ด€๋ฆฌ
  • ์ค‘๋ณต ์š”์ฒญ ์ž๋™ ์ œ๊ฑฐ

ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ (useEffect)

Hook์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ง์ ‘ ํ˜ธ์ถœํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ถŒ์žฅ: ๊ฐ€๋Šฅํ•˜๋ฉด TanStack Query Hook์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ž๋™ ์บ์‹ฑ, ์žฌ๊ฒ€์ฆ, ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ๋ชจ๋‘ ์ œ๊ณตํ•˜์—ฌ ์ฝ”๋“œ๊ฐ€ ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•ด์ง‘๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ

์‚ฌ์šฉ์ž ์•ก์…˜์— ๋”ฐ๋ผ API๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

useTypeForm์œผ๋กœ ํผ ์ฒ˜๋ฆฌํ•˜๊ธฐ (๊ถŒ์žฅ)

@sonamu-kit/react-components์˜ useTypeForm์„ ์‚ฌ์šฉํ•˜๋ฉด ํƒ€์ž… ์•ˆ์ „ํ•œ ํผ์„ ๋” ๊ฐ„ํŽธํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
useTypeForm์˜ ์žฅ์ :
  • โœ… ํƒ€์ž… ์•ˆ์ „: Zod ์Šคํ‚ค๋งˆ์—์„œ ํƒ€์ž… ์ž๋™ ์ถ”๋ก 
  • โœ… ์ž๋™ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ: ์Šคํ‚ค๋งˆ ๊ทœ์น™ ์ž๋™ ์ ์šฉ
  • โœ… ๊ฐ„๊ฒฐํ•œ ์ฝ”๋“œ: useState + ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋ถˆํ•„์š”
  • โœ… ์—๋Ÿฌ ์ฒ˜๋ฆฌ: ํ•„๋“œ๋ณ„ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ž๋™ ๊ด€๋ฆฌ
  • โœ… ํ†ตํ•ฉ ์ปดํฌ๋„ŒํŠธ: Input, Button ๋“ฑ ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
๊ถŒ์žฅ: ์ƒˆ๋กœ์šด ํผ์„ ์ž‘์„ฑํ•  ๋•Œ๋Š” useTypeForm์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ๋ฅผ ํฌ๊ฒŒ ์ค„์ด๊ณ  ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
์—๋Ÿฌ ํ‘œ์‹œ ์˜ˆ์ œ:
ํŒจํ„ด ๋น„๊ต:
@sonamu-kit/react-components๋Š” Material-UI, Ant Design ๋“ฑ ๋‹ค๋ฅธ UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€๋„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SSR์—์„œ Service ์‚ฌ์šฉํ•˜๊ธฐ

Sonamu๋Š” Vite + React ๊ธฐ๋ฐ˜์˜ SSR์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. SSR์—์„œ๋Š” queries.generated.ts์— ์ž๋™ ์ƒ์„ฑ๋œ SSR ์ „์šฉ Service๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

SSR Service๋ž€?

ํ”„๋ก ํŠธ์—”๋“œ Service(services.generated.ts)์™€๋Š” ๋ณ„๊ฐœ๋กœ, ๋ฐฑ์—”๋“œ์— SSR ์ „์šฉ Service๊ฐ€ ์ž๋™ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

registerSSR์—์„œ ์‚ฌ์šฉ

SSR ๋ผ์šฐํŠธ๋ฅผ ๋“ฑ๋กํ•  ๋•Œ ์ด Service๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ Service vs SSR Service

ํ•ต์‹ฌ ์ฐจ์ด์ : SSR Service๋Š” HTTP ์š”์ฒญ ์—†์ด ๋ฐฑ์—”๋“œ Model ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•˜๋ฏ€๋กœ ๋„คํŠธ์›Œํฌ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋” ์•Œ์•„๋ณด๊ธฐ

SSR์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

๋ฐ์ดํ„ฐ ํ”„๋ฆฌ๋กœ๋”ฉ

registerSSR๋กœ ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ ๋ฏธ๋ฆฌ ๋กœ๋“œํ•˜๊ธฐ

SSR ์„ค์ •

SSR ์‹œ์Šคํ…œ ์ดํ•ดํ•˜๊ธฐ

Service ์ƒ์„ฑ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ์ดํ•ดํ•˜๊ธฐ

Service๋Š” Namespace ๊ธฐ๋ฐ˜์˜ ์ •์  ํ•จ์ˆ˜ ๋ชจ์Œ์ž…๋‹ˆ๋‹ค.

Service๋Š” ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ Namespace

Namespace์˜ ํŠน์ง•:
  • ๋ฌด์ƒํƒœ (Stateless): ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์Œ
  • ์ •์  ํ˜ธ์ถœ: UserService.getUser() ์ง์ ‘ ํ˜ธ์ถœ
  • ํƒ€์ž… ์•ˆ์ „: TypeScript Namespace๋กœ ์™„๋ฒฝํ•œ ํƒ€์ž… ์ถ”๋ก 
  • ํŠธ๋ฆฌ ์…ฐ์ดํ‚น: ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•จ์ˆ˜๋Š” ๋ฒˆ๋“ค์— ํฌํ•จ ์•ˆ๋จ

Service๋Š” ์˜์กด์„ฑ ์ฃผ์ž…(DI)์ด ์—†์Œ

Service๋Š” ์ˆœ์ˆ˜ ํ•จ์ˆ˜์ด๋ฏ€๋กœ ์˜์กด์„ฑ์ด ์ฃผ์ž…๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค:
Context๋Š” ์–ด๋–ป๊ฒŒ ์ „๋‹ฌ๋˜๋‚˜์š”? Service๋Š” HTTP ์š”์ฒญ์œผ๋กœ Context๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค:
๋ฐฑ์—”๋“œ์—์„œ๋Š” HTTP ์š”์ฒญ์—์„œ Context๋ฅผ ์ž๋™ ์ถ”์ถœ:

Service ์ƒ์„ฑ ๊ณผ์ •

์ƒ์„ฑ ๋‹จ๊ณ„:
  1. ๋ฐฑ์—”๋“œ: Model์— @api ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ์ž‘์„ฑ
  2. Sonamu Sync: pnpm sonamu sync ์‹คํ–‰
  3. ์ž๋™ ์ƒ์„ฑ: services.generated.ts ํŒŒ์ผ ์ƒ์„ฑ
  4. Namespace ํ•จ์ˆ˜: ๊ฐ API ๋ฉ”์„œ๋“œ๊ฐ€ Namespace ํ•จ์ˆ˜๋กœ ๋ณ€ํ™˜
  5. Hook ์ƒ์„ฑ: GET ๋ฉ”์„œ๋“œ๋Š” useQuery Hook ์ž๋™ ์ƒ์„ฑ

Model Instance๋Š” ์–ด๋””์— ์žˆ๋‚˜์š”?

Server Components์—์„œ ์ง์ ‘ ์ƒ์„ฑ:
์™œ new UserModel()์„ ํ•ด๋„ ๋˜๋‚˜์š”?
  • Model์€ ๋ฌด์ƒํƒœ์ด๋ฏ€๋กœ ๋งค๋ฒˆ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด๋„ ์•ˆ์ „
  • Constructor์—์„œ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๊ฒƒ์€ Subset ์ฟผ๋ฆฌ๋ฟ
  • Context๋Š” Sonamu.getContext()๋กœ ๋™์ ์œผ๋กœ ๊ฐ€์ ธ์˜ด

Service vs Model ๋น„๊ต

Model ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ์‹œ ์ฃผ์˜์‚ฌํ•ญ: 1. Server Components์—์„œ๋งŒ: Client Component์—์„œ๋Š” Model์„ importํ•  ์ˆ˜ ์—†์Œ 2. ๋งค๋ฒˆ ์ƒ์„ฑ: ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด ์‚ฌ์šฉ ๋ถˆํ•„์š” (๋ฌด์ƒํƒœ์ด๋ฏ€๋กœ) 3. Context ์ ‘๊ทผ: Sonamu.getContext()๋Š” ์š”์ฒญ ์ปจํ…์ŠคํŠธ์—์„œ ์ž๋™์œผ๋กœ ๊ฐ€์ ธ์˜ด
๊ถŒ์žฅ ํŒจํ„ด: - Client Component: Service ์‚ฌ์šฉ - Server Component: Model ์ง์ ‘ ์‚ฌ์šฉ - API ์—”๋“œํฌ์ธํŠธ: Model์— @api ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ

Client Components

Client Components์—์„œ๋Š” Service๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—๋Ÿฌ ์ฒ˜๋ฆฌ

SonamuError ์ฒ˜๋ฆฌ

Service ํ˜ธ์ถœ ์‹œ ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ๋ฅผ ํƒ€์ž… ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

React์—์„œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ

๊ณ ๊ธ‰ ํŒจํ„ด

๋ณ‘๋ ฌ ์š”์ฒญ

์—ฌ๋Ÿฌ API๋ฅผ ๋™์‹œ์— ํ˜ธ์ถœํ•˜์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
์„ฑ๋Šฅ ๋น„๊ต:
  • ์ˆœ์ฐจ: 300ms + 200ms + 150ms = 650ms
  • ๋ณ‘๋ ฌ: max(300ms, 200ms, 150ms) = 300ms

Subset ํ™œ์šฉ ์ตœ์ ํ™”

์ƒํ™ฉ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ Subset์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

TanStack Query ํ™œ์šฉ

์กฐ๊ฑด๋ถ€ ํŽ˜์นญ

์บ์‹œ ๋ฌดํšจํ™”

Prefetching

์‹ค์ „ ์˜ˆ์ œ

์ „์ฒด CRUD ํ”Œ๋กœ์šฐ

์ฃผ์˜์‚ฌํ•ญ

Service ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์‚ฌํ•ญ: 1. ์ƒ์„ฑ๋œ Service ํŒŒ์ผ(services.generated.ts)์€ ์ ˆ๋Œ€ ์ˆ˜๋™ ์ˆ˜์ • ๊ธˆ์ง€ 2. Subset ํŒŒ๋ผ๋ฏธํ„ฐ ํ•„์ˆ˜: getUser ๋“ฑ์—์„œ subset ์ง€์ • ํ•„์š” 3. Server Components์—์„œ๋Š” Service ๋Œ€์‹  ๋ฐฑ์—”๋“œ ๋ชจ๋ธ ์ง์ ‘ ํ˜ธ์ถœ 4. ์—๋Ÿฌ ์ฒ˜๋ฆฌ ์‹œ isSonamuError() ํƒ€์ž… ๊ฐ€๋“œ ์‚ฌ์šฉ 5. TanStack Query Hook์€ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ๋งŒ ํ˜ธ์ถœ 6. await ํ‚ค์›Œ๋“œ ํ•„์ˆ˜ (๋ชจ๋“  Service ํ•จ์ˆ˜๋Š” async) 7. Namespace์ด๋ฏ€๋กœ new ๋ถˆํ•„์š”: UserService.getUser() ์ง์ ‘ ํ˜ธ์ถœ

๋‹ค์Œ ๋‹จ๊ณ„

Service ๋™์ž‘ ์›๋ฆฌ

์ž๋™ ์ƒ์„ฑ ์ดํ•ดํ•˜๊ธฐ

TanStack Query Hook

React์—์„œ ๋” ์‰ฝ๊ฒŒ

์ธ์ฆ

์ธ์ฆ ์‹œ์Šคํ…œ

์—๋Ÿฌ ์ฒ˜๋ฆฌ

์—๋Ÿฌ ์ฒ˜๋ฆฌ ํŒจํ„ด