REST API 정리와 HATEOAS 개념

최형안·2025년 3월 24일

REST API 정리와 HATEOAS 개념

API(Application Programming Interface)는 애플리케이션 간 소통을 위한 인터페이스

REST API는 REST 원칙을 따르는 API로, HTTP를 사용해 리소스(데이터)를 주고받는 방식의 API

REST는 Representational State Transfer의 약자로,
웹에서 자원을 효율적이고 일관되게 다루기 위한 아키텍처 스타일

REST API의 핵심 구성 요소와 REST의 5가지 원칙과 이유, 그리고 HATEOAS를 정리


REST API 핵심 구성 요소

1. 엔드포인트 (Endpoint)

  • API에서 접근 가능한 자원(리소스)의 위치
  • 보통 URL 형태로 나타남: /products, /users/1/orders

2. 메서드 (Method)

  • 엔드포인트에서 수행할 수 있는 행동 정의
    • GET: 데이터 조회
    • POST: 데이터 생성
    • PUT: 데이터 수정
    • DELETE: 데이터 삭제

3. 요청 (Request)

  • 작업에 필요한 데이터와 매개변수를 포함

4. 응답 (Response)

  • API가 클라이언트에 반환하는 결과
  • 보통 JSON 형식이며, HTTP 상태 코드(200 OK, 404 Not Found 등)를 함께 포함

RESTful API 설계 5가지 원칙

1. 클라이언트 – 서버 구조

  • 프론트엔드와 백엔드를 독립적으로 개발 및 배포할 수 있다.
  • 한 서버(API)가 여러 클라이언트(웹, 모바일 등)를 지원 가능
  • DB에 직접 접근하지 않고, 서버에서 인증과 권한을 처리해 보안 강화

→ 프론트엔드(React, Vue)와 백엔드(Spring, Node.js)를 분리
→ 서버는 데이터만 반환하고, UI는 클라이언트가 구성


2. 무상태성 (Stateless)

  • 서버는 클라이언트의 상태를 저장하지 않아야 한다
  • 모든 요청은 독립적이며, 필요한 모든 정보를 포함해야 한다

이점

  • 서버 메모리 사용량 감소
  • 구현이 단순하고 명확
  • 상태 복원이 필요 없어 복원 처리 용이
  • 동일한 요청에 동일한 응답이 가능 → 캐싱에 유리
  • 다중 서버 환경(로드 밸런싱)에서 사용가능 ex) JWT 처리로 모든 서버에서 동일 인증 가능
세션 방식: 매 요청마다 Redis나 DB에서 세션 조회 필요  
JWT 방식: 서버가 토큰 디코딩만으로 인증 가능  
→ 클라이언트는 요청마다 필요한 정보를 다 포함해서 보낸다

HTTP는 본질적으로 stateless이므로, HTTP를 사용하면서 세션을 사용하지 않으면 구현 가능

3. 캐시 가능

  • 응답 결과를 클라이언트 또는 중간 서버가 저장해 재사용할 수 있어야 한다
  • 성능 최적화에 효과적

예시:

GET /news  
Cache-Control: max-age=3600

→ 1시간 동안 캐시 유지
→ 브라우저나 CDN에 저장되어 서버 부하 감소
→ HTTP GET은 기본적으로 캐싱을 지원


4. 계층화된 시스템

  • API 요청은 프록시, 게이트웨이, 로드밸런서 등의 중간 계층을 거칠 수 있다
  • 클라이언트는 이 구조를 몰라도 되며, API만 알면 됨

장점

  • 추상화, 캐싱, 로드밸런싱, 마이크로서비스 구조 분리, 보안 강화(JWT 인증 처리)

예시:

  • Nginx 로드밸런서가 클라이언트 요청을 여러 서버에 분산
  • API Gateway가 요청을 받아 내부 마이크로서비스로 전달

용어 정리

  • 프록시: 클라이언트-서버 사이에서 간접적 접속을 가능하게 하는 시스템
  • 포워드 프록시: 클라이언트 보호용. IP 숨김, 캐싱 제공
  • 역방향 프록시: 서버 보호용. 로드 밸런싱, 캐싱, 서버 IP 보호
  • 로드 밸런서: 여러 서버에 부하를 나눠줌
  • 게이트웨이: 클라이언트와 API(서버)또는 마이크로서비스 사이의 중개자 역할을 하는 서버
    Api 호출을 수신 처리한 후 마이크로서비스로 라우팅하는데 이때 요청이 올바른 마이크로서비로 갈 수 있도록 안내하는 역할

5. 일관된 인터페이스 (Uniform Interface)

  • API는 일관된 방식으로 설계되어야 한다
  • 리소스를 중심으로 동작하고, HTTP 메서드를 올바르게 사용해야 함

규칙

  • URI는 명확하게 리소스를 나타내고, 동작을 포함하지 않아야 함
  • 소문자 사용, 계층적으로 구성, 너무 길면 _ 대신 - 사용
  • 응답은 JSON, 상태코드는 HTTP 표준을 따른다

예시

  • 자원은 URL로 식별: /products/1
  • 자원 조작은 HTTP 메서드 사용: GET, POST, DELETE, PUT 등
  • 헤더에 Content-Type 명시: MIME 타입에 맞춰 표현

HATEOAS란?

HATEOAS (Hypermedia As The Engine Of Application State)

“API 응답 안에 현재 상태에서 가능한 다음 행동 링크들을 포함하자”


예시: 상태에 따른 행동 제공

{
  "id": 1,
  "name": "상품 A",
  "status": "NEW",
  "_links": {
    "self": { "href": "/products/1" },
    "update": { "href": "/products/1", "method": "PUT" },
    "delete": { "href": "/products/1", "method": "DELETE" }
  }
}

→ 클라이언트는 상품 상태가 NEW일 때 update, delete가 가능함을 알 수 있다
→ 서버가 상태 전이에 따른 행동을 명시적으로 안내

// 일반적인 클라이언트 처리 예시
if (order.status === "NEW") {
  showPayButton();
  showCancelButton();
} else if (order.status === "PAID") {
  showShipButton();
}

// HATEOAS 방식
if (order._links.pay) showPayButton();
if (order._links.cancel) showCancelButton();
if (order._links.ship) showShipButton();

→ 클라이언트는 서버의 로직을 구현하지 않아도 된다
→ 링크 존재 여부만으로 기능 수행 가능
→ 상태 기반 로직의 클라이언트 종속을 줄일 수 있다


변경 대응: API 경로가 바뀌었을 때

기존

GET /products/42/reviews

변경

GET /items/42/feedback

HATEOAS 적용 응답

{
  "id": 42,
  "name": "상품 A",
  "_links": {
    "self": { "href": "/products/42" },
    "reviews": { "href": "/items/42/feedback" }
  }
}

클라이언트 코드

const reviewsUrl = response._links.reviews.href;
fetch(reviewsUrl).then((res) => res.json()).then(...);

→ 클라이언트는 URI를 외우거나 문서로 학습하지 않아도 됨
→ 서버가 알려주는 링크만 따라가면 됨
→ 유지보수가 쉬워지고, 유연성이 높아짐


HATEOAS의 장점 요약

장점설명
상태 기반 UI 처리현재 상태에 따라 가능한 행동을 응답에 포함시켜 클라이언트가 유연하게 처리
서버 주도 흐름 제어클라이언트가 로직을 몰라도 서버가 안내하는 링크만 따라가면 됨
유지보수성 향상API 경로가 바뀌어도 클라이언트는 링크만 따라가므로 수정이 적음
자동 탐색 가능문서 없이도 클라이언트 또는 자동화 도구가 API를 탐색 가능

마무리

RESTful API는 명확한 원칙을 기반으로 설계되고,
HATEOAS는 그 위에 더 유연하고 확장 가능한 API를 만드는 방법이다.

작은 프로젝트에서는 HATEOAS가 필요 없을 수도 있지만,
상태 기반 로직이 복잡하거나 API가 자주 변경될 가능성이 있는 경우에는 매우 유용한 개념이다.

0개의 댓글