Skip to main content
@api ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” Model ๋ฉ”์„œ๋“œ๋ฅผ HTTP API ์—”๋“œํฌ์ธํŠธ๋กœ ์ž๋™ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ์— ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ผ์šฐํŒ…, ํƒ€์ž… ๊ฒ€์ฆ, ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๊ฐ€ ์ž๋™ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

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

์ƒ์„ฑ๋˜๋Š” ๊ฒƒ๋“ค:
  • HTTP ์—”๋“œํฌ์ธํŠธ: GET /user/findById?id=1
  • TypeScript ํด๋ผ์ด์–ธํŠธ ํ•จ์ˆ˜
  • TanStack Query hooks (์„ ํƒ ์‹œ)
  • API ๋ฌธ์„œ

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ์˜ต์…˜

์ „์ฒด ์˜ต์…˜

httpMethod

HTTP ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
๊ธฐ๋ณธ๊ฐ’: httpMethod๋ฅผ ์ƒ๋žตํ•˜๋ฉด GET์ด ๊ธฐ๋ณธ๊ฐ’์ž…๋‹ˆ๋‹ค.

clients

์ƒ์„ฑํ•  ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ํƒ€์ž…์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
์ƒ์„ฑ๋˜๋Š” ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ:
๊ธฐ๋ณธ๊ฐ’: clients๋ฅผ ์ƒ๋žตํ•˜๋ฉด ["axios"]๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์ž…๋‹ˆ๋‹ค.

path

์ปค์Šคํ…€ API ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ:
๊ฒฝ๋กœ๋ฅผ ์ƒ๋žตํ•˜๋ฉด /{model}/{method} ํ˜•์‹์œผ๋กœ ์ž๋™ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  • Model: UserModel โ†’ user
  • Method: findById โ†’ findById
  • ๊ฒฐ๊ณผ: /user/findById

resourceName

API ๋ฆฌ์†Œ์Šค ์ด๋ฆ„์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. TanStack Query์˜ queryKey์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
๋„ค์ด๋ฐ ๊ฐ€์ด๋“œ:

guards

์ธ์ฆ ๋ฐ ๊ถŒํ•œ ๊ฒ€์‚ฌ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
Guard ์ข…๋ฅ˜:
Guard ๋กœ์ง์€ sonamu.config.ts์˜ guardHandler์—์„œ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
sonamu.config.ts

contentType

์‘๋‹ต์˜ Content-Type์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

timeout

API ํƒ€์ž„์•„์›ƒ์„ ๋ฐ€๋ฆฌ์ดˆ ๋‹จ์œ„๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
ํƒ€์ž„์•„์›ƒ์€ ํด๋ผ์ด์–ธํŠธ ์ธก ์„ค์ •์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„์—์„œ๋Š” ๊ณ„์† ์‹คํ–‰๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์„œ๋ฒ„ ์ธก ํƒ€์ž„์•„์›ƒ๋„ ๋ณ„๋„๋กœ ์„ค์ •ํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

cacheControl

HTTP Cache-Control ํ—ค๋”๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
CacheControl ์˜ต์…˜:

compress

์‘๋‹ต ์••์ถ• ์„ค์ •์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ์กฐํ•ฉ

@api + @transactional

ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ API๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

@upload (๋…๋ฆฝ ์‚ฌ์šฉ)

ํŒŒ์ผ ์—…๋กœ๋“œ API๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. @upload๋Š” @api ์—†์ด ๋…๋ฆฝ์ ์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
Upload ์˜ต์…˜: ๋‹จ์ผ/๋‹ค์ค‘ ํŒŒ์ผ ์—ฌ๋ถ€๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…(UploadedFile vs UploadedFile[])์œผ๋กœ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.

API ๊ฒฝ๋กœ ๊ทœ์น™

๊ธฐ๋ณธ ๊ฒฝ๋กœ๋Š” ๋‹ค์Œ ๊ทœ์น™์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค:
๋ณ€ํ™˜ ๊ทœ์น™:
  • Model ์ด๋ฆ„: PascalCase โ†’ camelCase
    • UserModel โ†’ user
    • BlogPostModel โ†’ blogPost
  • Method ์ด๋ฆ„: ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ
    • findById โ†’ findById
์˜ˆ์‹œ:

์‹ค์ „ ์˜ˆ์ œ

๊ธฐ๋ณธ CRUD API

์ธ์ฆ API

Sonamu๋Š” ์ธ์ฆ์„ better-auth์˜ HTTP ์—”๋“œํฌ์ธํŠธ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธ(/api/auth/sign-in/email), ๋กœ๊ทธ์•„์›ƒ(/api/auth/sign-out) ๋“ฑ์€ Sonamu @api ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๊ฐ€ ์•„๋‹Œ better-auth๊ฐ€ ์ง์ ‘ ์ œ๊ณตํ•˜๋Š” ์—”๋“œํฌ์ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” me() API๋Š” context.user๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

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

Business Logic

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ž‘์„ฑ ํŒจํ„ด ๋ฐฐ์šฐ๊ธฐ

Stream Decorator

@stream์œผ๋กœ ์‹ค์‹œ๊ฐ„ ์ด๋ฒคํŠธ ์ „์†กํ•˜๊ธฐ

Upload Decorator

@upload๋กœ ํŒŒ์ผ ์—…๋กœ๋“œ ์ฒ˜๋ฆฌํ•˜๊ธฐ

Guards

์ธ์ฆ๊ณผ ๊ถŒํ•œ ๊ฒ€์‚ฌ ๊ตฌํ˜„ํ•˜๊ธฐ