728x90
Rest API는 Rest를 기반으로 만들어진 API를 의미합니다. 이번 포스트에서는 Rest하다는 것이 무엇인지 그 의미에 대해 Rest API의 등장부터 차근차근 정리해보도록 하겠습니다.
Rest API의 등장
Rest API란 Representation State Transfer API의 약어로, 2000년도 로이 필딩(HTTP의 주요 저자 중 한명)의 박사 학위 논문에서 최초로 소개되었습니다. 로이 필딩은 웹(HTTP) 설계의 우수성에 비해 제대로 사용되지 못하는 모습이 안타까워 웹(HTTP)의 장점을 극대화 시킬 수 있는 아키텍처로써 Rest API를 발표했다고 합니다.
Rest API의 구성
Rest API는 다음과 같이 구성되어 있습니다.
- 자원 - URI
- 행위 - HTTP METHOD
- 표현
Rest API의 특징
- Uniform Interface(유니폼 인터페이스)
- URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일을 말합니다.
- 예시)
[ Request Params을 이용한 URL ]
>> 회원 모두 조회: GET localhost:8080/members
>> 회원 한명 조회: GET localhost:8080/members?uId=a
>> 회원 정보 수정: POST localhost:8080/members/rev?uId=a
>> 회원 정보 삭제: POST localhost:8080/members/rm?uId=a
[ Uniform Interface을 이용한 URL ]
>> 회원 모두 조회: GET localhost:8080/members
>> 회원 한명 조회: GET localhost:8080/members/a
>> 회원 정보 수정: PUT/PATCH localhost:8080/members/a
>> 회원 정보 삭제: DELETE localhost:8080/members/a
- Stateless(무상태성)
- 작업을 위한 상태정보는 따로 저장하고 관리하지 않습니다.
- 세션이나 쿠키정보를 별도로 저장하고 관리하지 않기 때문에 API서버는 들어오는 요청을 단순히 처리할 수 있습니다.
- 때문에 서비스에 대한 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않아 구현이 단순합니다.
- Cacheable(캐시 가능)
- REST의 가장 큰 특징 중 하나로, HTTP웹 표준을 사용하기 때문에 웹 기존 인프라를 그대로 사용할 수 있습니다.
- HTTP캐싱 기능 적용이 가능합니다.
- Self-descriptiveness(자체 표현 구조)
- REST의 또 다른 큰 특징 중 하나로, API 메시지만 보고도 쉽게 이해할 수 있는 자체 표현 구조로 되어 있습니다.
- Client-Server 구조
- 서버는 API를 제공하고, 클라이언트는 사용자 인증이나 컨텍스트(로그인 정보, 세션)등을 직접 관리하는 구조를 가지고 있습니다.
- 역할 구분이 확실하여 서로간 의존성이 줄어들고 어떤 내용을 개발해야 할 지 명확히 할 수 있습니다.
- 계층형 구조
- Rest 서버는 다중 계층으로 구성할 수 있습니다.
- 보안/로드 밸런싱/암호화 계층을 추가해 구조상의 유연성을 둘 수 있습니다.
- 프록시 서버나 게이트웨이 같은 네트워크 기반의 중간서버를 사용할 수 있게 해줍니다.
Rest API 디자인 가이드
- URI은 정보 자원을 표현해야 합니다. 행위에 대한 표현이 들어가서는 안되며 리소스명은 동사보다는 명사를 사용합니다.
- URI는 하나의 고유한 리소스를 대표하도록 설계합니다.
- 특정한 URI는 반드시 그에 상응하는 데이터 자체를 의미해야 합니다.
- 특정 URI를 통해서 사용자가 원하는 정보를 제공할 수 있어야 합니다.
- 자원에 대한 행위는 HTTP Method (GET,POST,PUT,PATCH,DELETE)로 표현해야 합니다.
POST localhost:8080/members/rm?uId=a - (1)
DELETE localhost:8080/members/a - (2)
✨ 1번보다 2번이 더 좋음!
Rest API 설계 시 주의 사항
- 슬래시 구분자 /는 계층 관계를 나타낼 때 사용합니다.
localhost:8080/members/a
- 마지막 문자로 /를 포함하지 않습니다.
- URI에 포함되는 모든 글자는 리소스의 유일한 식별자로 사용되어야 합니다.
- URI가 다르다는 것은 리소스가 다르다는 것을 의미합니다. (반대도 마찬가지입니다.)
- REST API는 분명한 URI를 만들어 통신해야하기 때문에 혼동을 주지 않기 위해 마지막 문자에 /는 포함하지 않습니다.
- 긴 URI를 작성해야 하는 경우 가독성 향상을 위해 -를 사용할 수 있습니다.
- URI에서 _는 가독성이 떨어지고 문자에 가릴 수 있기 때문에 사용하지 않습니다.
- URI경로는 소문자로 표현합니다.
- 대문자를 사용할 경우 행위를 나타내는 HTTP Method이거나 다른 의미일 수 있기 때문입니다.
- 파일 확장자는 URI에 포함하지 않습니다.
- 파일 확장자는 HTTP Message 중에 Accept Header를 이용합니다.
http://restapi.example.com/members/soccer/345/photo.jpg (X) GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg (O)
- 리소스간의 관계 표현법
- GET: .../naver/pay >> naver has payments department (has-a 관계일 때 일반적으로 / 사용) GET: .../naver/payments/detail // 네이버 페이 상세목록 >> payments's details ('s 관계일 때도 일반적으로 / 사용) GET: .../naver/shopping/likes/food // 네이버 쇼핑 리스트 찜 목록 중 음식 관련 카테고리 >> likes는 동사지만 리소스 간의 관계를 명확하기 표현하기 위해 이렇게 사용할 수 있음
- 자원을 표현하는 객체나 객체 집합은 복수로 표현합니다.
- https://shopping.naver.com/my/keep-products
HTTP 응답 상태 코드
잘 설계된 REST API는 URI만 잘 설계된 것이 아닌 그 리소스에 대한 응답을 잘 나타내줄 수 있어야 합니다. 정확한 응답의 상태코드는 많은 정보를 전달할 수 있기 때문입니다.
응답 상태 코드는 종류가 많아 대표적으로 자주 쓰는 것만 요약하겠습니다.
- 2xx - 성공
- 요청을 성공적으로 받았으며 인식했고 수용함
- 종류
- 200 OK
- 요청이 성공적으로 됨
- 정보는 요청에 따른 응답으로 반환됨
- 201 Created
- 요청이 성공적
- 그 결과로 새로운 리소스가 생성됨
- 일반적으로 POST 요청이나 PUT 요청 이후에 따라옴
- 게시물 작성이나 회원 가입등 새로운 데이터를 서버에 쓰는 작업이 성공했을 때 사용함
- 202 Accepted
- 요청을 수신하였지만 그에 응하여 행동을 할 수 없음
- 해당 응답은 요청 처리에 대한 결과를 이후에 HTTP로 비동기 응답을 보내는 것에 대해 명확하게 명시하지 않음
- 다른 프로세스에서 처리 또는 서버가 요청을 다루고 있거나 배치 프로세스를 하고 있는 경우를 위해 만듦
- 게시글 등록 / 삭제 예약
- 203 Non-Authoritative Information
- 응답 코드는 돌려받은 메타 정보 세트가 오리진 서버 것과 일치하지 않지만 로컬이나 서드 파티 복사본에서 모아졌음을 의미함
- 해당 응답이 아니라 200 OK 응답을 반드시 우선됨
- 204 No Content
- 요청에 대해서 보내줄 수 있는 콘텐츠는 없지만 헤더는 의미가 있을 수 있음
- 사용자 에이전트는 리소스가 캐시된 헤더를 새로운 것으로 업데이트 할 수 있음
- 웹 문서 편집기의 save 버튼
- save를 눌러도 화면상 변화는 없음
- 결과 내용은 없지만 204 상태코드로 해당 작업의 성공을 인식시켜줄 수 있음
- 리소스의 삭제가 정상적으로 처리되었을 때
- 200 OK
- 3xx - 리다이렉션
- 요청 완료를 위해 리다이렉션을 함
- 종류
- 301 Moved Permanently 영구 리다이렉션
- 요청한 리소스의 URI가 변경되었음을 의미함
- 새로운 URI가 응답에서 아마도 주어질 수 있음
- 308 Permanent Redirect 영구 리다이렉션
- 리소스가 HTTP 응답 헤더의 Location에 명시된 영구히 다른 URI에 위치하고 있음을 의미함
- 이것은 301 Moved Permanently HTTP 응답 코드와 동일한 의미를 가지고 있음
- 사용자 에이전트가 반드시 HTTP 메소드를 변경하지 말아야 하는 점만 다름
- 만약 첫 요청에 POST가 사용되었다면 두번째 요청도 반드시 POST를 사용해야 함
- 본문이 제거될 수 있음
- 302 Found 일시 리다이렉션
- 요청한 리소스의 URI가 일시적으로 변경되었음을 의미함
- 새롭게 변경된 URI는 나중에 만들어질 수 있음
- 클라이언트는 향후의 요청도 반드시 동일한 URI로 해야함
- 리다이렉트 요청 메소드가 GET으로 변하고 본문이 제거될 수 있음
- 303 See Other 일시 리다이렉션
- 클라이언트가 요청한 리소스를 다른 URI에서 GET 요청을 통해 얻어야 할 때 서버가 클라이언트로 직접 보내는 응답
- 302 대용으로 등장하였지만 302 보다 자주 사용되진 않음
- 304 Not Modified 특수 리다이렉션
- 캐시를 목적으로 사용됨
- 클라이언트에게 응답이 수정되지 않았음을 알려주며 클라이언트는 계속해서 응답의 캐시된 버전을 사용할 수 있음
- 클라이언트는 로컬 PC에 저장된 캐시 재사용
- 로컬 캐쉬를 그대로 사용해야하기 때문에 Body에 메시지를 포함하면 안됨
- 301 Moved Permanently 영구 리다이렉션
- 4xx - 클라이언트 오류
- 요청의 문법이 잘못되었거나 요청을 처리할 수 없음
- 종류
- 400 Bad Request
- 잘못된 문법으로 인하여 서버가 요청하여 이해할 수 없음 의미
- 요청 구문이나 메시지 오류가 있을 때 사용함
- 클라이언트는 요청 내용을 다시 검토 후 요청해야 함
- 401 Unauthorized
- 비인증 (unauthenticated)를 의미
- 클라이언트는 요청한 응답을 받기 위해서는 반드시 스스로를 인증해야 함
- 로그인이 필요한 환경에 비로그인으로 접속했을 경우 발생
- 응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명해서 보낼 수 있음
- 404 Not Found
- 서버는 요청받은 리소스를 찾을 수 없음
- 브라우저에서는 알려지지 않은 URL을 의미함
- API에서 종점은 적절하지만 리소스 자체는 존재하지 않음을 의미할 수 있음
- 서버들은 인증받지 않은 클라이언트로부터 리소스를 숨기기 위하여 이 응답을 403 대신에 전송할 수도 있음
- 응답 코드는 웹에서 반복적으로 발생함
- 추가적으로 403과 같이 클라이언트가 권한이 부족한 리소스에 접근했을 경우 페이지 숨기는 용도로 가끔 사용
- 400 Bad Request
- 5xx - 서버 오류
- 서버가 명백히 유효한 요청에 대한 충족을 실패함
- 정말 서버에 문제가 있을 경우에만 사용 🚨
- 개발자가 직접 해당 에러를 리턴하는 경우는 없음
- 종류
- 500 Internal Server Error
- 웹 사이트 서버에 문제가 있음을 의미하지만 서버는 정확한 문제에 대해 더 구처적으로 설명할 수 없음
- 웹 서버에 문제가 있을 때 발생하는 에러
- 서버에 발생하는 에러 원인을 정확하게 파악하지 못한 경우 (애매한 경우)
- 503 Service Unavailable
- 서버가 요청을 처리할 준비가 되지 않음
- 일반적인 원인은 유지보수를 위해 작동이 중단되거나 과부하가 걸린 서버임
- 해당 응답과 함께 문제를 설명하는 사용자 친화적인 페이지가 전송되어야 한다는 점에 유의
- 해당 응답은 임시 조건에 사용되어야 하며 Retry-After: HTTP 헤더는 가능하면 서비스를 복구하기 전 예상 시간을 포함해야 함
- Retry-After - 날짜 표기로 언제부터 ~ 언제까지 서비스 이용이 불가능한지 표현 가능 - 웹 마시터는 또한 이러한 일시적인 조건 응답을 캐시하지 않아야 하므로 해당 응답과 함께 전송되는 캐싱 관련 헤더에 대해서도 주의해야 함
- 서비스 점검 (유지/보수)시 일시적으로 서버의 작동을 중단시킬 때 사용
- 500 Internal Server Error
'Spring' 카테고리의 다른 글
Spring - ResponseEntity, RequestEntity (0) | 2022.11.21 |
---|---|
Spring - @RestController (0) | 2022.11.21 |
Spring - @Controller (0) | 2022.11.21 |
Spring - IoC, DI (0) | 2022.11.21 |
Spring - 스프링 모델 (0) | 2022.11.21 |
댓글