λ°±μ—”λ“œμ™€ 데이터, νƒ€μž… μ£Όκ³ λ°›κΈ°

NaHCoH
  • #API
  • #React
  • #DTO
  • #Typescript

μ•ˆλ…•ν•˜μ„Έμš”. λ…Έλ¨ΈμŠ€ ν”„λ‘ νŠΈμ—”λ“œ νŒ€ ν™©ν˜Έμ°¬μž…λ‹ˆλ‹€.

μ˜€λŠ˜μ€ κ°œλ°œνŒ€μ—μ„œ ν”„λ‘ νŠΈμ—”λ“œνŒ€κ³Ό λ°±μ—”λ“œνŒ€κ°„μ— API 톡신에 λŒ€ν•΄μ„œ μ†Œκ°œν•΄λ³΄λ €κ³  ν•©λ‹ˆλ‹€. λ‹¨μˆœνžˆ APIλ₯Ό 톡해 데이터λ₯Ό μ£Όκ³ λ°›λŠ”κ²ƒ 뿐이 μ•„λ‹ˆλΌ μ–΄λ–€μ‹μœΌλ‘œ 두 νŒ€μ΄ λ…Όμ˜λ₯Ό ν•˜κ³ , 저희 νŒ€ λ‚΄μ—μ„œ μ–΄λ–€μ‹μœΌλ‘œ νƒ€μž…μ„ κ΄€λ¦¬ν•˜λŠ”μ§€μ— λŒ€ν•œ 이야기λ₯Ό μ˜ˆμ‹œ μ½”λ“œμ™€ ν•¨κ»˜ 개발 진행 μˆœμ„œλŒ€λ‘œ 진행해보렀 ν•©λ‹ˆλ‹€.

1. API μΈν„°νŽ˜μ΄μŠ€ μž‘μ„±

μš°μ„  ν”„λ‘œμ νŠΈμ˜ 기획, λ””μžμΈμ— λŒ€ν•œ λ…Όμ˜κ°€ μ’…λ£Œλœ ν›„ API μΈν„°νŽ˜μ΄μŠ€λ₯Ό μž‘μ„±ν•©λ‹ˆλ‹€. μž‘μ„± μ£Όμ²΄λŠ” λ°±μ—”λ“œ 개발 λ‹΄λ‹Ήμžκ°€ μ•„λ‹Œ ν”„λ‘ νŠΈ 개발 λ‹΄λ‹Ήμžκ°€ μž‘μ„±ν•©λ‹ˆλ‹€.

μ²˜μŒμ—λŠ” λ°±μ—”λ“œνŒ€μ—μ„œ μΈν„°νŽ˜μ΄μŠ€ μž‘μ„±κΉŒμ§€ λ‹΄λ‹Ήν–ˆμ—ˆλŠ”λ°μš”, 막상 개발이 μ‹œμž‘ν•˜κ³  보면 ν”„λ‘ νŠΈνŒ€μ—μ„œλ§Œ μΈμ§€ν• μˆ˜ μžˆλŠ” 데이터듀이 μžˆμ–΄ ν•΄λ‹Ή 정보가 λˆ„λ½λ˜κ³  개발 쀑에 변경이 λ°œμƒν•˜λŠ” 일이 μž¦μ•˜μŠ΅λ‹ˆλ‹€.

μ΄ν›„λ‘œλŠ” ν”„λ‘ νŠΈμ—”λ“œ νŒ€μ—μ„œ μΈν„°νŽ˜μ΄μŠ€ μž‘μ„±μ„ 톡해 ν•„μš”ν•œ λ°μ΄ν„°μ˜ λˆ„λ½μ„ μ΅œμ†Œν™” ν•˜κ³ , λ°±μ—”λ“œμ™€μ˜ 회의λ₯Ό 톡해 λ°±μ—”λ“œ νŒ€ λ‚΄μ—μ„œ κ΄€λ¦¬ν•˜λŠ” λ„€μ΄λ°μ΄λ‚˜ μ»¨λ²€μ…˜μ„ μ μš©μ‹œμΌœ μ΅œμ’…μ μœΌλ‘œ μΈν„°νŽ˜μ΄μŠ€κ°€ μž‘μ„±λ˜κ³  ν”„λ‘ νŠΈ νŒ€μ—μ„œλŠ” λ°±μ—”λ“œμ˜ API μž‘μ„±μ„ 기닀리지 μ•Šκ³  κ°œλ°œμ„ μ‹œμž‘ν•˜κ²Œ λ©λ‹ˆλ‹€.

μ•„λž˜λŠ” 저희가 κ°œλ°œμ‹œ μ‚¬μš©λ˜μ—ˆλ˜ μΈν„°νŽ˜μ΄μŠ€μ˜ μΌλΆ€μΈλ°μš”, μ²˜μŒμ— arti의 값은 객체가 μ•„λ‹ˆλΌ artiId, artiNameμ΄λΌλŠ” 각각의 ν‚€λ‘œ μž‘μ„±λ˜μ—ˆμ§€λ§Œ λ…Όμ˜ κ³Όμ •μ—μ„œ artiλΌλŠ” κ°μ²΄μ•ˆμ—μ„œ λ¬Άμ–΄ μ‚¬μš©ν•˜λŠ”κ±Έλ‘œ λ…Όμ˜λ˜μ–΄ λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

// GET /post/:postId
{
	id: number;
	type?: 'image' | 'video';
	arti: {
		id: string;
		name: string;
    }
}

2. Mock 데이터λ₯Ό ν†΅ν•œ 개발

ν•΄λ‹Ή μΈν„°νŽ˜μ΄μŠ€κ°€ 정해지고 λ‚˜λ©΄ ν”„λ‘ νŠΈμ—”λ“œ νŒ€μ€ ν•΄λ‹Ή μΈν„°νŽ˜μ΄μŠ€λ₯Ό 기반으둜 ν•˜λŠ” mock 데이터λ₯Ό μž‘μ„±ν•˜κ³  κ°œλ°œμ„ μ‹œμž‘ν•©λ‹ˆλ‹€. μ΄λ•Œ, ν•΄λ‹Ή 개발 λ°©μ‹μ˜ λͺ©ν‘œλŠ” μ΅œμ’… API μ—°λ™μ‹œ λ³„λ„μ˜ μž‘μ—… 없이 API μ—”λ“œν¬μΈνŠΈμ™€ νƒ€μž…μ„ μ •μ˜ν•΄μ£ΌλŠ” μž‘μ—…λ§ŒμœΌλ‘œ 연동 μ™„λ£Œλ˜λŠ”κ²ƒμ„ λͺ©ν‘œλ‘œ ν•©λ‹ˆλ‹€. μ‹€μ œ μ½”λ“œλ₯Ό λ¨Όμ € ν•œλ²ˆ λ΄λ³ΌκΉŒμš”?

// post.api.ts
export type GetPostResponse = {
	id: number;
	type?: 'image' | 'video';
	arti: {
		id: string;
		name: string;
	}
}
const getPost = ({postId}: {postId: number}) => {
	return fetch<GetPostResponse>({ baseUrl: `/post/${postId}`});
}
// post.vo.ts
export class PostVo {
	id: number;
	type: 'text' | 'image' | 'video';
	arti: {
		id: string;
		name: string;
	}

	static from(response: GetPostResponse) {
		return new PostVo(response);
	}

	constructor(response: GetPostResponse) {
		this.id = response.id;
		this.type = response.type ?? 'text';
		this.arti = response.arti;
	}
}
// post.query.ts
const useGetPost = (postId: number) => {
	return useQuery({
        queryKey: ['getPost'],
        queryFn: () => {
	        getPost({postId}).then(PostVo.from)
        }
    })
}

μ΄λŸ¬ν•œ νλ¦„μ˜ μ½”λ“œλ₯Ό μ €ν¬λŠ” μž‘μ„±ν•˜κ³  μžˆλŠ”λ°, api.tsλŠ” ν•΄λ‹Ή api의 ν˜ΈμΆœμ„ μœ„ν•œ μ½”λ“œμ΄κ³  query.tsλŠ” react-queryλ₯Ό μ‚¬μš©ν•˜λŠ” λΆ€λΆ„μœΌλ‘œ λ‚˜λ¦„ μ΅μˆ™ν•œ μ½”λ“œλΌκ³  μƒκ°ν•˜μ§€λ§Œ vo.ts νŒŒμΌμ€ 쑰금 μƒμ†Œν•œ κ°œλ…μ΄λΌκ³  μƒκ°ν•©λ‹ˆλ‹€.
저희가 μ‚¬μš©ν•˜λŠ” vo.ts νŒŒμΌμ€ DB에 μ–΄λŠμ •λ„ 의쑴적인 API의 리턴 νƒ€μž…μ„ ν”„λ‘ νŠΈμ—μ„œ 더 μž…λ§›μ— 맞좰 μ‚¬μš©ν•˜κΈ° μœ„ν•œ 컨버터 κ°œλ…μœΌλ‘œ μ΄ν•΄ν•΄μ£Όμ‹œλ©΄ 쒋을것 κ°™μŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, μœ„μ—μ„œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν• λ•Œ typeμ΄λΌλŠ” ν‚€μ˜ νƒ€μž…μ€ image, video 두가지 ν˜•μ‹λ§Œ κ°€μ§ˆμˆ˜ μžˆλŠ”λ° voμ—μ„œλŠ” ν•΄λ‹Ή 값이 μ—†μ„λ•Œ textλΌλŠ” κ°’μœΌλ‘œ λ³€κ²½ν•˜μ—¬ μ‚¬μš©ν•˜κ³  μžˆλŠ”κ±Έ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” 사싀 type이 undefined μΌλ•Œ text ν˜•μ‹μ˜ 데이터가 λ„˜μ–΄μ˜€κΈ°λ‘œ λ˜μ–΄ μžˆμ—ˆκ³  ν”„λ‘ νŠΈμ—μ„œ 가독성을 더 μ±™κΈ°κΈ° μœ„ν•΄μ„œ ν•΄λ‹Ή 데이터λ₯Ό ν•œλ²ˆ 더 가곡해주고 μžˆλŠ” κ²ƒμž…λ‹ˆλ‹€.

덕뢄에 μ €ν¬λŠ” μ•„λž˜μ²˜λŸΌ 가독성이 ν–₯μƒλœ 개발이 κ°€λŠ₯ν•΄μ‘ŒμŠ΅λ‹ˆλ‹€.
μ™œ type이 μ—†λŠ”λ° text μ—°κ΄€ 둜직이 λ‚˜μ˜€λ‚˜μš”? κ°€ μ•„λ‹ˆλΌ type에 λ§žλŠ” text μ—°κ΄€ 둜직이 λ‚˜μ˜€λŠ”κ΅¬λ‚˜! 라고 μƒκ°ν• μˆ˜ μžˆμ–΄μ§„κ²ƒμž…λ‹ˆλ‹€.

// X
if (!type) {
	// text μ—°κ΄€ 둜직 및 UI
}

// O
if (type === 'text') {
	// text μ—°κ΄€ 둜직 및 UI
}

3. μ‹€ APIμ™€μ˜ 연동

저희가 2λ²ˆμ—μ„œ μ„€λͺ…λ“œλ¦° λ°©μ‹μœΌλ‘œ κ°œλ°œμ„ μ§„ν–‰ν•˜κ³  있으면 λ°±μ—”λ“œνŒ€μ—μ„œ 개발 μ™„λ£Œμ— λŒ€ν•œ μ•Œλ¦Όμ΄ μ˜΅λ‹ˆλ‹€.

음.. 그런데 μ–΄μ°¨ν”Ό λ°°ν¬ν–ˆμœΌλ©΄, ν•΄λ‹Ή μΈν„°νŽ˜μ΄μŠ€ κΈ°μ€€μœΌλ‘œ μž‘μ„±μ΄ λ˜μ—ˆμ„ν…Œκ³  ν”„λ‘ νŠΈμ—μ„œ ν•΄λ‹Ή 정보 κΈ°μ€€μœΌλ‘œ ν˜ΈμΆœν•˜λ©΄ λ˜λŠ” 일인데 μ™œ 배포 λ²„μ „κΉŒμ§€ 곡유λ₯Ό ν•΄μ£Όμ‹œλŠ” κ±ΈκΉŒμš”?
그건 λ°”λ‘œ λ°±μ—”λ“œμ—μ„œ ν•΄λ‹Ή publishλ₯Ό ν†΅ν•΄μ„œ API의 νƒ€μž…μ„ 같이 λ„˜κ²¨μ£ΌκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

저희 λ°±μ—”λ“œμ—μ„œλŠ” nestjs + typescriptλ₯Ό μ΄μš©ν•˜μ—¬ κ°œλ°œμ„ μ§„ν–‰ν•˜κ³  μžˆλŠ”λ° ν”„λ‘ νŠΈμ™€ 같이 νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μ‚¬μš©ν•˜κ³  μžˆλ‹€λ³΄λ‹ˆ, λ°±μ—”λ“œκ°€ μ •μ˜ν•œ νƒ€μž…μ„ λ°°ν¬ν•˜κ³  μ €ν¬μ—κ²Œ κ³΅μœ ν•΄μ£ΌλŠ”κ±Έλ‘œ μ €ν¬λŠ” κ·Έ νƒ€μž…μ„ κ°„λ‹¨νžˆ λ°›μ•„μ„œ μ‚¬μš©ν• μˆ˜ 있게 λ©λ‹ˆλ‹€.

κ°„λ‹¨νžˆ μœ„μ—μ„œ μ •μ˜ν–ˆλ˜ api.ts 파일이 μ•„λž˜μ²˜λŸΌ λ°”λ€Œκ²Œ λ©λ‹ˆλ‹€.

// post.api.ts

// before
export type GetPostResponse = {
	id: number;
	type?: 'image' | 'video';
	arti: {
		id: string;
		name: string;
	}
}
const getPost = ({postId}: {postId: number}) => {
	return fetch<GetPostResponse>({ baseUrl: `/post/${postId}`});
}

// after
import {GetPostResponse} from '@knowmerce/fromm-channel-post';

const getPost = ({postId}: {postId: number}) => {
	return fetch<GetPostResponse>({ baseUrl: `/post/${postId}`});
}

ν•΄λ‹Ή 방식을 μ‚¬μš©ν–ˆμ„λ•Œ λŠκ»΄μ§€λŠ” μž₯μ μœΌλ‘œλŠ”

  • λ°±μ—”λ“œκ°€ μ „λ‹¬ν•΄μ£ΌλŠ” νƒ€μž…μ„ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— νœ΄λ¨Όμ—λŸ¬λ‘œ μΈν•œ νƒ€μž… μ˜€μ°¨κ°€ λ°œμƒν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
  • λ°±μ—”λ“œκ°€ λ°°ν¬μ‹œ μ „λ‹¬ν•΄μ£ΌλŠ” 버전을 톡해 νƒ€μž…μ„ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— λ°±μ—”λ“œ λ‚΄λΆ€μ—μ„œ λ²„μ „μ΄λ‚˜ νƒ€μž…μ˜ 변경에 영ν–₯을 λ°›μ§€μ•ŠμŠ΅λ‹ˆλ‹€.
  • ν•΄λ‹Ή λ²„μ „μ—μ„œ λ³€κ²½λœ νƒ€μž…μ΄ μžˆλ‹€λ©΄ μ–΄λ””μ„œ μ—λŸ¬κ°€ λ°œμƒν•˜κ³  μžˆλŠ”μ§€ λ°”λ‘œλ°”λ‘œ μΈμ§€ν• μˆ˜ μžˆμ–΄ λ³€κ²½λœ 뢀뢄을 λΉ λ₯΄κ²Œ μ μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

마무리

이처럼 저희 νŒ€μ€ ν”„λ‘ νŠΈμ—”λ“œμ™€ λ°±μ—”λ“œ κ°„μ˜ 효율적인 ν˜‘μ—…κ³Ό 개발 속도 ν–₯상을 μœ„ν•΄ μΈν„°νŽ˜μ΄μŠ€ μž‘μ„±λΆ€ν„° Mock 데이터 ν™œμš©, VO νŒ¨ν„΄ λ„μž…, 그리고 νƒ€μž…μŠ€ν¬λ¦½νŠΈ 기반의 νƒ€μž… κ³΅μœ κΉŒμ§€ 일련의 ν”„λ‘œμ„ΈμŠ€λ₯Ό μ²΄κ³„μ μœΌλ‘œ κ΄€λ¦¬ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

μ΄λŸ¬ν•œ 방식은 데이터 λˆ„λ½μ΄λ‚˜ νƒ€μž… 뢈일치둜 μΈν•œ 였λ₯˜λ₯Ό μ΅œμ†Œν™”ν•˜κ³ , 개발 초기 단계뢀터 λͺ…ν™•ν•œ 기쀀을 μ„Έμ›Œ 효율적인 ν˜‘μ—… ν™˜κ²½μ„ μ‘°μ„±ν•˜λŠ” 데 큰 도움을 μ£Όκ³  μžˆμŠ΅λ‹ˆλ‹€.

이 글이 μ—¬λŸ¬λΆ„μ˜ ν˜‘μ—…κ³Ό API 톡신 및 νƒ€μž… 관리에 μ°Έκ³ κ°€ 되기λ₯Ό λ°”λžλ‹ˆλ‹€!

← λͺ©λ‘μœΌλ‘œ λŒμ•„κ°€κΈ°

Art Changes Life

λ…Έλ¨ΈμŠ€μ™€ ν•¨κ»˜ μ—”ν„°ν…Œν¬ 산업을 ν˜μ‹ ν•΄λ‚˜κ°ˆ 멀버λ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€.

μ±„μš© 쀑인 곡고 보기