์๋ ์์ฑ Service ๊ฐ์
ํ์ ์์ ์ฑ
๋ฐฑ์๋์ ๋๊ธฐํ ์ปดํ์ผ ํ์ ๊ฒ์ฆ
Namespace ๊ธฐ๋ฐ
์ ์ ํจ์ ๊ฐ๊ฒฐํ ํธ์ถ
TanStack Query
React Hook ์๋ ์์ฑ ์บ์ฑ๊ณผ ์ฌ๊ฒ์ฆ
Subset ์ง์
ํ์ํ ํ๋๋ง ์ฑ๋ฅ ์ต์ ํ
์ ์๋ ์์ฑ์ธ๊ฐ?
๋ฌธ์ : ์๋ API ํด๋ผ์ด์ธํธ์ ํ๊ณ
์ ํต์ ์ธ ํ๋ก ํธ์๋ ๊ฐ๋ฐ์์๋ ๋ฐฑ์๋ API๋ฅผ ํธ์ถํ๊ธฐ ์ํด ์๋์ผ๋ก ํด๋ผ์ด์ธํธ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค. ์๋ ํด๋ผ์ด์ธํธ ์์:- ํ์
์์ ์ฑ ๋ถ์ฌ:
anyํ์ ๋จ๋ฐ, ๋ฐํ์ ์๋ฌ ๋ฐ์ - ๋ฐฑ์๋ ๋ณ๊ฒฝ ์ถ์ ๋ถ๊ฐ: API๊ฐ ๋ณ๊ฒฝ๋์ด๋ ํ๋ก ํธ์๋๋ ๋ชจ๋ฆ
- ์ค๋ณต ์ฝ๋: ๋ชจ๋ API๋ง๋ค ๋น์ทํ ์ฝ๋ ๋ฐ๋ณต
- ์ค์ ๊ฐ๋ฅ์ฑ: URL ์คํ, ์๋ชป๋ ํ๋ผ๋ฏธํฐ ๋ฑ
- ์ ์ง๋ณด์ ์ด๋ ค์: API ๋ณ๊ฒฝ ์ ๋ชจ๋ ํธ์ถ ์ง์ ์์ ํ์
ํด๊ฒฐ: ์๋ ์์ฑ์ ์ฅ์
Sonamu๋ ๋ฐฑ์๋์@api ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ๋ถ์ํ์ฌ ํ์
์์ ํ ํด๋ผ์ด์ธํธ๋ฅผ ์๋ ์์ฑํฉ๋๋ค.
์๋ ์์ฑ ํด๋ผ์ด์ธํธ ์์:
- โจ ์์ ํ ํ์ ์์ ์ฑ: ๋ฐฑ์๋ ํ์ ์ด ํ๋ก ํธ์๋์ ๊ทธ๋๋ก ๋ฐ์
- โจ ์ฆ๊ฐ์ ์ธ ์๋ฌ ๋ฐ๊ฒฌ: ์ปดํ์ผ ํ์์ API ๋ณ๊ฒฝ ๊ฐ์ง
- โจ ์๋ ์์ฑ: IDE๊ฐ API ํ๋ผ๋ฏธํฐ์ ์๋ต ํ์ ์๋ ์ ์
- โจ Namespace ๊ธฐ๋ฐ: ๊น๋ํ ๊ตฌ์กฐ, import ๊ฐํธ
- โจ ๋จ์ผ ์ง์ค ๊ณต๊ธ์: ๋ฐฑ์๋๊ฐ API ๋ช ์ธ์ ์ ์ผํ ์์ค
**๋จ์ผ ์ง์ค ๊ณต๊ธ์ (Single Source of Truth)**์ด๋ ์์คํ
์ ๋ชจ๋ ์ ๋ณด๊ฐ ํ๋์ ์์ค์์ ํ์๋๋
์์น์
๋๋ค. Sonamu์์๋ ๋ฐฑ์๋์
@api ๋ฐ์ฝ๋ ์ดํฐ๊ฐ ์ ์ผํ API ๋ช
์ธ์ด๋ฉฐ, ํ๋ก ํธ์๋๋ ์ด๋ฅผ
๋ฐ๋ผ๊ฐ๋๋ค.Service ์์ฑ ๊ณผ์
1๋จ๊ณ: ๋ฐฑ์๋ API ์ ์
๋ฐฑ์๋์์@api ๋ฐ์ฝ๋ ์ดํฐ๋ก API๋ฅผ ์ ์ํฉ๋๋ค.
2๋จ๊ณ: TypeScript AST ํ์ฑ
Sonamu๋ TypeScript ์ปดํ์ผ๋ฌ API๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋๋ฅผ ๋ถ์ํฉ๋๋ค. ๋ถ์ ๊ณผ์ :- AST (Abstract Syntax Tree): ์ฝ๋๋ฅผ ํธ๋ฆฌ ๊ตฌ์กฐ๋ก ํํํ ๊ฒ
- ํ์ ์ถ์ถ: TypeScript์ ํ์ ์์คํ ์์ ์ ํํ ํ์ ์ ๋ณด ํ๋
- ๋ฉํ๋ฐ์ดํฐ ์์ง: ๋ฐ์ฝ๋ ์ดํฐ ์ต์ , Guards, ์ฃผ์ ๋ฑ ๋ชจ๋ ์ ๋ณด ์์ง
3๋จ๊ณ: Namespace Service ์์ฑ
์์ง๋ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก Namespace ๊ธฐ๋ฐ Service๋ฅผ ์์ฑํฉ๋๋ค. ์์ฑ๋๋ ์ฝ๋ (services.generated.ts):- ๊ฐ๊ฒฐํจ: ํด๋์ค๋ณด๋ค ๊ฐ๋จ (new ๋ถํ์)
- ์ ์ ๋ฉ์๋: ์ํ ๊ด๋ฆฌ ๋ถํ์
- Tree-shaking: ์ฌ์ฉํ์ง ์๋ ํจ์๋ ๋ฒ๋ค์์ ์ ์ธ
- Import ๊ฐํธ:
import { UserService } from "./services.generated"
4๋จ๊ณ: TanStack Query Hook ์์ฑ
React์์ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ Hook๋ ์๋ ์์ฑ๋ฉ๋๋ค.- ์๋ ์บ์ฑ
- ์๋ ์ฌ๊ฒ์ฆ
- ๋ก๋ฉ/์๋ฌ ์ํ ์๋ ๊ด๋ฆฌ
- ์กฐ๊ฑด๋ถ ํ์นญ ์ง์
- ๋๊ด์ ์ ๋ฐ์ดํธ ์ง์
์์ฑ๋ Service์ ๊ตฌ์กฐ
fetch ์ ํธ๋ฆฌํฐ ํจ์
๋ชจ๋ Service๊ฐ ์ฌ์ฉํ๋ ๊ณตํต fetch ํจ์์ ๋๋ค.- Axios ํธ์ถ ๋ํ:
options๋ฅผ Axios์ ์ ๋ฌ - ์๋ ์๋ต ์ถ์ถ:
res.data๋ฅผ ๋ฐ๋ก ๋ฐํ - ์๋ฌ ๋ณํ: Axios ์๋ฌ โ
SonamuError - Zod ์ด์ ์ฒ๋ฆฌ: ์ ํจ์ฑ ๊ฒ์ฌ ์๋ฌ๋ฅผ ํ์ ์์ ํ๊ฒ ์ฒ๋ฆฌ
Subset ์์คํ
Sonamu์ ๋ ํนํ ๊ธฐ๋ฅ์ธ Subset ์์คํ ์ ๋๋ค. Subset์ด๋? ์ํฐํฐ์ ์ฌ๋ฌ ๋ณํ(subset)์ ์ ์ํ์ฌ ํ์ํ ํ๋๋ง ์กฐํํ ์ ์๋ ์์คํ ์ ๋๋ค.- ์ฑ๋ฅ: ํ์ํ ํ๋๋ง ์กฐํํ์ฌ ๋คํธ์ํฌ ๋น์ฉ ์ ๊ฐ
- ํ์ ์์ : ๊ฐ Subset๋ง๋ค ์ ํํ ํ์ ๋ฐํ
- ๋ช ์์ฑ: ์ด๋ค ๋ฐ์ดํฐ๊ฐ ํ์ํ์ง ์ฝ๋์์ ๋ช ํํ ํํ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ต์ ํ: SELECT ์ ์ ํ์ํ ์ปฌ๋ผ๋ง ํฌํจ
- A: ๊ธฐ๋ณธ ํ๋ (id, ํต์ฌ ์ ๋ณด)
- B: ์ค๊ฐ ํ๋ (A + ์ถ๊ฐ ์ ๋ณด)
- C: ์ ์ฒด ํ๋ (๋ชจ๋ ์ปฌ๋ผ, ํ์์คํฌํ ํฌํจ)
ํ์ ์์ ์ฑ์ ์ค์
์ปดํ์ผ ํ์ ๊ฒ์ฆ
๋ฐฑ์๋ API๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์ปดํ์ผ ํ์์ ์ฆ์ ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค. ๋ฐฑ์๋ ๋ณ๊ฒฝ:IDE ์๋ ์์ฑ
ํ์ ์ ๋ณด ๋๋ถ์ IDE๊ฐ ๊ฐ๋ ฅํ ์๋ ์์ฑ์ ์ ๊ณตํฉ๋๋ค.๊ฐ๋ฐ ์ํฌํ๋ก์ฐ
๋ฐฑ์๋ ์ฐ์ ๊ฐ๋ฐ
Sonamu์ ์๋ ์์ฑ์ ๋ฐฑ์๋ ์ฐ์ (Backend-First) ๊ฐ๋ฐ์ ๊ถ์ฅํฉ๋๋ค. ์ผ๋ฐ์ ์ธ ์ํฌํ๋ก์ฐ: ์ฅ์ :- ๋ฐฑ์๋์ ํ๋ก ํธ์๋์ ๊ณ์ฝ(Contract)์ด ๋ช ํ
- ํ์ ๋ถ์ผ์น๋ก ์ธํ ๋ฒ๊ทธ ์์ฒ ์ฐจ๋จ
- API ๋ฌธ์ ์๋ ์์ฑ (Service๊ฐ ๊ณง ๋ฌธ์)
- ํ์ ํจ์จ์ฑ ํฅ์
๊ฐ๋ฐ ์ ์ฌ์์ฑ
API๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค Service๋ฅผ ์ฌ์์ฑํด์ผ ํฉ๋๋ค.์ค์ ์ฌ์ฉ ์์
๊ธฐ๋ณธ ์ฌ์ฉ
React์์ ์ฌ์ฉ (TanStack Query Hook)
์กฐ๊ฑด๋ถ ํ์นญ
๊ณ ๊ธ ๊ธฐ๋ฅ
qs.stringify ์ฌ์ฉ
GET ์์ฒญ์ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ฅผ ์ง๋ ฌํํ ๋qs ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- ์ค์ฒฉ ๊ฐ์ฒด ์ง์ (
filters[status]=active) - ๋ฐฐ์ด ์ง๋ ฌํ ์ง์ (
ids[]=1&ids[]=2) - ๋ฐฑ์๋์ ํ์ฑ ๋ฐฉ์๊ณผ ์ผ์น
์๋ฌ ์ฒ๋ฆฌ
SonamuError๋ฅผ ํ์ ์์ ํ๊ฒ ์ฒ๋ฆฌํฉ๋๋ค.Query Options ์ฌ์ฌ์ฉ
Prefetching
์ฃผ์์ฌํญ
๋ค์ ๋จ๊ณ
Service ์ฌ์ฉํ๊ธฐ
์์ฑ๋ Service ํ์ฉ๋ฒ
TanStack Query Hook
React์์ ์ฌ์ฉํ๊ธฐ
Creating APIs
@api ๋ฐ์ฝ๋ ์ดํฐ
Subset System
Subset ์์คํ