Rest API (Representational State Transfer)

REST를 기반으로 만들어진 API

  • 디바이스의 종류에 상관없이 공통으로 데이터 처리할 수 있는 방식
  • 하나의 URI는 하나의 고유한 Resource를 대표하도록 설계된다는 개념
  • Resource를 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것


  • 사용자가 URI(Resource)로 요청 HTTP Method(POST, GET, PUT, DELETE)을 보낼 때
    • 사용자가 필요로 하는 결과(데이터 - URI에 대한 CRUD, Representation of Resource) 리턴


Rest API 구성요소

  1. Resource : URI(ex) user)
    서버는 Unique한 ID를 가지는 Resource를 가짐
    클라이언트는 이러한 Resource에 요청
    Collection : Resource의 집합(ex) users)
  2. Method : 서버에 요청을 보내기 위한 방식(GET, POST, PUT, PATCH, DELETE)
    CRUD 연산 중에서 처리를 위한 연산에 맞는 Method를 사용하여 서버에 요청을 보내야 함

    제목 없음

    1) GET : 서버로부터 정보를 가져올 때 사용(Read)
    2) POST : 리소스를 생성할 때 사용(Create)
    3) PUT : 리소스를 수정할 때 사용(Update)
    4) DELETE : 리소스를 제거할 때 사용(Delete)

    참고) Idempotent : 여러 번 수행해도 결과가 같은 경우를 의미

  3. Representation : 자원에 대한 행위의 내용 = 요청에 대한 Body(형태는 json, xml, text, rss 등)


RESTful

REST의 원리를 따르는 시스템
REST라는 아키텍쳐개념을 그대로 적용해서 웹서버를 구성하고 웹서비스 하는 것

  • 웹서버가 RESTful 하다 = REST API 이용할 수 있다
    = 웹서버에 구성된 주소(URI)만 알고 있다면 어떤 클라이언트라도 해당 웹서버를 이용할 수 있음
  • REST를 사용했다 하여 모두가 RESTful 하지는 않음
    REST API의 설계 규칙을 명확하게 지킨 시스템만이 RESTful 하다고 말할 수 있음


REST 규칙(디자인)

  • URI
    • 명사 사용
      • Non-Resource URL(특정 작업을하고 응답으로 아무것도 하지 않는 경우)에는 동사 사용가능
    • 슬래시로 계층 관계 표현
    • 소문자로만 구성
    • 가독성이 떨어지는 경우 하이픈( _ 대신 - ) 사용
      • Path Variable에는 카멜케이스(userId) 사용
    • 파일확장자 포함x
      • ex) 나쁜예 [GET] /users/1/profile.png
      • 클라이언트가 허용할 수 있는 파일 형식 정보가 있는 Accept header를 사용
       [GET] ttaehee.github.io/users/1/profile-img
       Accept: image/jpg
      
  • HTTP Method로 표현

    [PUT] /posts/1
    
  • 적절한 상태값 응답
  • JSON property에는 카멜케이스 사용

    {
       userId: "1"
       userName: "Covenant"
    }
    
  • API 버전을 위해서 서수를 사용

    https://kapi.kakao.com/v2/user/me
    


REST의 특징

1) Uniform Interface(일관된 인터페이스)
Resource(URI)에 대한 요청을 통일되고 한정적으로 수행하는 아키텍처 스타일을 의미

  • 요청을 하는 Client가 플랫폼(Android, Ios, Jsp 등)에 무관
  • 특정 언어나 기술에 종속받지 않음 의미

=> Rest API는 HTTP 사용하는 모든 플랫폼에서 요청가능 + Loosely Coupling(느슨한 결함) 형태 가짐


2) Stateless(무상태성)
클라이언트의 컨텍스트를 서버쪽에 유지 하지 않음 의미
(Server는 각각의 요청을 별개의 것으로 인식하고 처리해야함, 이전 요청이 다음 요청에 연관되어서는 안됨)
= HTTP Session과 같은 컨텍스트 저장소에 상태 정보를 저장하지 않는 형태
=> 서버의 처리방식에 일관성 부여, 서버의 부담을 줄이기 위함

=> Rest API는 서비스의 자유도가 높음(각 API 서버는 들어오는 요청만을 들어오는 메시지로만 처리하면 됨)
  서버에서 불필요한 정보를 관리하지 않으므로(컨텍스트 정보를 신경쓸 필요가 없기 때문에) 구현이 단순


3) Cacheable(캐시가능)

  • Rest API는 HTTP라는 기존의 웹표준을 그대로 사용 -> 웹의 기존 인프라 그대로 활용가능 -> Rest API에서도 캐싱 가능
  • HTTP 프로토콜 표준에서 사용하는 Last-Modified Tag 또는 E-Tag를 이용하여 캐싱 구현가능

=> 대량의 요청 효율적으로 처리가능
(REST 컴포넌트가 위치한 서버에 트랜잭션 발생x -> 전체 응답시간, 성능, 서버의 자원 사용률 비약적으로 향상)

제목 없음

       Client가 HTTP GET을 Last-Modified 값과 같이 보냄
       -> 컨텐츠 변화가 없으면 REST 컴포넌트는 304 Not Modified 리턴
       -> Client는 자체 캐시에 저장된 값을 사용


4) Self-Descriptiveness(자체 표현)
REST API 자체가 매우 쉬워서 API 요청메시지 자체만 보고도 API를 이해할 수 있는 자체 표현 구조로 되어있음

  • Resource와 Method로 어떤 메서드에 무슨 행위를 하는지를 알 수 있음
  • Message format 역시 JSON을 이용해서 직관적으로 이해가 가능한 구조


  HTTP POST, http://localhost:8080/board
  {
    "board":{
    "title":"제목",
    "content":"내용"
    }
  }

localhost:8080/board 로 게시글의 제목, 내용 전달하고 있음
board라는 데이터를 추가(POST)하는 요청임을 쉽게 파악


5) Client-Server Architecture (클라이언트-서버 구조)

  • Client : 자원을 요청하는 쪽, 사용자 인증, 컨텍스트(세션, 로그인 정보) 등을 직접 관리하는 역할
  • Server : Rest API에서 자원을 가지고 있는 쪽, API 제공하는 역할

=> 역할을 확실히 구분시킴으로써 개발 관점에서 클라이언트와 서버에서 개발해야 할 내용들이 명확하게 되고 서로의 개발에 있어서 의존성이 줄어들게 됨


6) Layered System(계층 구조)

  • 클라이언트 입장에서는 REST API 서버만 호출(서버와 직접 통신하는지, 중간 서버와 통신하는지 알 수 없음)
  • 서버는 다중 계층으로 구성될 수 있음
    • 순수 비즈니스 로직을 수행하는 API 서버와 그 앞단에 사용자 인증(Authentication), 암호화(SSL), 로드밸런싱 등을 하는 계층을 추가해서 구조를 변경할 수 있음
    • Proxy, Gateway와 같은 네트워크 기반의 중간매체를 사용할 수 있게 해줌



Spring에서 Rest API 사용

  • 1- @RestController
    • 클래스 레벨에 선언
    • 붙은 클래스의 모든 메서드는 자동으로 @ResponseBody가 적용


  • 2- @Controller (이것만 붙어있으면 리턴 String 값의 html 파일을 찾아서 리턴) + @ResponseBody
    • 스프링의 message converter에 의해 데이터 자체를 리턴
      = Rest 구조로 받을 수 있게 json 형태로 변환시켜줌

      @ResponseBody
      @GetMapping("/helloworld")
      public String helloWorld() {
          return "helloworld";
      }
      
      • @ResponseBody로 인해 helloworld라는 view가 아닌 문자열 그대로 반환
      • vo 객체도 반환 가능 -> json형태로 반환


  • Spring의 REST 관련 Annotation
    • @RestController : Controller가 REST 방식을 처리하기 위한 것임을 명시
    • @ResponseBody : 일반적인 JSP와 같은 뷰로 전달되는 게 아니라 데이터 자체를 전달하기 위한 용도
    • @PathVariable : URL 경로에 있는 값을 파라미터로 추출하려고 할 때 사용
    • @RequestBody : JSON 데이터를 원하는 타입으로 바인딩 처리
    • @CrossOrigin : Ajax의 크로스 도메인 문제를 해결


Response 내려주는 방법

@RestController
@RequestMapping("/api")
public class ApiController{


1) text 형태

  @GetMapping("/text")
  public String text(@RequestParam String account){
      return account;
  }
  • [GET] localhost:8080/api/text?account=user1

    제목 없음

2) json 형태

(User.java DTO 생성 후)

  @PostMapping("/json")
  public User json(@RequestBody User user){
      return user;
  }
  • object mapper가 json(text) <-> object 변환을 처리
    json(request) -> object mapper -> object
    -> method
    -> object -> object mapper -> json(response)

  • [POST] localhost:8080/api/json

    제목 없음

    =>
    제목 없음



3) ResponseEntity 형태 : 사용자가 직접 응답형태를 수정

언제나 200이 아닌 경우에 맞는 HTTP Status 전달
(Response를 내려줄 때 HTTP Status를 지정해주기)

  @PutMapping("/put")
  public ResponseEntity<User> put(@RequestBody User user){
      return ResponseEntity.status(HttpStatus.CREATED).body(user);
  }
  • [PUT] localhost:8080/api/put

    제목 없음

    =>
    제목 없음



4) @Controller에서 JSON 사용

  • @ResponseBody : @ResponseBody 어노테이션을 통해 @Controller도 Json 형태로 데이터 반환가능
  • User.java field : int는 기본 0이 셋팅 되므로 Integer로 변경
  @Controller
  public class PageController {

      @ResponseBody
      @GetMapping("/user")
      public User user() {
          User user = new User();
          user.setName("hello")
          user.setAddress("경기도");
          return user;
      }
  }
  • null 값은 제외하고 싶을 시 User.java에서
    • @JsonInclude(JsonInclude.Include.NON_NULL) : Null을 포함시키지 않음
    • @JsonInclude(JsonInclude.Include.NON_EMPTY) : 빈값을 포함시키지 않음



Reference
https://sidepower.tistory.com/408
https://mangkyu.tistory.com/46
https://pronist.dev/146
https://rimkongs.tistory.com/221
https://bcho.tistory.com/953
https://100100e.tistory.com/393
https://sharplee7.tistory.com/49
https://covenant.tistory.com/241
https://dreaming5developer.tistory.com/243

업데이트: