김데이의 개발공부

[ TIL ] Day 48 - RESTful API 설계 원칙 / 구현 요소 / 문서화 본문

코드잇 Node.js(BE) 부트 캠프/TIL (Today I Learn) 📑

[ TIL ] Day 48 - RESTful API 설계 원칙 / 구현 요소 / 문서화

theday365 2025. 12. 2. 18:45
반응형

🗓️ 수업 일자 : 2025.12.02

✨ 오늘의 수업 평가 :  [ GOOD ]  배움이 팡팡 터진 날 🍿💡 

 

지금까지 했던 실습에 대한 이론이라서 그런가

생각보다 어렵지 않게 이해 할 수 있는 이론들이였다~

 

 

📝  오늘 배운 내용  

- RESTful API 설계 원칙

- RESTful API 구현 요소

- Swagger를 사용한 API 문서화

 

개발 이론
개발 이론


1. RESTful API 설계 원칙

- RESTful API : REST원칙을 지켜서 설계한 API 스타일

- REST : Representational State Transfer, 웹의 리소스를 명확하게 표현해서 주고 받는 방식

               POST /products = 제품 리소스를 하나 추가한다
               GET /products/51 = 아이디가 51인 제품 리소스를 확인하겠다

 

+ 추가 🤓 비슷하게 썻지만 다른 의미! 

  API : 서비스 기능 단위, 인터페이스 개념

  엔드포인트(endpoint) 또는 라우트(route) : 특정 요청을 어떤 로직으로 보낼지 정해놓은 규칙

  URL 패스(path) : 도메인 뒤에 붙는 경로 문자열, 쿼리 스트링을 포함하지 않음

  리소스 경로(Resource URI) : API에서 리소스를 식별하는 주소

 

 

REST 제약조건(로이필딩)

  1. Client - Server (클라이언트 - 서버 역할 분리)
    : 클라이언트 / 서버 각각 자신의 역할을 명확히 분리하여 독립적으로 사용 → 유지보수 편리 
  2. Stateless (무상태성)
    : 클라이언트는 상태를 저장하지 않고, 특정 작업 시 쿠키에 토큰 /세션 등을 담아 서버에 요청을 보냄.
    : 서버 역시 이전 상태를 기억하지 않고, 클라이언트가 작성 한 리퀘스트를 기반으로 필요한 모든 정보를 제공
  3. Cache(캐시) 
    : 매번 새로운 데이터를 전달하는 것 보다, 이미 전달받은 데이터를 사용하면 더욱 빠르게 서비스를 제공 할 수 있음 = 캐시
    : "캐싱"을 통해 네트워크 효율성을 높이며, 리스폰스에 이러한 "캐시 사용 가능/불가능" 여부가 들어 있어야 함
  4. Uniform Interface (일관된 인터페이스) = 실제 개발에서 가장 신경써야 할 부분
    : URL구조, 리소스 개념, HTTp 메서스 활용이 모두 일관적이어야 함
  5. Layered System (계층화 된 시스템)
    : 클라이언트는 서버에 요청할 때, 어떤 서버에 어떤 방식으로 연결 되었는지 알 수 없음.
      즉, 메인 서버에 직접 연결 되었는지 중간 서버를 통해 연결 되었는지 알 필요가 없으며, 모든 서버는 하나로 보여야 함
      → 보안, 확장성, 성능강화에 유리 
  6. Code on Demand (주문형 코드) 
    : 서버에서 보낸 코드를 클라이언트에서 실행 할 수 있어야 함
      (해당 조건은 선택적 제약 조건, 지키지 않아도 REST에는 문제 없음)

 

2. RESTful API 구현 요소

1) URI

: API에서 리소스를 가리키는 고유 경로(주소)

  • 최대한 명사로 구현 하며, 자원의 종류에 따라 단수형 / 복수형으로 사용
  • 소문자로 작성하고 띄어쓰기가 필요한 경우 '-'를 사용 
  • 계층 표현에는 슬래시 사용하고, 마지막은 슬래시를 붙이지 않음(의미가 없는 슬래시)
  • 파일 확장자는 포함하지 않고 Content-type으로 표현 해 주기 
  • 리소스 목록에 필터가 필요할 경우 쿼리 문자열을 사용하기 
⭕ GOOD ⭕
POST /members
GET  /members/52
GET  /menbers/top-group 

❌ BAD ❌
POST /create-member  : 가능하면 명사 하나로 사용
GET  /members/52/    : 마지막에 슬래시는 의미 없음, 사용하지 않음

쿼리스트링 응용하기 
❌ BAD ❌  users/123/orders/12/items/5412 -> 해석하기 복잡
⭕ GOOD ⭕ items?orderId=12&itemId=5412   -> 비교적 단순

 

 

2) 메소드

: 클라이언트가 서버에 요청을 보낼 때, HTTP 메소드를 사용하여 정확한 요청 작업 진행

  • GET : 특정 리스트 / 상세 조회 등 리소스를 조회 할 때 사용
  • POST : 신규 리소스를 생성(신규 데이터 생성) 할 때 사용
  • PUT : 저장 된 리소스 전체를 새로운 값으로 교체할 때 사용
  • PATCH : 저장 된 리소스의 일부분을 업데이트 할 때 사용
  • DELETE : 저장 된 리소스를 삭제 할 때 사용

 PUT vs PATCH 

: PUT으로 진행하면 "전체 교체(replace)"가 진행되므로, 수정 시 일부 값만 작성하여 보내면 안보낸 값은 null이 입력 됨

  반면, PATCH의 경우 "부분 수정(Partial update)"이 진행되므로, 수정 시 보낸 값만 업데이트 되어 저장 됨

product/1 
body = { name : "장갑", price: 12000 }


PUT product/1 
req.body = { name: "목도리" }
res.body = { name : "목도리", price: null } 
// 작성하지 않은 price 값에 null이 들어감

PATCH product/1 
req.body = { name: "머플러" }
res.body = { name : "머플러", price: 12000 }
// 작성하지 않은 price값은 유지됨

 

 

3) 상태코드

: 클라이언트가 서버로 부터 요청을 보냈을때, 결과로 받게되는 응답 코드 

(기존 공부했던 자료 : https://theday365.tistory.com/147)

MDN  상태 코드 자료 : https://developer.mozilla.org/ko/docs/Web/HTTP/Reference/Status

 

HTTP 상태 코드 - HTTP | MDN

이 응답은 요청을 한지 시간이 오래된 연결에 일부 서버가 전송하며, 어떨 때에는 이전에 클라이언트로부터 어떠한 요청이 없었다고 하더라도 보내지기도 합니다. 이것은 서버가 사용되지 않는

developer.mozilla.org

 

  • 1XX = 정보, 요청을 받았고 계속 처리 중
  • 2XX = 성공, 요청한 내용이 성공적으로 처리 됨
  • 3XX = 리디렉션 요청, 다른 URL 또는 다른 방식으로 요청을 재시작 해야할 때 보내는 응답.
  • 4XX = 클라이언트 오류, 즉 요청이 잘못 됨(요청하는 방식 오류)
  • 5XX = 서버 오류, 서버가 처리를 하는 도중 오류가 발생

 

 

4) 캐싱

: 이미지나 동영상 처럼 용량이 큰 데이터 또는 자주 사용하는 데이터를 임시로 저장 해 두었다가, 동일한 요청이 들어오면 저장 해 둔 데이터를 재사용 하는 기술. 주로 Header에 캐시 관련 설정을 저장 해 둠

MDN 공식 문서 : https://developer.mozilla.org/ko/docs/Web/HTTP/Reference/Headers#%EC%BA%90%EC%8B%B1

 

HTTP 헤더 - HTTP | MDN

WWW-Authenticate 리소스에 대한 접근을 하는데 사용되어야하는 인증 메소드를 정의합니다. Authorization 서버와함께 유저 에이전트를 인증하기 위한 자격 증명을 포함합니다. Proxy-Authenticate 프록시 서

developer.mozilla.org

 

헤더(Header)에서 사용하는 캐시 관련 설정

  • Cache-Control : 캐시 관련 단방향 설정값, 단순하게 얼마동안 사용 가능한지 / 몇 초 뒤에 업데이트 될지 등
                              클라이언트가 캐시를 사용하는데 필요한 간략한 정보가 들어감
                              Cache-Control: max-age=<seconds> 몇 초 동안 현재 캐시가 사용 가능함 
                              Cache-control: no-cache                     현재 요청은 사용 전 반드시 서버 검증 필요 
  • Last-Modified : Res Header / 서버가 가지고 있는 마지막 수정 일자를 클라이언트에게 전달 함 
    If-Modified-Since : Req Header / 클라이언트가 요청을 보낼 때, 가지고 있는 정보가 최신 정보인지 확인하기 위하여 
                                   서버에게 받았던 Last-Modified값을 If-Modified-Since에 담아서 보냄.
                                   두 값이 다르면 서버가 새로운 정보 전달.
  • ETag : Res Header / 날짜가 가지고 있는 한계를 넘고자, 데이터를 기반으로 한 해시 값을 서버가 만들어 클라이언트에 전달
    If-None-Match : Req Header / 클라이언트가 새로운 요청 시 서버로 부터 받은 ETag 값을 해당 헤더의 값으로 담아서 전달.
                               서버가 ETag 해시값과 If-None-Match 해시 값을 비교하고, 만약 다르다면 새로운 데이터를 전달 함  
HTTP/1.1 200 OK
Content-Type: image/png
Cache-Control: max-age=60
Last-Modified: TUE, 02 Dec 2025 00:00:00 GMT
ETag: "33a64df551425fccsdf245sd4f1cz2df4d4"

 

 

 

5) API 버저닝

 - 기능 설계를 진행하다보면 신규 버전의 API가 적용 될 필요가 있음 

    웹 : 서버에 접속하는 즉시 신규 버전 API가 바로 적용 됨

    앱 : 설치하여 서비스를 쓰기 때문에, 신규 버전의 API가 바로 적용되지 않음 
         

API 버저닝 관리 방법

  • 앱 업데이트의 경우, 사용자를 통해 강제로 업데이트 진행
    ex) 어플 접속 시 "새로운 버전이 필요합니다" 안내 멘트와 함께 업그레이드 버튼만 제공 (종료 외에 빠져 나갈 방법이 없음)
  • 기존 버전 URI /v1/users과 신규 버전인 /v2/users를 함께 운영한 뒤 일정 시간이 지나면 신규 버전만 사용
  • 쿼리 스트링으로 /users?version=2 와 같이 버전을 표기하여 사용
  • 클라이언트가 요청을 보낼 때, 사용하는 버전을 Header에 Accept-Version: 1.2으로 명시 

 

 

6) 페이지네이션 

 - 페이지네이션 : 정해진 데이터(양)가 한 페이지에 보여지고, 이후 데이터를 보기 위해서는
                           하단의 버튼 (좌/우, 숫자 등)을 통해 새로운 페이지로 이동하며 추가 데이터를 확인하는 구조 

 - 커서(cursor) : 페이지가 무한히 이어지는 것 처럼 보이는 구조. 주로 SNS 등에 적용 됨.
                         데이터의 맨 하단으로 이동하면, 자동 로드 기능을 통해 일정양의 데이터가 자동으로 하단에 로딩되어 표기 됨.  

 

Prisma ClientOffset Pagenation VS Cursor Pagenation

 - Offset Pagenation : "skip,  take" 로 “몇 개 건너뛰고 몇 개 가져올지” 계산하는 방식.

 - Cursor Pagenation : “어디서부터 이어서 가져올지” 기준점을 사용하는 방식. 
                                     추가 데이터를 제공하는 경우, 이전에 불러온 데이터의 마지막 데이터가 Cursor의 기준점이 되기 때문에
                                     "skip :1" 을 하지 않으면 중복된 데이터가 제공 됨. 

Offset Pagination — req.body 예시
req.body = {
  "skip": 20,
  "take": 10
}

Cursor Pagination — req.body 예시
req.body = {
  "cursor": "lastItemId_abc123",
  "take": 10
}

 

 

3. Swagger를 사용한 API 문서화

- OpenAPI : 외부에서 API를 사용 할 수 있도록, API 설계 & 설명을 제공 하는 것

- Swagger : OpenAPI 기반의 문서 생성 도구, YAML & JSON 형식으로 작성
        1) swagger-express-ui : Express 서버에서 Swagger 문서를 사용하기 위한 라이브러리

        2) swagger-jsdoc : 코드에 적은 JSDoc 주석을 읽어서 Swagger문서를 생성하는 라이브러리

- typescript 에서의 Swagger : 타입이 정의 된 @types/swaggerjsdoc , @types/swagger-ui-express 사용

- Swagger 사용법 

   1) swagger.ts

      - 전체를 관리하는 options 설정 파일 

      - 기본 정보, 컴포넌트(쿠키)설정, 스키마 정의 등을 진행 

   2) 그 외 swagger 기본 문법(공부했던 내용 : https://theday365.tistory.com/150)

 

[ TIL ] Day 34 - Swagger 전격 분석하기! 📋🖊️

🗓️ 수업 일자 : 2025.11.12✨ 오늘의 수업 평가 : [ HARD ] 오늘은 좌절 연속… 그래도 기록은 남긴다 🥲✍️ ... 머리가 너무 아파서 오늘 개인 평가는 쉽니다.. 👩‍💻 [개인 / 팀 프로젝트] 오늘

theday365.tistory.com

 


 

📃 내일은 뭘 배울까 🤔

- 코드레벨 아키텍쳐

- 디자인패턴(with 코드)

반응형