Deep Dive into RESTful API

hyob·2020년 4월 28일
2

'What is RESTful API?' 의 내용이 아니라😂
최근 API를 설계했던 경험에 대해 공유하는 글이에요.
자소설닷컴의 백엔드 애플리케이션은 Ruby on Rails로 만들어져 있지만,
RESTful API는 함께 생각해볼 수 있을것 같아요.😄

이번 작업은 자소설닷컴의 채팅 서비스를 약간 업그레이드 하는 것 이었어요.
개인별로 채팅목록을 좀 더 편하게 관리할 수 있도록 했습니다.

저는 백엔드 애플리케이션과, iOS클라이언트 작업을 진행했어요.
다음 글에서는 iOS개발 과정에서 있었던 이슈들을 공유해 볼게요🏃🏻‍♂️

이전 채팅 서비스

채팅 리스트 - 그룹별로 섹션이 나누어져 있지만, 유저가 다룰 수 없어요. 정해진 섹션을 서버에서 보내주고 있습니다.

내 채팅 - 유저가 참여한 채팅방 리스트. 에디팅 모드는 없고, 채팅방 안에서 '나가기'를 할 수 있어요.

요구사항

위와 같았던 채팅리스트를 앞으로는 좀 더 유저가 사용하기 편하게 바꾸려 하고 있어요!
이번에는 크게 3가지 요구사항이 있었습니다.👀

  1. 채팅을 그룹별로 관리 할 수 있어야 한다.
  2. 편집모드에서 한번에 여러 채팅방을 삭제할 수 있어야 한다.
  3. 채팅 목록을 접었다 펼 수 있어야 하고, 상태가 저장되어야 한다.

더 있는것 같은데, 백엔드 관련해서는 이정도로 추릴 수 있을것 같아요!

리소스

기존에는 User, Chat, ChatUser 정도로 채팅 서비스를 운영하고 있었어요.
User와 Chat은 M:N관계로 chat_users를 조인 테이블로 이용했어요.
그래서 내가 참여하고 있는 채팅방들은 다룰 수 있었습니다.

하지만 이제 내가 참여한 채팅방들을 그룹별로 관리할 수 있도록 해야해서, ChatGroup 을 새로 만들었어요.
User : ChatGroup = 1 : N
ChatGroup : Chat = M : N

의 형태입니다.

필요한 API

  1. 유저의 채팅그룹 리스트를 가져오는 것
  2. 유저의 채팅그룹을 업데이트 하는 것
  3. 유저의 채팅그룹에서 채팅방을 추가/삭제 하는것
  4. 유저의 채팅 목록에서 채팅방을 추가/삭제 하는것

api/v1/chat-groups

먼저 채팅그룹 리소스를 다루는 API를 만들었어요.

namespace :api, defaults: { format: :json } do
  namespace :v1 do

     ...

     resources :chat_groups, path: 'chat-groups', only: [:index, :update]
  end
end

config/routes.rb

레일즈 코드입니다

  1. GET /api/v1/chat-groups
  2. PATCH(PUT) /api/v1/chat-groups/:id

두개의 엔드포인트가 생성되요. 기본적인 형태죠?

하지만 이것은 ChatGroup에 '바로' 접근하는 형태라 마음에 들지 않았어요.
저는 'User'의 ChatGroup리소스를 다루고 싶었거든요.

그래서 chat-group 앞에 user를 붙이기로 했어요!

그런데 두 가지 생각해 볼 부분이 있었어요..🤣

1. resources VS resource

첫번째는 복수형이냐 단수형이냐 문제입니다.
보통 API에서 리소스를 다룰때, 복수형으로 하곤 하잖아요?
그래서 저도 처음에 복수형 resources를 이용했습니다.

namespace :api, defaults: { format: :json } do
  namespace :v1 do

     ...
     
     resources :users, only: [] do
       resources :chat_groups, path: 'chat-groups', only: [:index, :update]
     end
  end
end

config/routes.rb

결과는
GET /api/v1/users/:user_id/chat-groups
라는 엔드포인트가 만들어졌습니다!

하지만 또 마음에 들지 않았어요😱

이 형태는 전체 유저풀에서 user_id로 유저를 조회해, 그 유저의 chat_groups 를 찾는 느낌이랄까요?
물론 이것도 틀린 것은 아니에요. 경우에 따라 필요하고, 쓸 수 있는 형태라고 생각합니다!

그래서 일단 's'를 빼고 단수형으로 바꿔봤습니다.

  ...
  
    resource :users, only: [] do
    
  ...

이제 GET /api/v1/user/:user_id/chat-groups 가 되었습니다!

그래도 아직이더라구요.🥶😥

2. resource VS namespace

이번에 필요한 API는 '나의 채팅그룹들' 을 조회하는 엔드포인트였어요!
내 것을 찾으면 되는데, 쿼리 파라미터로 user_id를 넘겨 리소스를 조회 하는것은 좀 이상하다? 생각했어요.

레일즈 라이브러리인 Devise에서는 user_signed_in?이나 current_user라는 메소드도 이미 존재하고 있고,
컨트롤러에서 before_action :authenticate_user! 로 로그인을 강제할 수 있기 때문에, 파라미터로 user_id를 넘기지 않기로 결정했습니다!

그래서 resource키워드 대신, namespace를 사용하기로 했어요🤗

namespace :api, defaults: { format: :json } do
  namespace :v1 do

     ...
    namespace :user do
      resources :chat_groups, path: 'chat-groups', only: [:index, :update]
    end
  end
end

config/routes.rb

최종적으로

  1. GET /api/v1/user/chat-groups
  2. PATCH /api/v1/user/chat-groups/:id
    의 형태가 되었어요.✌🏻

길이 좀 글어지는것 같아 나누어서 포스팅 하겠습니다!
'Deep Dive'라고 했지만 여기까지는 사실 큰 고민 없었고,
다음 편에서 이야기할 부분이 좀 볼만 하실 것 같아요😅

'many to many 관계를 끊어주는 엔드포인트?' 로 다음 포스팅을 이어가겠습니다!

profile
앵커리어에서 자소설닷컴을 개발하고 있습니다.

1개의 댓글

comment-user-thumbnail
2020년 4월 28일

두번째 찬준👏

답글 달기