REST API에 대해 알아보자.

이민선(Jasmine)·2023년 3월 29일
1

WEB 개발 기초

목록 보기
2/7
post-thumbnail

REST API가 뭘까요?
뭐긴 뭐야 RESTful한 API지...

그치 운명의 데스티니고 전설의 레전드지... 머릿속에서 대략적인 느낌은 오지만 말이나 글로 설명하기 어려운 것들이 종종 있는데, 나의 경우에는 REST API가 딱 그 중 하나이다.
아무리 자료들을 읽어봐도 추상적인 개념들만 머릿속에 맴돌고 말이나 글로 설명하기 어렵다는 것은 아직 온전히 나의 지식이 아니라는 방증일 것이다.
그래서 이번 기회에 내가 공부한 REST API를 최대한 쉽게 풀어서 포스팅해보며 나의 지식으로 만들고자 한다.

하나씩 뜯어보자. REST는 무엇이고 API는 무엇인가?

REST API를 이해하기 위한 첫 걸음(이자 절반)은 API가 무엇인지부터 제대로 짚고 넘어가는 것이다. 사실 API라는 단어는 제대로 모르면서도 자주 쓰는 단어이다. 왜 공공데이터포털에 있는 그거!.. 그거 있잖아..!
...
API가 무엇인지부터 설명하는 것을 목표로 하자.

API(Application programming interface)

API라는 단어를 이해하는 데에 가장 큰 도움이 되었던 게시물
https://yozm.wishket.com/magazine/detail/727/

우선 interface라는 단어에 초점을 맞춰보자.

GUI(graphic-user interface)라는 단어를 떠올려보자. API처럼 interface라는 단어가 들어간다. GUI는 '컴퓨터'와 '사람'을 연결하는 사용자 인터페이스의 예시이다.

크롬을 켜고 싶은 사용자가 있다고 가정해보자. 그래픽으로 된 예쁜 아이콘을 클릭하여 크롬 좀 켜달라고 요청하면(GUI), 프로그램이 알아서 복잡한 내부 작업을 거쳐 사용자가 원하는 대로 크롬을 켜주며 응답한다. 하지만 크롬 사용자는 복잡한 내부 작업은 안물 안궁이고 얼른 크롬을 켜서 인터넷 쇼핑이나 하고 싶다. 버튼 클릭하기 -> 크롬 쨔잔~~ 이라는 단순한 절차만 알고 있고 알고 싶을 뿐이다. interface는 이처럼 "복잡한 내부 작업은 딱히 보고 싶지 않고 난 크롬만 켜면 돼"라는 사람이 대다수이므로 존재하는 것이다.

API는 사용자 인터페이스와 달리 '컴퓨터 프로그램'과 '컴퓨터 프로그램'을 연결하는 인터페이스이다. 사용자 인터페이스와의 중요한 차이는 사용자와 최종 사용자가 일치하지 않는다는 점이다.

위의 사용자 인터페이스 예시에서 사용자인 동시에 최종사용자인 유저는 단순히 버튼을 누르고 크롬을 여는 기능을 이용하면 그만이다. 하지만 API는 앱 개발을 하는 개발자를 위한 인터페이스이다. 즉 API에서 사용자는 개발자이고, 최종 사용자는 앱 유저이며 이 둘은 일반적으로 일치하지 않는다.

최근에 파이어베이스로 구글 oAuth 구현하는 것을 시도해보았다.

https://velog.io/@jasmine0714/firebase-authentication-firebase%EB%A1%9C-%EA%B5%AC%EA%B8%80-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0

이렇게 DOCS만 보고 함수를 만들면 구글로부터 사용자 정보를 제공받아 인증을 구현할 수 있다. 이렇게 "로그인 구현을 하고 싶으면 요렇게 죠렇게 하면 짠!"이라는 간단한 코드들이 전부 개발자인 나에게 API가 되는 것이다. 물론 나는 초보 개발자여서 쉽게 사용하라고 만든 '인터페이스'인데도 꽤 헤맸지만, 이 코드들을 만들어서 사이트에 공개하기까지 똑똑하신 분들이 얼마나 복잡한지도 모르는 절차를 설계하며 피땀눈물을 흘렸을지 상상도 못하겠다.

즉, 이 앱을 프로그래밍함에 있어서 사용자는 개발자인 나 쟤스민이고, 최종 사용자는 이 앱에 로그인하는 유저들일 것이다. (있을지는 의문이다 ㅋㅋㅋ) 복잡한 내부작업은 숨기고 필요한 기능만 사용자(개발자)에게 제공하는 도구 모음인 것이다. 그러한 도구 중에서도 프론트엔트 개발자가 가장 먼저 초점을 두고 공부해야 하는 API는 아마도 웹 API일 것이다.

웹 API 중에서도 HTTP 요청에 집중해보자.

웹 API에도 종류가 많지만, 클라이언트-서버 아키텍처로 어느 정도 범위를 좁혀서 웹 API의 한 종류인 HTTP 요청에 대해 설명하면 오늘의 주제인 REST API와 좀 더 가까워질 것이다.

자 이제 클라이언트의 컴퓨터 프로그램과 서버의 컴퓨터 프로그램 간의 리소스 요청과 응답을 위한 인터페이스로 범위를 좁혔다. 클라이언트 컴퓨터는 서버의 리소스(예컨대 HTML 파일, CSS 파일 등등)를 필요로 할 때 '그 리소스 좀 갖다주세요', '그 리소스 좀 수정해주세요' 등등의 요청을 하고, 서버는 요청에 맞게 응답한다. 이 때 어떠한 방식으로 요청을 해야하는지에 대한 규격이 바로 API이다. 사용자 인터페이스에서 크롬 아이콘을 클릭하는 것이 크롬 페이지 GET 요청을 위한 '규격'이라면, 클라이언트-서버 아키텍처에서는 클라이언트 컴퓨터 프로그램이 서버가 가진 리소스에 접근하는 방식이 바로 '규격'이자 API인 것이다. 그렇다면 대체 그 방식이 어떤 방식이고 규격이 어떤 규격인가?

  • HTTP 요청 형식으로 요청을 보냄
  • JSON 또는 XML의 형식으로 응답을 받음

등등 이것이 일반적인 HTTP 요청의 규격인 것이다.

즉, 정리하자면 웹 API인 HTTP 요청은 클라이언트가 서버의 리소스에 접근하기 위해 요청과 응답을 주고 받는 규격/방식이며, 정해진 규격/방식에만 집중하면 사용자(프로그래머)가 서버의 리소스에 접근하여 원하는 목적을 달성할 수 있는 인터페이스가 되는 것이다.

REST(Representational State Transfer)

REST를 소개한 로이필딩 선생림의 논문
https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

계속해서 클라이언트-서버 아키텍처를 전제하고 설명을 이어나가 보자.
REST는 HTTP를 기반으로 클라이언트가 서버의 리소스에 접근하는 방식을 규정한 아키텍처 디자인 원리이다. (demonstrated by 로이 필딩 선생림) REST 아키텍처 디자인 원리를 준수하여 API를 구현한다면 그 API는 REST API가 되는 것이다.

그렇다면 그 REST 아키텍처 디자인 원리라는 게 도대체 뭔데?? 로이 필딩 선생림 논문에 딱 나와있다. API가 진짜 RESTful한 API가 되기 위한 6가지 제한 조건부터 살펴보자.

https://restfulapi.net/rest-architectural-constraints/
https://www.geeksforgeeks.org/rest-api-architectural-constraints/

6 Architectural Constraints of REST

1. Uniform interface

REST API 제작의 가장 핵심이 되는 제약사항이다. 서버와 교류하는 방법에 일관성이 있고 요청과 응답에 정보가 충분히 들어있어야 한다는 규칙이다.
4가지 가이드라인도 있다.

  • Resource Based : 요청 시 개별 자원을 식별할 수 있어야 한다. (하나의 자료는 하나의 URL로)
  • Manipulation of Resources Through Representations:
    클라이언트는 서버의 데이터를 수정하거나 삭제함에 있어, 리소스에 대해 충분히 표현된 정보를 보유하며 이를 기반으로 한다.
  • Self-descriptive Messages: 각 메시지에는 서버가 요청을 쉽게 분석하여 메시지의 작업을 처리할 수 있도록 충분한 정보가 포함되어야 한다.
  • Hypermedia as the Engine of Application State (HATEOAS): 연관된 리소스를 찾을 수 있는 하이퍼링크가 있다면, 서버는 응답에 해당 링크를 포함해야 한다.

2. 클라이언트-서버

클라이언트-서버 아키텍처가 있어야 한다. 클라이언트는 리소스를 요청하고 서버 내부에 구축된 데이터와 관련이 없어야 하며, 서버는 리소스를 보유하고 사용자 상태와 관련이 없는 사람이어야 한다. 즉, 둘은 독립적이어야 한다.

3. stateless

stateless!! 코드스테이츠에서 HTTP의 큰 특징이라고 배웠는데, 로이 필딩 선생림 역시 HTTP에서 영감을 받았기에 stateless도 REST의 6가지 제약에 반영이 되었다고 한다.
앱에서 상태를 담당하는 것은 완전히 클라이언트의 영역이고, 서버는 상태와 무관하다는 의미이다. 모든 클라이언트의 요청을 상태와 독립적으로 처리한다는 의미이다. stateless는 추후 HTTP 포스팅에서 다시 자세히 다뤄보자.

4. cacheable

모든 응답에는 응답을 캐시할 수 있는지 여부와 클라이언트 측에서 캐시할 수 있는 기간이 포함되어야 한다. 캐싱이 잘 관리되면 보냈던 데이터를 또 보낼 일 이 줄어들기 때문에 성능 향상과 확장성에도 큰 도움이 된다.

최근에 본 아티클인데, Etag를 이용하여 클라이언트가 캐시를 운영할 수 있도록 설계할 수 있다고 한다. 아직 서버 지식이 부족해서 다 이해하기는 어렵지만 일단은 Etag를 이용할 수 있다는 점만 이해하고 나중에 서버 지식이 차오르면 다시 보는 걸루!
https://yozm.wishket.com/magazine/detail/1772/

5. layered system

클라이언트는 대상 서버에 직접 연결되었는지, 또는 중간 서버를 통해 연결되었는지 인지할 수 없다.

6. code on demand(optional)

REST API 설계 시 원칙:

URI → 리소스에 집중, HTTP 요청 메서드 → 행위에 집중

1) URI는 리소스를 표현해야 한다.

리소스를 식별할 수 있는 이름이 직관적이고 사용하기 쉬워야 한다. 이를 위해서는 동사를 사용하기보다는 명사를 사용하는 것이 좋다. 특히 HTTP 요청 메서드에 들어갈 동사가 들어가서는 안된다.

http://www.yes24.com/Product/Goods/102124327

요즘 눈독 들이고 있는 이펙티브 타입스크립트의 yes24 URL 예시이다.
엔드포인트에 명사를 사용하였으며 직관적이고 쉽다. 딱봐도 엔터를 누르면 상품번호 102124327번이 나올 것만 같다.

2) 리소스에 대한 행위는 HTTP 요청 메서드(GET, POST, PUT, DELETE)로 표현해야 한다.

URI에는 리소스의 이름이 표현되었다면, HTTP 요청 메서드에는 CRUD를 구현할 동사로 클라이언트가 서버에게 보내는 요청의 종류와 목적이 표현되어야 한다.

app.get("/mypage", isLoggedin, function (req, response) {
  response.render("mypage.ejs", { 사용자: req.user });
});

mypage get 요청을 할 때의 코드이다. 요청 메서드에는 get 뿐만 아니라 post, put,patch, delete를 사용할 수 있다. 중요한 것은 이러한 CRUD를 구현하는 메서드가 URI에 포함되면 안된다는 것이다.

REST 성숙도 모델

위에서 제시했듯이 API가 RESTful하기 위한 6가지 제약사항도 있지만, Web API가 REST원칙을 얼마나 잘 준수하고 있는지를 평가할 때 좀 더 실용적으로 적용할 수 있는 Richardson의 REST 성숙도 모델도 있다.

0단계부터 3단계까지로 분류하며, 높은 단계일수록 REST 원칙을 잘 지키고 있다는 의미이다.

부산으로 가는 기차를 예약하는 것으로 예시로 들어보자. 2가지 HTTP 요청이 필요하다고 가정하자.

  • 가능한 예약 시간을 확인하는 GET 요청
  • 가능 예약 시간 확인 후 실제로 기차를 예약하는 POST 요청


0단계 : The Swamp of Pox

HTTP 프로토콜을 사용하고 있기는 하지만, 하나의 URI 엔드포인트가 모든 작업을 다 포괄하고 있는 경우이다. 즉, 하나의 리소스에 하나에 URI가 배정되는 것이 아니므로 리소스가 제대로 정의되지 못한다. 0단계 정도로는 REST API라고 할 수 없다.

예약 시간 확인, 예약하기, 예약 삭제 하기 등등에 필요한 리소스들을 하나의 URI로 몽땅 퉁치는 것이다.

POST /bookReservation HTTP/1.1

1단계 : Resources

개별 리소스와의 통신을 준수해야 한다. 즉, 0단계와 달리 하나의 리소스에는 하나의 URI가 있어야 한다는 것이다. 요청하는 리소스가 무엇인지에 따라 각기 다른 엔드포인트로 구분한다. 이때 엔드포인트는 명사로 작성해야 한다.

POST /getReservationScheduleList HTTP/1.1
POST /bookReservation HTTP/1.1

0단계와 달리 나름 예약 가능 시간 확인 요청과 예약 요청 각각의 URI를 2개로 구분하였다.
다만 여전히 HTTP 메서드를 둘다 POST를 사용하고 있는데, getReservationScheduleList는 가능한 예약 시간을 확인하는 GET 요청을 하는 것이므로 개선이 필요해보인다.

2단계 : HTTP verbs

GET /reservationScheduleList HTTP/1.1
POST /reservation HTTP/1.1
DELETE /reservation HTTP/1.1

book이라는 행위를 나타내는 동사를 엔드포인트에서 제거하고 CRUD 작업을 나타내는 HTTP 요청 메서드를 보다 적합하게 활용하였다.
예약을 할 때와 예약을 삭제할 때 HTTP 요청 메서드를 각각 POST와 DELETE로 구분하니 1단계에 비해 1 리소스 1 URI에 보다 가까워졌다.

3단계 : Hypermedia controls

HATEOAS(Hypermedia As The Engine Of Application State)는 HTTP 응답에 관련 리소스의 URI를 포함한 링크 요소를 삽입하라는 의미이다.

예를 들어서 예약 가능 시간을 확인하는 GET 요청을 할 때, 예약 시간 달랬다고 서버가 진짜로 예약 가능한 시간만 보내주고 예약 가능한 링크는 없다면 곤란할 것이다.

요청

GET /reservationScheduleList HTTP/1.1

응답

HTTP/1.1 200 OK
.
.
  "links : {
     "reservation : {
          "href" : "http://srt.com/reservation",
          "method" : "POST"
          }
       }
.
.

참고:
https://enjoyinjoanne.tistory.com/56
https://www.hanl.tech/blog/api%EB%9E%80-api%EC%9D%98-%EC%A0%95%EC%9D%98%EC%99%80-%EC%A2%85%EB%A5%98-%EC%9E%A5%EB%8B%A8%EC%A0%90/
https://en.wikipedia.org/wiki/API
https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
https://github.com/googleapis/googleapis
https://www.javatpoint.com/what-is-rest
https://yozm.wishket.com/magazine/detail/1772/
https://jaehoney.tistory.com/176
코딩애플
https://prohannah.tistory.com/156
https://www.geeksforgeeks.org/rest-api-architectural-constraints/
https://restfulapi.net/resource-naming/
https://ko.wikipedia.org/wiki/REST
https://www.cleveroad.com/blog/what-is-an-api/

profile
기록에 진심인 개발자 🌿

2개의 댓글

comment-user-thumbnail
2023년 3월 29일

와 엄청 꼼꼼하게 본인만의 말로 설명해 주셔서 글이 술술 읽히네요! 역시 민선님👍 완성될 부분도 기대됩니다!

1개의 답글