본문 바로가기

개발/Review

우리에게 REST API란?

 

최근 Thiago Marini라는 개발자가 Medium에 작성한 "Guys, REST APIs are not Databases"을 읽게 되었다.

 

해당 글은 REST 방식의 Open API를 구성할 때 개발자가 고민해야 할 점을 이야기하고 있다.

 

Thiago Marini는 REST API를 만드는 개발자들이 흔히 REST API를 데이터베이스처럼 다루는 실수를 하고 있다고 말한다.

 

"REST(Representational State Transfer)"는 말 그대로 어떤 프로토콜로 ‘무언가’의 상태를 전송하는것을 의미한다. 일반적으로 HTTP가 선택되며, 무언가는 리소스(Resource)를 의미한다. 그리고 상태(State)란 리소스의 스냅샷(Snapshot)이다.

 

많은 문서들이 GET: Read, POST: Create, PUT or PATCH: Update, DELETE: Delete와 같은 표현을 많이 사용한다.

 

Thiago Marini 또한 이러한 매칭은 자연스러운 흐름이라고 말한다.

 

하지만 많은 개발자가 REST API를 데이터베이스와 밀접하게 연결 지으면서 REST의 요점들을 놓치게 되는 문제가 발생한다고 주장한다.

 

데이터베이스의 목적은 데이터의 보관이며, API는 구성 요소가 서로 어떻게 상호 작용하는지에 관한 것이기 때문이다.

 

그리고 DB 스키마에 맞춰 API를 만든다면 시간이 지남에 따라 API가 애매하고 유지하기 어려워질 가능성이 높아지는 문제가 발생할 수 있다고 경고한다. API는 다양한 Context를 지원해야 하고, API를 통한 결과가 다양하게 바뀔 수 있기 때문이다.

 

특히 "시간"과 같은 데이터는 단지 GET을 통해 알 수 있고, POST를 통해 다른 날짜를 생성할 수 있다. 이것은 데이터베이스가 필요 없는 것이다.

 

그렇다면 어떻게 올바른 REST API를 작성할 수 있을까

 

 

 

사용자의 Context에 맞춰 API 만들기

 

Thiago Marini는 API와 수화물 리소스를 가진 해상운송회사를 예로 들고 있다.

 

그리고 구매자, 판매자, 수송사가 수화물 리소스를 같은 관점에서 보지 않는다고 말한다.

 

각 사용자들은 수화물 리소스의 관점을 갖고, API를 통해 각기 다른 일을 하기를 원하기 때문이다.

 

구매자는 수화물에 대한 가격 지불과 배송 추적을 원하며, 판매자는 재고 및 배송에 대해 걱정할 뿐이다. 그리고 수송사는 수화물의 면적과 무게, 목적지에 대해서만 신경쓴다. (so it goes!)

 

이런 상황에서 API가 모두 하나로 된 One-In-All 솔루션을 만들어 위 세명의 사용자에게 제공한다면, 결국 지나치게 유지보수하기 어렵고 개선하기 어려운 애매한 API가 될 수 있다.

 

즉, 사용자의 Context 별로 구성되지 않은 One-In-All 솔루션은 지나치게 거대해 질 수 있는 문제점을 가진다는 것이다.

 

따라서 Thiago Marini는 각 사용자의 Context 별로 3개의 전문화된 API가 구성되어야 한다고 말한다.

 

구성된 세 가지의 API는 데이터 수준에서 높은 결합으로 인해 동일한 프로젝트에서 위치해야 할 수 있어야 하며, 대부분의 최신 웹 프레임워크가 하위 도메인 또는 접두사 라우팅을 지원하므로 이를 고려하여 분이 구현된 API가 동일 프로젝트에 위치하여 구현이 가능하도록 해야 한다는 것이다.

 

사실 위의 구성에서 "굳이 이러한 복잡함이 필요할까" 라는 생각이 들지만 바라보는 관점에 따라 해석이 다를 수 있다고 생각한다.

 

많은 사람들이 따르고 있는 MSA(Microservice Architecture) 조차도 사람들의 관점에 따라 수 많은 단점들이 존재하며, 대표적인 디자인 패턴인 MVC 역시 마찬가지이기 때문이다.

 

나는 실제로 RESTful하지 못한 REST API를 경험했고, 심지어 이를 직접 작성하고 있었기 때문에 이러한 논의는 항상 바람직하다고 생각한다.

 

REST API를 떠나 옳고 그름과 좋고 나쁨의 경계가 아닌 현재보다 더 나은 구조를 위해 나아가려는 고민은 항상 즐겁기 때문이다.

 

다시 Thiago Marini의 글로 돌아가보자.

 

그렇다면 컨텍스트를 알 수 없을 때는 어떻게 할 수 있을까?

 

Thiago Marini는 만약, API를 너무 많은 사용자가 사용하여 도저히 컨텍스트를 확인하기 어렵다면 이를 인정하고 포용해야 하며, API 사용자를 돕기 위해 최선을 다해야 한다고 말한다. (나는 이 문장을 통해 Thiago Marini가 더 나은 REST API 구조를 위한 아키텍처를 제시하려는 것이지 REST API 구조에 대한 정답을 말하려는게 아니라는 것을 느꼈다.)

 

그리고 GraphQL과 같은 기술을 통해 API에게 질의하고 정보를 얻어갈 수 있는 권한을 사용자에게 줌으로서, 작은 조작을 통해 많은 것을 변화시킬 수 있다고 말한다.

 

GraphQL은 클라이언트가 필요한 데이터의 구조를 지정할 수 있고, 서버는 정확히 동일한 구조로 데이터를 반환한다. 즉, GraphQL은 사용자가 어떤 데이터가 필요한지 명시할 수 있게 해주는 API에 대한 Query Language다.

GraphQL은 특정 데이터베이스나 스토리지 엔진과 연결되어 있지 않은, 기존 코드와 데이터에 의해 뒷받침되는 서버 측 런타임이다.

 

최근 지인에게 평소에 GraphQL을 쓰다가 불가피하게 REST API를 사용하게 되서 너무 불편하다는 말을 들었다.

 

아직 GraphQL을 사용해보지 않았는데 곧 GraphQL을 사용해 본 후 REST API와 비교한 포스팅을 작성 해야겠다. (TMI)

 

다시 글로 돌아가보자!

 

 

 

하지만, 제 API는 작다구요. 더 복잡해지는 것을 멈춰주세요! (But my API is too small, stop overcomplicating thigs!)

 

그렇다. 누군가 화를 내기 시작한 모양이다.

 

Ok, ok.

 

Thiago Marini는 이에 대해 크기와 범위는 직접적인 관계가 있으며, API가 작을수록 범위 또한 좁아진다고 말한다. (it`s a no-brainer.)

따라서 API가 작다면 설계에 따라 모호(ambiguous)하고, 일반적(generic)일 것이며, 컨텍스트도 필요하지 않기 때문에 CRUD와 REST 엔드포인트를 단순하게 매핑할 수 있다고 말한다.

 

하지만 해당 API의 개선을 주시(close-eye)해야 하며, 스스로 API의 유지보수를 위해 타입이나 조건을 추가하려 한다면 지금까지의 내용과 접근법을 고려해야 한다고 말하며 글을 끝내고 있다.

 

 

 

마치며

 

이 글을 읽은 후 글에서 언급되는 'Guys"는 내가 아닐까라는 생각을 하게 되었다.

 

지금까지 많은 REST API를 작성하고, 사용왔지만 이 글을 통해 정작 REST의 특징을 자세히 이해하고 있지 못했다는 것을 느꼈기 때문이다.

 

내가 작성했던 REST API를 보더라도 데이터베이스에 의존성이 없는 API는 없다. 그리고 이것이 문제를 일으킬 수 있다고 느낀 적이 없었다. 그 이유는 스스로 REST에 대한 깊은 이해가 없었기 때문일 수도 있겠지만 데이터베이스와의 관계에서 파생되는 의존성의 문제점을 느끼지 못했기 때문이다.

 

물론 경우에 따라 위에 언급한 "시간"과 같은 케이스가 필요 없을 수도 있고, 작은 규모에서는 굳이 필요하지 않을 수 있다.

 

하지만 이 글의 목적은 REST API 구조에 대한 정답을 제시하는 것이 아니라고 생각한다. 위에서 언급했듯 Thiago Marini는 REST API에 대한 더 나은 아키텍처를 제시할 뿐이다.

 

편하고 익숙한 흐름 속에서 REST의 특징을 잊고, 데이터베이스와 밀접한 관계를 가지는 REST API만을 떠올리는 나와 같은 개발자에게 꼭 한 번 읽어보라고 추천해주고 싶은 글이다.

 

 

원글: https://medium.com/@marinithiago/guys-rest-apis-are-not-databases-60db4e1120e4


 

 

 

안녕하세요. 평범한 대학생 개발자 yorr입니다.

포스팅을 읽고 궁금한 점 또는 문의가 있으신 분은 메일 또는 댓글을 남겨주세요.

 

Mail: twysg@likelion.org

Github: https://github.com/sangyeol-kim