Post

Restful하다는건 뭘까?

Restful하다는건 뭘까?

Restful하다는 것

사이드 프로젝트에서 API 개발을 진행하던 중, 좋은 인사이트를 얻게 되어 글을 남긴다.


프로젝트 상황과 초기 설계

이번 스프린트에서는 사용자와 사용자를 연결하는 기능을 맡게 되었다.

어떤 사용자가 특정 사용자에게 연결을 요청하고,
해당 요청을 받은 사용자가 수락하거나 거절하여 최종적으로 연결 여부가 결정되는 구조였다.

처음에는 사용자 요청과 연결을 별도의 객체로 분리해서 설계하려고 했지만,
결국 하나의 객체 내에서 상태로 관리하는 쪽으로 방향을 잡았다.

수락 시 데이터를 거의 그대로 가져와 새로운 연결을 생성하기보다,
단일 객체에서 상태만 변경하는 방식이 더 간단하다고 판단했다.
또한 요청부터 수락까지의 이력을 하나의 객체에서 관리할 수 있는 장점도 있었다.
(물론 상태 관리를 해야 한다는 trade-off는 존재한다.)

그래서 Connection이라는 객체를 만들었고,
이 안에 요청자, 수신자, 상태 등 연결에 대한 전반적인 정보를 담았다.


처음 만든 API와 그 한계

초기 조회 API 설계는 아래와 같았다.

의존성 구조
해당 API 명세서

당시에는 리소스 중심으로 Restful하게 만들었다고 생각했다.

하지만 프론트엔드 팀에서도, 같은 팀과도 소통하면서 이는 좋은 API가 아님을 깨달았다. 직관적으로 생각했을 때 연결과 연결요청은 분리되어 있다고 생각하여 이 하나의 API에서 State를 통해 가져올 수 있다고 생각하지 않는다는 것이다.

또한 이 API 구조에서는 클라이언트가 “Connection이라는 객체 내부에서 state로 상태를 관리한다“는 사실을 알고 있어야 제대로 요청을 보낼 수 있었다.
문서를 꼼꼼히 본다면 유추할 수는 있겠지만, 직관적이지 않았고 클라이언트 입장에서 불친절했다.


Restful의 진짜 의미에 대한 재고

이 문제를 계기로 다시 한 번 “Restful API란 무엇인가?“에 대한 고민을 하게 되었다.

그동안 나는 “일관된 인터페이스로 상태를 담지 않고 리소스 중심으로 설계한다” 정도로만 이해하고 있었는데,
이번 기회에 더 찾아보던 중 양질의 글을 찾을 수 있었다.
Rest의 representation이란 무엇인가

Rest의 첫 글자는 Resource가 아니라 Representational임에 주목할 필요가 있다.
우리가 반환하는 것은 리소스 그 자체가 아니라,
리소스의 특정 상태를 담은 표현(Representation)이다.

그리고 이 표현은 DB 테이블 구조에 종속될 필요가 없다.
오히려 DB에 종속될수록 Restful하지 않은 API가 될 수 있다.
클라이언트가 직관적으로 이해할 수 있도록 리소스를 표현하는 것이 더 중요하다.

기존의 GET /api/connections?state=pending 방식은
잘못 설계되었다고 할 순 없겠지만,
클라이언트가 서버 내부 state 모델에 의존해야 했기 때문에
서버 구현 변경 시 클라이언트가 영향을 받는 구조였다.


최종 API 변경과 얻은 교훈

그래서 최종 API는 아래와 같이 변경했다.

  • GET /api/connections/requests/sent
  • GET /api/connections/requests/received
  • GET /api/connections

이제는 클라이언트가 파라미터 없이
Path만으로도 원하는 리소스를 직관적으로 표현할 수 있게 됐다.

서버 내부 구현에 대한 의존도도 크게 줄어들었고,
가독성과 직관성 모두 개선됐다.

이번 경험을 통해 “Restful API의 진짜 의미“를
몸으로 체감할 수 있었다.

앞으로 API 설계 시에는 단순히 DB 모델링 중심이 아니라,
“클라이언트가 직관적으로 이해하고 사용할 수 있는 리소스 표현”
이 점을 최우선으로 고려할 것이다.

참고자료

Rest의 representation이란 무엇인가

This post is licensed under CC BY 4.0 by the author.