리나 Dev토리

Restful API 설계하기 본문

SpringBoot 개인플젝(TodayMaker)

Restful API 설계하기

리나lina 2022. 12. 21. 01:13

현재 컨트롤러는

페이지를 응답하는 URI와 

에서 form으로 요청한 것을 처리해주는 컨트롤러만 개발했었다.

 

Restful API용 컨트롤러를 추가 개발하기 위해

URI, 메소드 등 부터 설계하였다.

 

Restful의 개념은 알고 있었지만

먼저 "URI 리소스 명명 가이드" 를 보며 다시 한 번 리마인딩하며 

아래와 같이 정리하였다.

리소스 - 명사
ex) 사용자, 디바이스
http://api.example.com/device-management/managed-devices 
http://api.example.com/device-management/managed-devices/{device-id} 
http://api.example.com/user-management/users
http://api.example.com/user-management/users/{id}
더 명확하게 하기 위해 리소스 종류를 네 가지 범주(문서, 컬렉션, 저장소 및 컨트롤러)로 나눔.
그러면 항상 리소스를 하나의 범주에 넣은 다음 명명 규칙을 일관되게 사용하는 것이 가장 좋습니다 .

문서 - 단일 리소스 - 단수
http://api.example.com/device-management/managed-devices/{device-id}
http://api.example.com/user-management/users/{id}
http://api.example.com/user-management/users/admin

컬렉션 리소스: 서버에서 관리하는 리소스 디렉터리 - 복수형
클라이언트는 컬렉션에 추가할 새 리소스를 제안할 수 있습니다.
http://api.example.com/device-management/managed-devices
http://api.example.com/user-management/users
http://api.example.com/user-management/users/{id}/accounts

클라이언트 관리 리소스 저장소 - 복수형
http://api.example.com/song-management/users/{id}/playlists

컨트롤러: 컨트롤러 리소스는 절차적 개념을 모델링
매개 변수와 반환 값, 입력 및 출력이 있는 실행 가능한 함수와 같습니다. - login
"동사"를 사용하여 컨트롤러 원형을 나타냅니다.
http://api.example.com/cart-management/users/{id}/cart/checkout 
http://api.example.com/song-management/users/{id}/playlist/play

일관성이 핵심입니다
모호성을 최소화하고 가독성과 유지 관리성을 극대화하기 위해 일관된 리소스 명명 규칙과 URI 형식을 사용

슬래시(/)를 사용하여 계층적 관계
http://api.example.com/device-management
http://api.example.com/device-management/managed-devices
http://api.example.com/device-management/managed-devices/{id}
http://api.example.com/device-management/managed-devices/{id}/scripts
http://api.example.com/device-management/managed-devices/{id}/scripts/{id}

하이픈(-)을 사용하여 URI의 가독성 향상
사람들이 쉽게 스캔하고 해석할 수 있도록 URI를 만들려면 하이픈(-) 문자를 사용하여 
긴 경로 세그먼트에서 이름의 가독성을 높이십시오.
http://api.example.com/devicemanagement/manageddevices/
http://api.example.com/device-management/managed-devices 	/*much better version*/

밑줄( _ )을 사용하지 않기
프로그램의 글꼴에 따라 일부 브라우저나 화면에서 밑줄(_) 문자가 부분적으로 가려지거나 숨겨질 수 있음

URI에 소문자 사용
가능한 한 URI 경로에서 일관되게 소문자를 사용하기
http://api.example.org/my-folder/my-doc     //1
HTTP://API.EXAMPLE.ORG/my-folder/my-doc     //2
http://api.example.org/My-Folder/my-doc     //3 - 대문자도 사용(비추)

파일 확장자를 사용하지 않기
헤더를 통해 전달되는 미디어 유형(Content-Type)에 의존하여 본문의 콘텐츠를 처리
http://api.example.com/device-management/managed-devices.xml  /*Do not use it*/
http://api.example.com/device-management/managed-devices 	/*This is correct URI*/

URI에 CRUD 함수 이름을 사용하지 않기
URI는 리소스를 고유하게 식별하는 데만 사용되어야 하며 리소스에 대한 작업이 아닙니다.
어떤 CRUD 기능이 수행되는지 나타내기 위해 HTTP 요청 메소드를 사용해야 합
HTTP GET http://api.example.com/device-management/managed-devices  //Get all devices
HTTP POST http://api.example.com/device-management/managed-devices //Create new Device

HTTP GET http://api.example.com/device-management/managed-devices/{id}  //Get device for given Id
HTTP PUT http://api.example.com/device-management/managed-devices/{id}  //Update device for given Id
HTTP DELETE http://api.example.com/device-management/managed-devices/{id}  //Delete device for given Id

쿼리 파라미터를 사용하여 URI 컬렉션 필터링
정렬, 필터링 또는 제한되는 리소스 목록이 필요할 때
리소스 컬렉션 API에서 정렬, 필터링 및 페이지 기능을 위해 입력 매개 변수를 쿼리 파라미터로 전달
http://api.example.com/device-management/managed-devices
http://api.example.com/device-management/managed-devices?region=USA
http://api.example.com/device-management/managed-devices?region=USA&brand=XYZ
http://api.example.com/device-management/managed-devices?region=USA&brand=XYZ&sort=installation-date

 

그리고 한국정보과학기술정보연구원에서 작성한  "Open API 명세서 작성 가이드라인"를 살펴보았는데

 

좋은 점은

  필수 여부, 숫자 범위, 기본값 이 정의되어 있어서 좋았고

  메시지 교환 유형 등 디테일한 사항까지 있어서 좋았다.

 

restful 하지 않아 아쉬운 점은

  path에 카멜케이스를 사용

  url 에 .jsonp 확장자 표시

 

그리고 변수명이 fullname이 아닌 압축된 약어로 적혀있어서,

따로 이를 설명하는 주는 표를 참고해야 한다.

 

Today Maker 프로젝트 Restful API 명세서 초안을 엑셀에 작성하였다.

(전에는 노션에 적었는데 노션 database는 사용성이 아쉬운 점이 있어서, 이번엔 엑셀로 작업)

 

기능별로 URI 설계하는 과정에

Best Practice를 찾는 게 어려운 항목도 있었다.

 

바로, 로그인

어떤 사람은 /users/login 어떤사람은 /oauth/~~ 어디에서는 /user/refreshToken 

한참을 서치해보다가 

결국 처음에 봤던 'URI 리소스 명명 가이드'에 답이 있었다. 

/login에 대한 가이드 관리자의 답변

 

로그인, 로그아웃은 그냥 /login, /logout으로 써도 된다는 것!!

 

로그아웃에 id를 안넣어도 되는 이유는

  보통 로그인 하게되면, 요청할 때마다 헤더에 토큰 값을 전달하므로

  로그아웃시 id를 전달해주지 않아도 된다.

 

그리고 또 여기서 logout의 http 메소드는 뭘로 써야 Best일까?

궁금하여 찾아보았다.

 

"Should Logging Out Be a GET or POST?" 라는 글을 보고

 

  로그아웃이 get이면 link가 공개되었을 때 문제가 될 수 있고,

  스프링 시큐리티에서도 로그아웃 기본값이 POST이다.

  Get은 컨텐츠를 조회하는게 의도이므로, Post로 명시적인 요청을 보내는 게 좋다는 걸 알게되었다.

 

그렇게 완성한

1차 API 설계 결과

리소스는 명사, 복수 형태로 표현하고

to do는 자주 쓰이는 관용적인 단어이므로 명사취급하고 s를 붙여주었다.

리소스에 대한  행위는 모두 HTTP 메소드로 구분하였고

/login, /logout컨트롤러 리소스에 해당하므로 동사로 표현하였다.

 

카테고리를 추가할 때 부모카테고리 ID는 없을 수 있어서 필수가 아님을 알려주었다.

 

요청 바디 Json의 key는 카멜 케이스(camel case)로 해주었다.

 

path variabledash-case로 해야하고,

쿼리 파라미터(쿼리스트링)은 사용하는 곳마다 다 다른데, 

대문자를 따로 구분안하는 시스템도 있어서 소문자를 권장한다.

  - 윈도우는 대소문자를 구분안하고, 리눅스는 대소문자 구분함

 

현재는 최소한의 기능만 구현한 상태라

이후에 기능을 추가하고 점진적으로 확장하면서, API도 같이 보완할 예정이다.

 

참고

https://restfulapi.net/resource-naming/

[KISTI] Open API 명세서 작성 가이드라인

https://www.baeldung.com/logout-get-vs-post

https://covenant.tistory.com/241

 

Comments