REST API λ””μžμΈ 15가지 팁

2022. 5. 13. 15:09γ†πŸŒ Web

μ‚¬μ΄λ“œ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λ©΄μ„œ μ˜¬λ°”λ₯Έ REST API λ””μžμΈμ„ μˆ™μ§€ν•΄μ•Όκ² λ‹€κ³  느껴 μ•„λž˜ 포슀트λ₯Ό λ²ˆμ—­ν•˜κ²Œ λμŠ΅λ‹ˆλ‹€ (약간에 μ˜μ—­μ΄ μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€)

μ˜€νƒ€λ‚˜ μ˜€μ—­μ΄ μžˆμ„ 경우 λŒ“κΈ€λ‘œ μ•Œλ €μ£Όμ‹œλ©΄ λΉ λ₯΄κ²Œ μˆ˜μ •ν•˜λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

 

 

15 fundamental tips on REST API design

REST APIs are one of the most common types of web services available, but they’re also hard to design. They allow various clients including…

medium.com

 

REST API λŠ” κ°€μž₯ 일반적인 μ›Ή μ„œλΉ„μŠ€ λ””μžμΈμœΌλ‘œ μ•Œλ €μ Έ μžˆμ§€λ§Œ λ™μ‹œμ— μ„€κ³„ν•˜κΈ° μ–΄λ €μš΄ νŠΉμ§•λ„ μžˆλ‹€.

λΈŒλΌμš°μ €, λ°μŠ€ν¬ν†± μ•±, λͺ¨λ°”일 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 및 기본적으둜 인터넷이 μ—°κ²°λœ λͺ¨λ“  μž₯치의 ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ REST API둜 μ„œλ²„μ™€ 톡신할 수 μžˆλ‹€. λ•Œλ¬Έμ— μ—λŸ¬κ°€ λ°œμƒν•˜μ§€ μ•Šλ„λ‘ REST API λ₯Ό μ œλŒ€λ‘œ μ„€κ³„ν•˜λŠ” 것이 맀우 μ€‘μš”ν•˜λ‹€.

 

 κΈ°λ³Έμ μΈ λ³΄μ•ˆ, μ˜¬λ°”λ₯Έ HTTP λ©”μ„œλ“œ μ‚¬μš©, 인증 κ΅¬ν˜„, λ‹€μ–‘ν•œ μš”μ²­ 및 응닡 μ²˜λ¦¬κΉŒμ§€ λͺ¨λ“  것을 κ³ λ €ν•˜λ©΄  API λ₯Ό μ²˜μŒλΆ€ν„° λ§Œλ“œλŠ” 것은 μ‰¬μš΄ 일이 μ•„λ‹ˆλ‹€. 이번 ν¬μŠ€νŒ…μ—μ„œ 쒋은 API λ₯Ό λ§Œλ“€ 수 μžˆλŠ” 15가지 ν•­λͺ©μ„ μ†Œκ°œν•˜κ² λ‹€., 이 방법듀은 언어에 ꡬ애받지 μ•ŠμœΌλ©° λͺ¨λ“  ν”„λ ˆμž„μ›Œν¬μ™€ κΈ°μˆ μ— 적용될 수 μžˆμŒμ„ λ°νžŒλ‹€.

 

1. endpoint 에 λͺ…사λ₯Ό μ‚¬μš©ν•  것.

URL 경둜(μ—”λ“œν¬μΈνŠΈ)λ₯Ό μ„€μ •ν•  땐 ν΄λΌμ΄μ–ΈνŠΈκ°€ μ‘°νšŒν•˜κ³ μž ν•˜λŠ” μ—”ν‹°ν‹°(λͺ…사)λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•˜λ©°, 항상 λ³΅μˆ˜ν˜•μœΌλ‘œ μ§€μ •ν•΄μ•Όν•œλ‹€. HTTP μš”μ²­ λ©”μ„œλ“œ μžμ²΄κ°€ 동사λ₯Ό λ‚˜νƒ€λ‚΄κΈ°μ— URL에 λ™μ‚¬ν˜•μ€ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€.

κ°€μž₯ 일반적으둜 μ‚¬μš©λ˜λŠ” HTTP λ©”μ„œλ“œλŠ” GET, POST, PATCH, PUT, DELETE둜 REST API 의 ν–‰μœ„λŠ” λ°˜λ“œμ‹œ HTTP λ©”μ„œλ“œμ—μ„œ λ“œλŸ¬λ‚˜μ•Όν•œλ‹€.

  • GET :  λ¦¬μ†ŒμŠ€λ₯Ό μ‘°νšŒν•œλ‹€.
  • POST : μƒˆλ‘œμš΄ 데이터λ₯Ό μ„œλ²„μ— 보낸닀.
  • PUT/PATCH : κΈ°μ‘΄ 데이터λ₯Ό μ—…λ°μ΄νŠΈ ν•œλ‹€.
  • DELETE : 데이터λ₯Ό μ œκ±°ν•œλ‹€.

μ΄λŸ¬ν•œ 원칙을 μ—Όλ‘ν•΄μ„œ, μ±… λͺ©λ‘μ„ μ‘°νšŒν•  땐 GET/books 같은 경둜λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•œλ‹€. λ§ˆμ°¬κ°€μ§€λ‘œ POST /booksλŠ” μƒˆ 책을 μΆ”κ°€ν•˜κΈ° μœ„ν•œ μ—”λ“œν¬μΈνŠΈλ©°, PUT /books/:idλŠ” μ§€μ •λœ id둜 전체 μ±… 데이터λ₯Ό μ—…λ°μ΄νŠΈ, PATCH /books/:idλŠ” μ±…μ˜ 뢀뢄적인 λ³€κ²½ 사항을 μ—…λ°μ΄νŠΈν•œλ‹€. λ§ˆμ§€λ§‰μœΌλ‘œ, DELETE /books/:idλŠ” μ§€μ •λœ id의 λ¦¬μ†ŒμŠ€λ₯Ό μ‚­μ œν•œλ‹€.

 

μœ„μ˜ 원칙을 μ—Όλ‘ν•˜μ—¬ books μ—”ν‹°ν‹°λ₯Ό μ‘°νšŒν•΄λ³΄μž.

GOOD : GET /books 

BAD : GET /get-books 

 

λ§ˆμ°¬κ°€μ§€λ‘œ, λ‹€λ₯Έ HTTP λ©”μ„œλ“œλ„ μ•„λž˜μ²˜λŸΌ μ •μ˜ν•  수 μžˆλ‹€.

POST : POST /books

PUT : PUT /books/:id

PATCH : PATCH /books/:id

DELETE : DELETE /books/:id

 

μ‹€μ œλ‘œ μ €λŠ” μ‚¬μ΄λ“œ ν”„λ‘œμ νŠΈμ—μ„œ post λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” λŒ€μ‹  GET λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄μ„œ end-point λ₯Ό /save-store 라고 μ§“λŠ” μ–΄μ²˜κ΅¬λ‹ˆ μ—†λŠ” μ‹€μˆ˜λ₯Ό ν•˜κΈ°λ„ ν–ˆμŠ΅λ‹ˆλ‹€..

 

2. 데이터 전솑 포맷: JSON (JavaScript Object Notification)

 λͺ‡ λ…„ μ „κΉŒμ§€λ§Œ 해도 API μš”μ²­/응닡 μž‘μ—…μ—λŠ” λŒ€λΆ€λΆ„ XML이 μ‚¬μš©λλ‹€. μš”μ¦˜μ€ JSON 이 λŒ€λΆ€λΆ„μ˜ ν”„λ‘œκ·Έλž¨μ—μ„œ API 데이터λ₯Ό μ „μ†‘ν•˜λŠ” ν‘œμ€€ ν˜•μ‹μ΄ 됐닀.

μ—”λ“œν¬μΈνŠΈμ˜ μ‘λ‹΅μœΌλ‘œ JSON 데이터 ν˜•μ‹μ„ λ°˜ν™˜ν•˜κ³ , λ§ˆμ°¬κ°€μ§€λ‘œ HTTP 의 νŽ˜μ΄λ‘œλ“œλ₯Ό 톡해 정보λ₯Ό μš”μ²­ν•  λ•Œλ„ JSON ν˜•μ‹μ„ μ‚¬μš©ν•œλ‹€.

 

ν΄λΌμ΄μ–ΈνŠΈ μΈ‘μ—μ„œ νŒŒμΌμ„ 보낼 κ²½μš°μ—” Form data λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹μ§€λ§Œ, ν…μŠ€νŠΈμ™€ 숫자λ₯Ό λ³΄λ‚΄λŠ”λ°μ—” Form Data κ°€ ꡳ이 ν•„μš”ν•˜μ§€ μ•Šλ‹€. λŒ€λΆ€λΆ„μ˜ ν”„λ ˆμž„μ›Œν¬κ°€ ν΄λΌμ΄μ–ΈνŠΈ μΈ‘μ—μ„œ JSON 을 직접 전솑할 수 있기 λ•Œλ¬Έμ— ꡳ이 Form Data ν˜•μ‹μ„ μ‚¬μš©ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

ν΄λΌμ΄μ–ΈνŠΈ μΈ‘μ—μ„œ 데이터λ₯Ό 전솑할 땐, JSON 데이터λ₯Ό μ˜¬λ°”λ₯΄κ²Œ 해석할 수 μžˆλ„λ‘ 응닡 ν—€λ”μ˜ Content-Type을 application/json으둜 μ„€μ •ν•΄μ•Ό ν•œλ‹€. ν¬μŠ€νŠΈλ§¨μ—μ„œ ν…ŒμŠ€νŠΈμš©λ„λ‘œ api 톡신을 ν•  λ•Œ reqeust header μ—μ„œ 이λ₯Ό 확인할 수 μžˆλ‹€.

 

3. μ μ ˆν•œ HTTP μƒνƒœ μ½”λ“œ

μš”μ²­μ˜ 성곡/μ‹€νŒ¨λ₯Ό λ‚˜νƒ€λ‚΄κΈ° μœ„ν•΄ HTTP μƒνƒœ μ½”λ“œλ₯Ό 항상 μ‚¬μš©ν•΄μ•Όν•œλ‹€. (λΉ„μ¦ˆλ‹ˆμŠ€ 정책에 따라 λ””ν…ŒμΌν•œ μƒνƒœ μ½”λ“œκ°€ μ˜λ―Έν•˜λŠ” 것은 λ‹¬λΌμ§ˆ 수 μžˆμŒμ„ μΈμ§€ν•˜μž). μƒνƒœμ½”λ“œμ˜ μ˜λ―ΈλŠ” μ•„λž˜μ²˜λŸΌ μ‚¬μš©ν•  수 μžˆλ‹€

 

200 : 톡신 성곡

201 : 생성 성곡

400 : ν΄λΌμ΄μ–ΈνŠΈ 츑의 잘λͺ»λœ 경둜 μš”μ²­

401 : μΈμ¦λ˜μ§€ μ•Šμ€ μš”μ²­(μ‚¬μš©μž)

403: μΈκ°€λ˜μ§€ μ•Šμ€ μš”μ²­(μ‚¬μš©μž)

404 : NOT FOUND

429: λ„ˆλ¬΄ λ§Žμ€ μš”μ²­

5xx : μ„œλ²„ μ—λŸ¬λ₯Ό 의미

 

κ²½μš°μ— 따라 더 λ‹€μ–‘ν•œ μƒνƒœμ½”λ“œκ°€ μžˆμ§€λ§Œ, μƒνƒœ μ½”λ“œ λ²”μœ„μ— μ œν•œμ„ 두면  ν΄λΌμ΄μ–ΈνŠΈκ°€ 보닀 예츑 κ°€λŠ₯ν•œ APIλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

 

4. ν‘œμ€€ν™”λœ λ©”μ‹œμ§€λ₯Ό λ°˜ν™˜ν•˜λΌ

μœ μ‚¬ν•œ μ—”λ“œ ν¬μΈνŠΈμ— λŒ€ν•΄ 항상 ν‘œμ€€ν™”λœ 응닡을 μ‚¬μš©ν•΄μ•Ό ν•œλ‹€. ν΄λΌμ΄μ–ΈνŠΈλŠ” λ™μΌν•œ ꡬ쑰의 응닡 ν˜•μ‹μ„ κΈ°λŒ€ν•˜λ©° 그에 따라 행동할 수 μžˆλ‹€. μ΄λŠ” 정상 응닡 뿐 만 μ•„λ‹ˆλΌ, 였λ₯˜ λ©”μ‹œμ§€μ—λ„ μ μš©λœλ‹€. μ»¬λ ‰μ…˜ ꡬ쑰λ₯Ό μ‘°νšŒν•˜λŠ” κ²½μš°μ—” response 본문에 μ•„λž˜μ²˜λŸΌ νŠΉμ •ν•œ ꡬ쑰λ₯Ό μœ μ§€ν•˜λ„λ‘ 응닡 포맷을 ν‘œμ€€ν™” ν•œλ‹€.

μ•„λž˜μ˜ 두 방법 쀑 μ–΄λŠκ²ƒμ„ μ‚¬μš©ν•˜λ“ , ν•˜λ‚˜μ˜ ν‘œμ€€ν™”λœ ν˜•μ‹μ„ μœ μ§€ ν•΄μ•Όν•œλ‹€.

// array of data
[
  {
     bookId: 1,
     name: "The Republic"
  },
  {
     bookId: 2,
     name: "Animal Farm"
  }
]


// Or like this
{
   "data":
	// array of data
      [ 
         {
           "bookId": 1,
           "name": "The Republic"
         },
         {
           "bookId": 2,
           "name": "Animal Farm"
         }
       ],
   "totalDocs": 200,
   "nextPageId": 3
}

 

 

// POST /books μš”μ²­μ΄ μ„±κ³΅μ μœΌλ‘œ λ°˜ν™˜λμ„ λ•Œ
 {
     "bookId": 3,
     "name": "Brave New World"
 }

큰 λ¬Έμ œλŠ” μ•„λ‹ˆμ§€λ§Œ "Book Successfully created" 같은 λ©”μ‹œμ§€λ₯Ό λ°˜ν™˜ν•˜λŠ” 것은, HTTP μƒνƒœ μ½”λ“œμ— 이미 ν•¨μΆ•λœ 의미λ₯Ό μ€‘λ³΅ν•΄μ„œ ν‘œν˜„ν•˜λŠ” 것과 κ°™λ‹€.

 

 

{
  "code": "book/not_found",
  "message": "A book with the ID 6 could not be found"
}

λ°˜λ³΅ν•΄μ„œ λ§ν•˜μžλ©΄, 응닡 λ‚΄μš©μ— μƒνƒœ μ½”λ“œλ₯Ό λ°˜λ“œμ‹œ λ„£μ–΄μ•Ό ν•  ν•„μš”λŠ” μ—†μ§€λ§Œ book/not_found와 같은  자체 였λ₯˜ μ½”λ“œλ₯Ό μ •μ˜ν•˜λŠ” 것은 ν΄λΌμ΄μ–ΈνŠΈ μž…μž₯μ—μ„œλŠ” 맀우 μœ μš©ν•˜λ‹€. 특히 개발 ν™˜κ²½μ—μ„œλŠ” μ—λŸ¬ μŠ€νƒμ„ 응닡에 ν¬ν•¨μ‹œμΌœ 버그λ₯Ό 디버깅 ν•˜λŠ” 것이 μ μ ˆν•  수 μžˆλ‹€. λ¬Όλ‘  ν”„λ‘œλ•μ…˜ ν™˜κ²½μ—μ„œλŠ” μ—λŸ¬ μŠ€νƒμ„ λ…ΈμΆœ μ‹œν‚΄μœΌλ‘œ λ³΄μ•ˆ 문제λ₯Ό μ΄ˆλž˜ν•  수 μžˆμœΌλ―€λ‘œ μ΄λŸ¬ν•œ 정보λ₯Ό λ°°μ œν•΄μ•Ό ν•œλ‹€.

 

5. 응닡 κ°’μœΌλ‘œ μ»¬λ ‰μ…˜μ„ λ°›μœΌλ©΄ νŽ˜μ΄μ§•κ³Ό 필터링, μ •λ ¬ 처리λ₯Ό ν•΄μ•Όν•œλ‹€. 

 

응닡 κ°’μœΌλ‘œ 리슀트λ₯Ό λ°›λŠ” endpoint λ₯Ό 섀계할 땐 νŽ˜μ΄μ§• 처리λ₯Ό ν•΄μ€˜μ•Ό ν•œλ‹€. μ‹œμŠ€ν…œμ΄ λ°œμ „ν•¨μ— 따라 μ»¬λ ‰μ…˜ 값도 규λͺ¨κ°€ 점차 컀지기 λ•Œλ¬Έμ—, 항상 정해진 μ–‘μ˜ 데이터λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ μ œμ–΄ν•΄μ•Ό ν•œλ‹€. λ¬Όλ‘  ν΄λΌμ΄μ–ΈνŠΈ μΈ‘μ—μ„œ 전달받을 λ°μ΄ν„°μ˜ 규λͺ¨λ₯Ό μ •ν•˜λŠ” 것이 κ³΅μ •ν•˜κ² μ§€λ§Œ, API μΈ‘μ—μ„œ 미리 κ·Έ 규λͺ¨μ™€ μ΅œλŒ€ 값을 κ·œμ •ν•΄ λ‘λŠ” 것이 μ’‹λ‹€. 이런 νŽ˜μ΄μ§• 처리λ₯Ό ν•˜λŠ” μ΄μœ λŠ”, λ°©λŒ€ν•œ μ–‘μ˜ 데이터 배열을 λ°˜ν™˜ν•˜λŠ” 데 λ§Žμ€ μ‹œκ°„κ³Ό λŒ€μ—­ν­μ΄ μ†Œλͺ¨λ˜κΈ° λ•Œλ¬Έμ΄λ‹€ .

 

skip/limit κ³Ό keyset 이 λŒ€ν‘œμ μΈ νŽ˜μ΄μ§• 처리 기법이닀. skip/limit μ˜΅μ…˜μ€ 데이터λ₯Ό κ°€μ Έμ˜€λŠ” μ΅μˆ™ν•œ 방법에 μ†ν•˜μ§€λ§Œ, ν…Œμ΄λΈ” ν›„λ°˜λΆ€μ— μœ„μΉ˜ν•œ 데이터λ₯Ό κ°€μ Έμ˜¬ 땐 μ‹œκ°„μ΄ 많이 μ†Œλͺ¨λ˜κΈ° λ•Œλ¬Έμ— 일반적으둜 μ„±λŠ₯이 떨어진닀. 반면 keyset νŽ˜μ΄μ§• 기법은 μ‹λ³„μž/IDλ₯Ό μ°Έμ‘°κ°’μœΌλ‘œ λ°›μ•„ λ¦¬μŠ€νŠΈλ‚˜ ν…Œμ΄λΈ”μ„ μŠ€μΊ”ν•  ν•„μš”μ—†μ΄ 쑰건에 따라 데이터λ₯Ό νŽ˜μ΄μ§•ν•  수 μžˆλ‹€.

 

λ™μΌν•œ μΈ‘λ©΄μ—μ„œ, API λŠ” 데이터λ₯Ό μ‘°νšŒν•  λ•Œ 필터와 μ •λ ¬ κΈ°λŠ₯도 μ œκ³΅ν•΄μ•Ό ν•œλ‹€. μ„±λŠ₯ ν–₯상을 μœ„ν•΄ DB μΈλ±μŠ€λŠ” 필터와 정렬을 톡해 μ μš©λ˜λŠ” Access νŒ¨ν„΄μ„ μ‚¬μš©ν•˜κΈ°λ„ ν•œλ‹€. APIλ₯Ό 섀계할 λ•Œ 필터와 정렬은 쿼리 νŒŒλΌλ―Έν„°μ— μ •μ˜λœλ‹€. 예λ₯Ό λ“€μ–΄ "romance" 범주에 μ†ν•˜λŠ” 초기 10ꢌ의 책을 μ‘°νšŒν•˜λ €λ©΄ μ—”λ“œν¬μΈνŠΈλŠ” μ•„λž˜μ²˜λŸΌ μ„€κ³„ν•΄μ•Όν•œλ‹€.

GET /books?limit=10&category=romance

 

6. PUT λŒ€μ‹  PATCH 을 μ‚¬μš©ν•˜λΌ .

μ—”ν‹°ν‹°μ˜ λͺ¨λ“  μƒνƒœκ°’μ„ ν•œλ²ˆμ— μˆ˜μ •ν•˜λŠ” 일은 ν”νžˆ μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€. λ˜ν•œ ν΄λΌμ΄μ–ΈνŠΈκ°€ μˆ˜μ •ν•˜μ§€ λͺ»ν•˜κ²Œ μœ μ§€ν•˜κ³  싢은 λ³΅μž‘ν•˜κ±°λ‚˜ λ―Όκ°ν•œ 데이터도 μ‘΄μž¬ν•˜κΈ° λ§ˆλ ¨μ΄λ‹€. PUT λ©”μ„œλ“œλŠ” λ¦¬μ†ŒμŠ€μ˜ λͺ¨λ“  μš”μ†Œλ₯Ό μˆ˜μ •ν•΄λ²„λ¦¬κΈ° λ•Œλ¬Έμ—, λ°μ΄ν„°μ˜ 뢀뢄적인 μˆ˜μ •μ΄ ν•„μš”ν•  땐 PATCH λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€. 두 λ©”μ„œλ“œ λͺ¨λ‘ μ—…λ°μ΄νŠΈ ν•΄μ•Όν•˜λŠ” 정보λ₯Ό HTTP Body 에 λ‹΄μ•„ λ³΄λ‚΄μ•Όν•œλ‹€.

ν•˜μ§€λ§Œ κ·Έλ ‡λ‹€κ³  ν•˜μ—¬ λΆ€λΆ„ μ—…λ°μ΄νŠΈλ₯Ό ν•  λ•Œ PUT λ©”μ„œλ“œλ₯Ό μ•„μ˜ˆ μ‚¬μš©ν•˜μ§€ 말라고 κ°•μ œν•  μˆ˜λ„ μ—†λŠ” 노릇이닀. 정해진 "λ„€νŠΈμ›Œν¬ 전솑 μ œν•œ" κ·œλ²”μ΄ μžˆλŠ” 것도 μ•„λ‹ˆλ©°, κ·Έμ € PATCH λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 쒋은 방법이라 ꢌμž₯될 뿐이닀. 

 

7. ν™•μž₯된 응닡 μ˜΅μ…˜μ„ μ œκ³΅ν•˜λΌ. 

μ‹œμŠ€ν…œμ΄ ν™•μž₯됨에 따라, 응닡 κ°’μ˜ ν”„λ‘œνΌν‹°κ°€ λŠ˜μ–΄λ‚  수 도 μžˆμ§€λ§Œ, ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ λͺ¨λ“  ν”„λ‘œνΌν‹°κ°€ ν•„μš”ν•˜μ§€ μ•Šμ„ 수 μžˆλ‹€. 이런 κ²½μš°μ—λŠ” λ™μΌν•œ μ—”λ“œν¬μΈνŠΈμ— 

1) ν•„μš”ν•œ ν”„λ‘œνΌν‹°λ§Œ μ œκ³΅ν•˜λŠ” μΆ•μ†Œλœ 응닡 포맷을 λ‚΄λ €μ£Όκ±°λ‚˜ 

2) μΆ•μ†Œν•˜μ§€ μ•Šμ€ κΈ°μ‘΄ 응닡 포맷을 λ‚΄λ¦¬λŠ”

2가지 μ„ νƒκΆŒμ„ 쀄 수 μžˆλ‹€.

ν΄λΌμ΄μ–ΈνŠΈκ°€ 응닡 κ°’μ˜ μΌλΆ€λ§Œ ν•„μš”λ‘œ ν•  땐, κ°„λž΅ν™”λœ 응닡 포맷을 λ‚΄λ¦¬λŠ” 것이 λŒ€μ—­ν­ λ‚­λΉ„λ₯Ό 쀄일 수 μžˆλ‹€.

μ•„λž˜ μ˜ˆμ‹œμ²˜λŸΌ exteneded λΌλŠ” μΆ”κ°€ 쿼리λ₯Ό 맀개 λ³€μˆ˜λ‘œ μ œκ³΅ν•˜λ©΄ ν™•μž₯된 응닡 μ œκ³΅μ„ μ‰½κ²Œ ν™œμ„±/λΉ„ν™œμ„±ν™” ν•  수 μžˆλ‹€.

GET /books/:id
{
   "bookId": 1,
   "name": "The Republic"
}
GET /books/:id?extended=true
{
   "bookId": 1,
   "name": "The Republic"
   "tags": ["philosophy", "history", "Greece"],
   "author": {
      "id": 1,
      "name": "Plato"
   }
}

 

8. μ—”λ“œν¬μΈνŠΈμ˜ μ±…μž„μ„ μƒκ°ν•˜λΌ

API κ°€ ν•˜λ‚˜μ˜ μž‘μ—…μ„ 잘 μˆ˜ν–‰ν•˜λŠ” λ™μ‹œμ— λ³€ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄,  ν•΄λ‹Ή APIλŠ” 잘 μ„€κ³„λœ 것이라 ν•  수 μžˆλ‹€. 잘 μ„€κ³„λœ API λŠ” ν΄λΌμ΄μ–ΈνŠΈκ°€ API λ₯Ό μ‰½κ²Œ μ΄ν•΄ν•˜κ³ , μ „λ°˜μ μΈ 톡합을 μš©μ΄ν•˜κ²Œ ν•˜μ—¬ 예츑 κ°€λŠ₯ν•˜κ²Œ λ§Œλ“ λ‹€. ν•œλ²ˆμ— λ§Žμ€ μž‘μ—…μ„ ν•΄κ²°ν•˜λŠ” λ³΅μž‘ν•œ μ—”λ“œν¬μΈνŠΈλ₯Ό κ΅¬μΆ•ν•˜λŠ” 것 보닀, μ‚¬μš© κ°€λŠ₯ν•œ μ—”λ“œν¬μΈνŠΈ λͺ©λ‘μ„ μ „μ²΄μ μœΌλ‘œ ν™•μž₯ν•˜λŠ” 것이 λ°”λžŒμ§ν•˜λ‹€. 

 

9. μ •ν™•ν•œ API λ¬Έμ„œλ₯Ό μ œκ³΅ν•˜λΌ. 

APIλ₯Ό 잘 μ •λ¦¬ν•œ λ¬Έμ„œκ°€ μžˆμ–΄μ•Ό ν΄λΌμ΄μ–ΈνŠΈλŠ” μ‚¬μš©κ°€λŠ₯ν•œ μ—”λ“œν¬μΈνŠΈλ₯Ό μ–΄λ–»κ²Œ μ‚¬μš©ν•  것이며, μ–΄λ–€ κ²°κ³Όλ₯Ό 받을 수 μžˆμ„μ§€ μ˜ˆμΈ‘ν•  수 μžˆλ‹€.

μ •λ¦¬λœ λ¬Έμ„œλ₯Ό μ œκ³΅ν•˜κΈ° μœ„ν•΄μ„  λ‹€μŒκ³Ό 같은 츑면을 κ³ λ €ν•΄μ•Ό ν•œλ‹€.

  • μ—”λ“œν¬μΈνŠΈμ˜ λͺ©μ μ„ μ„€λͺ…
  • μ—”λ“œν¬μΈνŠΈλ₯Ό μ‹€ν–‰ν•  λ•Œ ν•„μš”ν•œ κΆŒν™˜
  • 호좜 및 응닡 예제
  • 에상 였λ₯˜ λ©”μ‹œμ§€

μ‹œμŠ€ν…œμ΄ μ—…λ°μ΄νŠΈ 되고 변경될 λ•Œ λ§ˆλ‹€ API λ¬Έμ„œ μ—­μ‹œ μ—…λ°μ΄νŠΈ ν•΄μ£ΌλŠ” 것이 μ€‘μš”ν•˜λ‹€. 이λ₯Ό 지킬 수 μžˆλŠ” κ°€μž₯ 쒋은 방법은 API λ¬Έμ„œν™”λ₯Ό 개발의 기본으둜 μ‚ΌλŠ” 것이닀. Swagger와 Postman이 잘 μ•Œλ €μ§„ API λ¬Έμ„œν™” λ„κ΅¬λ‘œ λŒ€λΆ€λΆ„μ˜ API 개발 ν”„λ ˆμž„μ›Œν¬μ—μ„œ μ‚¬μš©ν•  수 μžˆλ‹€.

 

10. λ³΄μ•ˆμ„ μœ„ν•œ SSL μ‚¬μš© 및 CORS μ„€μ •

 λ³΄μ•ˆ μ—­μ‹œ APIκ°€ κ°–μΆ°μ•Ό ν•  기본적인 속성 쀑 ν•˜λ‚˜λ‹€. 

μ„œλ²„μ— μœ νš¨ν•œ μΈμ¦μ„œλ₯Ό μ„€μΉ˜ν•˜μ—¬ SSL 을 μ„€μ •ν•˜λ©΄, ν΄λΌμ΄μ–ΈνŠΈμ™€μ˜ μ•ˆμ „ν•œ 톡신을 보μž₯ν•˜κ³  λͺ‡ 가지 잠재적인 곡격을 방지할 수 μžˆλ‹€.

CORS(Cross Origin Resource Sharing) λŠ” λΈŒλΌμš°μ € λ³΄μ•ˆ κΈ°λŠ₯으둜, λΈŒλΌμš°μ €μ˜ μŠ€ν¬λ¦½νŠΈμ—μ„œ μ‹œμž‘λ˜λŠ” 크둜슀 μ˜€λ¦¬μ§„(Cross origin) HTTP μš”μ²­μ„ μ œν•œν•œλ‹€. λ³΅μž‘ν•œ 크둜슀 μ˜€λ¦¬μ§„ HTTP μš”μ²­μ„ μˆ˜μ‹ ν•˜λŠ” REST APIλŠ”, κ·Έμ— λŒ€μ‘ν•  수 μžˆλŠ” CORS 지원을 ν™œμ„±ν™” ν•΄μ•Ό ν•œλ‹€.

CORS ν”„λ‘œν† μ½œμ€ λΈŒλΌμš°μ €κ°€ μ„œλ²„μ— 사전 μš”μ²­preflight 을 보내도둝 ν•˜λ©°, μ‹€μ œ μš”μ²­μ„ 보내기 μ „κΉŒμ§€ μ„œλ²„μ˜ μŠΉμΈμ„ κΈ°λ‹€λ¦°λ‹€. 사전 μš”μ²­(preflight request)은 OPTIONS λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” HTTP μš”μ²­μ„ μ˜λ―Έν•œλ‹€. 즉 REST APIκ°€ CORS에 λŒ€μ‘ν•˜λ €λ©΄ 사전 μš”μ²­(preflight)의 OPTIONS λ©”μ„œλ“œλ₯Ό μˆ˜ν–‰ν•  수 μžˆλ„λ‘,  FETCH ν‘œμ€€μ—μ„œ μš”κ΅¬ν•˜λŠ” μ•„λž˜μ˜ 사항을 응닡 헀더에 λ„£μ–΄μ•Όν•œλ‹€.

  • Access-Control-Allow-Methods
  • Access-Control-Allow-Headers
  • Access-Control-Allow-Origin

μœ„ 3가지 key 값에 할당될 값은 API κ°€ μ–Όλ§ˆλ‚˜ 개방적이고 μœ μš©ν•œμ§€μ— 따라 달라진닀. 잘 μ•Œλ €μ§„ Origin 을 ν• λ‹Ήν•˜κ±°λ‚˜ μ™€μΌλ“œ μΉ΄λ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 방법 λ“±μœΌλ‘œ CORS λ₯Ό μ„€μ •ν•  수 μž‡λ‹€. 

 

11. API 버전

개발 ν”„λ‘œμ„ΈμŠ€μ˜ μΌν™˜μœΌλ‘œ, API μ—”λ“œν¬μΈνŠΈκ°€ λ³€κ²½λ˜κ±°λ‚˜ μž¬κ΅¬μΆ• λ˜λŠ” κ²½μš°κ°€ μžˆλ”λΌλ„, ν΄λΌμ΄μ–ΈνŠΈ 톡신을 μœ„ν•΄ κ°‘μžκΈ° μ—”λ“œν¬μΈνŠΈλ₯Ό λ³€κ²½ν•˜λŠ” 일은 ν”Όν•΄μ•Όν•œλ‹€. APIλŠ” μƒˆλ‘œμš΄ μ—”λ“œν¬μΈνŠΈκ°€ 이전 λ²„μ „μ˜ ν‘œμ€€μ— 영ν–₯을 주지 μ•ŠλŠ” ν•˜μœ„ ν˜Έν™˜ λ¦¬μ†ŒμŠ€λ‘œ μƒκ°ν•˜λŠ” 것이 λ°”λžŒμ§ν•˜λ‹€. ν΄λΌμ΄μ–ΈνŠΈλŠ” μžμ‹ μ΄ μš”μ²­ν•  API μ£Όμ†Œλ₯Ό 선택할 수 μžˆμ–΄μ•Όν•˜κ³ , μ•„λž˜μ²˜λŸΌ API 버전을 κ΄€λ¦¬ν•˜λŠ” μ—¬λŸ¬ 방법이 μžˆλ‹€ .

1. μƒˆλ‘œμš΄ 헀더 μΆ”κ°€ "x-version=v2"
2. 쿼리 νŒŒλΌλ―Έν„° μ‚¬μš© "?apiVersion=2"
3. URL의 μΌλΆ€λ‘œ 버전을 ν‘œκΈ° "/v2/books/:id"

 

12. μ„±λŠ₯ ν–₯상을 μœ„ν•œ μΊμ‹œ 데이터 ν™œμš©

API 의 μ„±λŠ₯ ν–₯상을 높이렀면 빈번히 μ‚¬μš©λ˜λ©°, μ‰½κ²Œ λ³€ν•˜μ§€ μ•ŠλŠ” 데이터λ₯Ό μΊμ‹±ν•΄λ‘λŠ” 것이 μ’‹λ‹€. μ ‘κ·Ό λΉˆλ„κ°€ 높은 데이터λ₯Ό 잘 ν™œμš©ν•˜λ €λ©΄,  인메λͺ¨λ¦¬λ‚˜ μΊμ‹œ λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ 메인 λ°μ΄ν„°λ² μ΄μŠ€μ— μ ‘κ·Όν•˜λŠ” λΉ„μš©μ„ μ€„μ΄λŠ” 방법을 κ³ λ €ν•  수 μžˆλ‹€. μΊμ‹±λœ 데이터가 outdated 될 수 μžˆμœΌλ―€λ‘œ μ΅œμ‹  μƒνƒœμ˜ λ°μ΄ν„°λ‘œ ꡐ체 ν•˜λŠ” 방법 μ—­μ‹œ κ³ λ―Όν•΄μ•Ό ν•œλ‹€.

ν΄λΌμ΄μ–ΈνŠΈ μž…μž₯μ—μ„œλŠ”, μ„€μ •μ΄λ‚˜ μΉ΄νƒˆλ‘œκ·Έ 정보 처럼 μ‹œκ°„μ΄ μ§€λ‚˜λ„ 잘 λ³€ν•˜μ§€ μ•ŠλŠ” 정보λ₯Ό μΊμ‹œ λ°μ΄ν„°λ‘œ ν™œμš©ν•˜λ©΄ 맀우 μœ μš©ν•˜λ‹€. μΊμ‹œ 데이터λ₯Ό μ‚¬μš©ν•  땐 HTTP 헀더에 Cache-Control ν”„λ‘œνΌν‹°λ₯Ό κΌ­ 포함해야 ν•œλ‹€. 

 

 

13. ν‘œμ€€ UTC μ‚¬μš©

데이터 μˆ˜μ€€μ—μ„œ ν΄λΌμ΄μ–ΈνŠΈ 츑의 λ‚ μ§œ ν‘œμ€€ 방식을 일관성 있게 보여주도둝 μœ μ§€ν•˜λŠ” 일은 μ€‘μš”ν•˜λ‹€. ISO 8601 λŠ” λ‚ μ§œ/μ‹œκ°„ λ°μ΄ν„°μ˜ ꡭ제 ν‘œμ€€ ν˜•μ‹μœΌλ‘œ, λ‚ μ§œλŠ” 'Z' λ˜λŠ” UTC ν˜•μ‹μ΄μ–΄μ•Ό ν•˜λ©°, ν΄λΌμ΄μ–ΈνŠΈλŠ” μ–΄λ–€ μ‘°κ±΄μ—μ„œλ“  ν•΄λ‹Ή λ‚ μ§œλ₯Ό ν‘œμ‹œν•΄μ•Ό ν•  경우 μ‹œκ°„λŒ€λ₯Ό κ²°μ •ν•  수 μžˆλ‹€.

λ‹€μŒμ€ λ‚ μ§œ ν˜•μ‹μ˜ μ˜ˆμ‹œλ₯Ό 보여쀀닀.

{
    "createdAt": "2022-03-08T19:15:08Z"
}

 

14. ν—¬μŠ€ 체크 μ—”λ“œν¬μΈνŠΈ

API 에 λ¬Έμ œκ°€ 생겨 λ‹€μš΄λ  λ•Œ, API λ₯Ό μž¬κ°€λ™ν•˜κ³  μ‹€ν–‰ν•˜λŠ”λ° μ‹œκ°„μ΄ 걸릴 수 μžˆλ‹€. μ΄λŸ¬ν•œ μƒν™©μ—μ„œ ν΄λΌμ΄μ–ΈνŠΈλŠ” 문제 상황을 νŒŒμ•…ν•˜κ³  그에 따라 μ„œλΉ„μŠ€λ₯Ό μ΄μš©ν•  수 μ—†λ‹€λŠ” 사싀을 μ•Œμ•„μ•Ό ν•œλ‹€.  이λ₯Ό μœ„ν•΄ API κ°€ μ •μƒμ μœΌλ‘œ λ™μž‘ν•˜λŠ”μ§€ 확인할 수 μžˆλŠ” μ—”λ“œν¬μΈνŠΈ (ex GET /health) λ₯Ό μ œκ³΅ν•΄μ•Όν•œλ‹€. 이런 μ—”λ“œν¬μΈνŠΈλŠ” λ‘œλ“œλ°ΈλŸ°μ„œ 같은 λ‹€λ₯Έ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ— μ˜ν•΄ 호좜될 수 있으며, 더 λ‚˜μ•„κ°€ API의 ν—¬μŠ€ μ²΄ν¬λ‚˜ μœ μ§€ 보수 기간을 μ•Œλ €μ€„ μˆ˜λ„ μžˆλ‹€.

 

15. API Key 인증을 ν—ˆμš©ν•˜λΌ

API key λ₯Ό ν†΅ν•œ 인증은 μ¨λ“œ νŒŒν‹° μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 우리의 API에 μ†μ‰½κ²Œ μ‚¬μš©λ˜λ„λ‘ λ§Œλ“€ 수 μžˆλ‹€. API key 값은 X-Api-Key λ‚˜ Api-Key 같은 μ»€μŠ€ν…€ HTTP 헀더λ₯Ό 톡해 전달돼야 ν•œλ‹€. Key의 만료 κΈ°ν•œ μ—­μ‹œ 지정돼야 ν•˜λ©°, λ³΄μ•ˆμƒ λ¬Έμ œκ°€ μžˆμ„ 땐 λ¬΄νš¨ν™” λ˜λ„λ‘ 해지할 수 μžˆμ–΄μ•Ό ν•œλ‹€.