프로그래밍

REST API 아키텍처 간단 정리

Royal! 2025. 5. 16. 17:53
728x90
반응형

사전 지식

  • 해당 정리는 Architectural Styles and the Design of Network-based Software Architectures 논문을 기반
  • REST API와 RESTful API는 같은 용어
    • REST API는 RFC, ISO와 같은 국제 표준은 아님.
    • 다만 설계원칙 6가지를 얼마나 잘 준수(fulfil)했느냐에 따라 "RESTful" 하다고 평가함.
  • REST API는 경량화, 확장성, 단순성,가시성, 신뢰성을 중시

REST 아키텍처의 6가지 제약 조건 

  1. Client-Server (클라이언트-서버 분리)
    • 클라이언트(UI)와 서버(데이터 저장·처리)가 완전히 분리
    • 서로 독립적으로 발전·확장 가능
  2. Stateless (무상태성)
    • 각 요청(request)은 필요한 모든 정보를 포함
    • 서버는 이전 요청의 상태를 기억하지 않음 → 확장성·신뢰성 향상
  3. Cacheable (캐시 처리 가능)
    • 응답(response)에 Cache-Control 헤더를 달아 클라이언트나 중간 프록시가 캐싱
    • 불필요한 반복 호출 방지 → 성능·효율성 증가
  4. Uniform Interface (통일된 인터페이스) <<- 제일 중요
    • 리소스 식별: URI로 리소스 고유 식별
    • 표현 전송: JSON·XML 등으로 리소스 상태 주고받기
    • Self-descriptive Messages: 요청·응답 메시지 자체가 스스로 의미를 설명
    • HATEOAS (Hypermedia As The Engine Of Application State): 응답에 다음 동작 링크 제공
    • 표준 메서드:
      • GET – 조회
      • POST – 생성
      • PUT/PATCH – 수정
      • DELETE – 삭제
  5. Layered System (계층화 시스템)
    • 클라이언트는 중간 프록시·로드밸런서 등 여러 계층을 신경 쓰지 않고 오직 다음 계층에만 요청
    • 보안·로드 분산·모니터링 계층 삽입 가능
  6. Code On Demand (선택적)
    • 서버에서 클라이언트로 스크립트(JavaScript 등) 전달 가능(선택 사항)
    • 대체로 웹 브라우저와의 상호작용에서 사용

Client - Server

  • 클라이언트와 서버의 역할을 명확히 분리하여, 서로의 내부 구조나 구현 방식에 의존하지 않고 통신하도록 설계
  • 클라이언트와 서버 간 버전 호환성 관리가 필요함
    •  

stateless

  • 서버가 클라이언트의 상태(세션 정보 등)을 보관하지 않고 있으므로, 각 요청에 필요한 모든 정보를 담아서 보내야하는 것이 원칙
    • 가시성(Visibility)/신뢰성(Reliablity)
      • 각 요청이 "필요한 모든 컨텍스트"를 스스로 포함하기 때문에, 모니터링/로깅 시스템이 요청 단위만 보고도 전체 의미를 파악
      • 만약 stateful구조이면 일부 정보는 서버 세션에 저장돼 있어, 요청 실패 시 이전 세션까지 모두 확인해야해 모니터링/로깅이 어려움

  • 확장성(Scalability)
    • 서버는 요청 처리가 끝나면 즉시 메모리·세션 자원을 해제할 수 있어, 더 많은 동시 요청을 수용하면서도 구현이 단순해짐

Cacheable

  • 응답 데이터는(Response Data)는 암묵적 또는 명시적으로 "캐시 가능" 또는 "캐시 불가능(non-cacheable)"으로 표시를 해줘야함.
    • 캐시 가능으로 표시된 응답은 이후 동일한 요청에 대해 클라이언트 캐시가 재사용할 권한을 갖음
    • max-age를 잘 설정하는 것이 중요
  • 캐싱을 통해 얻을 이점
    • 네트워크 효율성 개선
      • 일부 요청/응답이 클라이언트나 프록시 캐시에 저장돼, 서버로 전송할 필요 없이 로컬에서 즉시 제공.
      • 불필요한 RTT가 줄어 Latency를 낮춤.
      • 페이지 렌더링 속도가 빨라짐
    • 확장성 향상
      • 서버에 도달하는 요청 수가 줄어들어 서버 처리 부하가 감소, 즉 더 많은 사용자를 수용할 수 있음.

Uniform Interface - REST API에서 제일 중요한 제약 조건

  • Uniform Interface가 선택된 이유
    •  단순성(Simplicity)
      • 인터페이스를 일반화(generality)함으로써, 모든 컴포넌트가 동일한 '연결자(connector) 인터페이스’만을 이해·구현하면 됨 
        •  Connector가 1개로 통일
          • 전통적인 분산 시스템(RPC, CORBA 등)은 각각의 서비스마다 복잡한 호출 방식/스펙을 정의했어야 함
          • REST는 모든 자원(Resource)에 대해 동일한 HTTP 메서드(GET, POST, PUT, DELETE)와 URI만 알면 됨
            • 클라이언트/서버/프록시/캐시 등 모든 컴포넌트가 "하나의 인터페이스(Connector)"만 구현해 놓으면 됨.
            • 수백, 수천 개의 서비스마다 별도 인터페이스를 설계/문서화할 필요가 없음
    • 독립전 진화(Independent Evolvability)
      • 클라이언트와 서버가 오직 "인터페이스 계약(둘 간의 규칙)"만 맞춘다면 내부 구현을 자유롭게 변경해도 서로에게 영향을 주지 않음.

  • Uniform Interface를 실현하기 위해 네 가지 세부 제약 
    • Resource Identification
      • 모든 중요한 개체는 단일 자원 식별자(URI)로 접근
        • 어떤 자원을 어떻게 찾을 것인가라는 문제를 URI라는 공통 언어로 명료하게 해결 
        • 이름을 붙일 수 있는 모든 것이 자원(Resource)
        • 식별자(Identifier)는 리소스의 의미를 고정해주므로, 시간이 지나도 "무엇을 가리키는지" 변하지 않음
          • 가르키는 것은 변하지 않아야 하나, 표현(Representation)은 달라질 수 있음 -> "어떻게 표현할지" 자유롭게 표현 가능
            • 서버는 클라이언트가 원하는 형태에 맞춰 JSON·XML·HTML·PNG(책 속 이미지) 등 여러 가지 포맷으로 응답 가능
    • Manipulation of Resource through Representaions
      • 클라이언트가 자원 그 자체가 아니라, 자원의 표현(Representation)을 주고 받으면서 자원의 상태를 변경/삭제/조회/하도록 설계
        • 표현 : 자원은 URI로 식별되는 추상적 개념이고, 실제 데이터를 주고받을 때는 JSON, XML, HTML 등 표현을 사용
        • 정리하면 자원에 접근해서 자원과 JSON/XML/HTML 등의 표현을 주고 받으면서 자원의 상태를 조회/변경/삭제하는 행위
          • 해당 행위에 CRUD(GET/POST/PUT/PATCH/DELETE)를 사용하는 것
    • Self-descriptive Messages
      • 클라이언트와 서버가 주고받은 각 메세지 자체에 "이것을 어떻게 처리해야 하는지"에 대한 모든 단서를 담고 있어햐함
        • 각 메시지(요청/응답)는 자체적으로 처리 방법을 드러내는 메타데이터(미디어 타입, 캐시 제어)등을 포함하고 있음
        • 단서들에는 미디어타입(Content-Type/Accept), 캐시제어(Cache-Control), 인증권한(Authorization),상태코드(Status Code), 링크 정보(Link/Location)이 존재
    • Hypermedia as the Engine of Application State(HATEOAS)
      • 서버는 가능한 다음 상태(Link, 전이 방법)를 하이퍼미디어(Hypermedia) 형태로 응답에 포함하여, 클라이언트가 외부 지식 없이도 애플리케이션 흐름을 탐색하도록 함.


Layered System (계층화 시스템)

  • 전체 시스템을 여러 계층으로 분리해, 각 컴포넌트가 바로 인접한 계층과만 상호작용하도록 설계
    • 클라이언트는 요청을 보낼 곳을 프록시, 로드밸런스, 원서버인지 구분 없이 오직 다음 계층에만 요청을 전달
    • 서버도 동일하게 설계
  • 계층별로 기능을 나눠서 담당함. 각 계층은 자신이 맡은 역할만 책임지므로 구성 요소가 단순
    • 보안 : WAF 같은 보안 장비를 애플리케이션 계층 앞에 두어 악의적 요청 차단
    • LB : 트래픽을 여러 서버로 골고루 분배
    • 캐싱 
    • 모니터링/로깅

즉, 전체 시스템이 단순해지면서 수평적 확장도 쉬워지며 유지보수도 용이함.


Code On Demand

  • 필요할 때 서버가 클라이언트에 실행 가능한 코드를 내려보낼 수 있는 기능
    • 서버가 "코드 패키지"를 보내줌
      • EX) 웹 브라우저가 /dashboard를 요청했더니 서버는 HTML과 함꼐 JavaScript파일을 함께 전달
    • 클라이언트가 코드를 모드 가지고 있지 않으며 필요한 기능이 있을 때 마다 서버에 요청
      • 클라이언트의 경량화 가능
    • 코드를 받을 때는 신뢰할 수 있는 출처인지 반드시 검증

즉, 클라이언트가 경량화되면서 서버에서 코드를 바꾸면(서버 패키지를 받음) 클라이언트가 새로고침만해도  최신 기능을 사용

728x90
반응형