티스토리 뷰
- 소개
캐치딜 서비스는 2019년 10월부터 시작된 토이프로젝트의 일환으로, 같은 대학 주니어 대학생 3명이서 똘똘뭉쳐 제작된 프로젝트입니다.
캐치딜은 여러 플랫폼(뽐뿌, 클리앙 등)에 퍼져있는 핫딜특가 데이터를 Selenium 크롤링을 통해 데이터를 수집해서 보여주는 서비스입니다.
- 캐치딜 : 앱 ↔ 웹의 통신 과정 살펴보기
캐치딜 앱에 보여지는 자료들은 앱 내에서 Database가 남겨져 있는 형식이 아닌, 앱에서 웹과의 통신을 통해 웹이 가지고 있는 Database 내 자료를 json으로 받아내어 데이터 결과를 보여주는 방식입니다.
위의 도식도를 좀 더 자세히 살펴보여드리겠습니다.
예를들어 만약 앱이 위와 같이 데이터를 보여준다고 치겠습니다.
그럼 이 데이터 같은 경우는 앱 내에 데이터베이스로 저장되어 있을까요??
아닙니다
아까와 말했다 싶이 위 데이터들은 앱 내에서 데이터베이스를 가진게 아니고, 앱은 웹서버와 통신 후, 웹서버 내 데이터베이스를 참고해서 보여주는겁니다.
앱에서 웹서버와 통신을 하게되면 웹서버는 위와같이 json 포맷을 통해 데이터를 Return하게 되어있습니다.
그리고 앱에서는 왼쪽 사진에 보이는 json 포맷을 참고해서 데이터를 보여주게 됩니다.
이게바로 캐치딜이 돌아가는 구조라고 보면 됩니다.
캐치딜에 있어 앱개발(프론트엔드 개발자)은 저와 함께 대학생활을 해왔던 형과 함께 진행한 프로젝트로, 캐치딜의 모든 시작은 이 형으로부터 탄생했다고 봐도 과언이 아닙니다.
Front-End 개발자와 개발을 하면서 저는 웹서버 설계 및 개발에 있어 앱과의 통신을 고려한 개발을 했어야 하는데, 그 시작이 바로 Restful API 설계라고 보면 됩니다.
- Restful API 설계의 과정
Restful API 설계의 과정은 다양한 경우의수를 전부 따져가며 설계를 해야할 필요가 있습니다. 또한 서버는 클라이언트에게 통신의 성공 부터 실패까지 전부 통틀어서 결과를 내뱉을 줄 알아야 합니다.
웹 개발자(Restful API)는 미래에 새로운 기능이 생기더라도 전체적인 규칙 양식에 변동이 없을 정도로 앞을 내다보며 통신 규칙을 설계를 해야할 능력이 필요하고, 앱 개발자는 웹 개발자가 설계한 대로의 통신 요청 규칙을 엄격히 지내며 최대한 서로의 약속을 잘 정해줘야 합니다.
1. 메소드
Restful API 설계에 있어 메소드는 기본적으로 5개의 약속이 존재합니다.
상황에 따라 어떤 메소드가 쓰일지에 대해 설계의 첫 째라고 보일 수 있습니다.
그러면 통신을 시도함에 있어서 메소드만을 보고 이 통신이 어떤 역할을 할지 가늠할 수 있습니다.
메소드 | 규칙설명 |
GET | 데이터를 조회할 때 많이 활용되는 메소드 입니다. |
POST | 새로운 데이터를 쓸 때(Write) 활용되는 메소드 입니다. |
PUT | 데이터를 수정할 때 활용합니다. (수정할 때 있어 전체 Data Column을 전송해야 합니다.) |
PATCH | 데이터를 수정할 때 활용합니다. (수정할 때 있어 일부 Data Column만 전송해도 됩니다.) |
DELETE | 데이터를 삭제할 때 활용되는 메소드 입니다. |
2. Params / Header / Body
통신 요청에 있어 요청 Parameter을 전송하는 방법은 크게 3가지 입니다.
하지만 Parameter을 보냄에 있어서도 아무렇게나 보내면 안되고, 어떤 상황이냐에 따라 잘 분간하면서 Parameter을 전송하고, 읽을 수 있어야 합니다.
1) Params
https://chm4674.run.goorm.io/apis/test?email=kbs4674@naver.com
Params는 흔하면서도 간단하게 URI 뒤에 Key / value를 붙이는 개념입니다.
하지만 이 방법은 별로일 수 있는게 Key가 URL에 노출됩니다.
인증 용도로서 사용은 부적합하고,
정렬 혹은 검색이 필요할 때 사용하도록 권장되고 있습니다.
2) Header
Header은 Key와 Value로만 표현이 가능하고, 보통 인증 혹은 인증 후 권한 확인을 위해 사용됩니다.
3) Body
{ "auth": { "email": "kbs4674@naver.com", "password": "123456" } }
API 통신을 통한 데이터 요청에 있어, 어떤 특정 데이터에 대한 응답을 받고자 할 때, 특정 정보를 요청할 때 사용됩니다.
보통은 Key, Value 표현에 있어선 JSON 형식으로 표현을 많이합니다.
여기서 유의해야할 사항이 있는데 JSON 방식을 통한 Body Parameter을 Request 및 서버에서 Json 검토에 있어, 요청 성격에 의거해서 소/중 분류로 나뉘어서 요청값을 받게 하는것을 권고드립니다.
옳은 예시
{ "user": { "id": "24", "password": "123456" }, "bookmark": { "id": "ko_156672" } }
나쁜 예시
{ "user_id": "24", "user_password": "123456", "bookmark_id": "ko_156672" }
3. URI 명칭
1) 언더바 표현 규칙
부록 [학학이] RESTful API 설계 가이드
URI 명칭을 통해 이름만으로 무슨기능을 하는지 유추할 수 있게 해줘야 할 필요가 있었습니다.
하지만 이름을 지을 때 명시해야할 부분이 있는,데 다른분이 작성한 개발문서에 따르면 이름 간 띄어쓰기 표현에 있어 언더바(_) 보단, 대시(-) 표현을 쓰는게 권고되어 있었습니다.
좋은 예시
[Get] http://example.com/product-list
나쁜 예시
[Get] http://example.com/product_list
2) URI 규칙 표시
부록
REST API URI설계
[Toast Blog] REST API 제대로 알고 사용하기
재미있는 REST API 파라미터의 종류와 개요
API 버전관리
URI 역할 표현에 있어 Method에 따른 URI 규칙을 잘 표현해야 합니다.
과거 캐치딜의 URI 표현 규칙은 위와같이 뭔가 일관성 없이 엉망이었습니다.
일단 위의 규칙에 있어 어떤게 잘못되었는지 살펴보겠습니다.
URI 디자인은 리소스를 중심으로 이루어져야 한다. 흔히 REST API를 설계할 때 URI에 동사를 넣지 말라는 것은 동사가 '리소스에 대한 작업'을 의미하기 때문이다.
REST API에서 리소스에 대한 작업은 HTTP 메서드를 사용해 정의된다.
URI에는 일관된 명명 규칙을 부여하는 것이 좋다. 컬렉션은 복수 명사를 사용하고, 단일 항목은 단수 명사를 사용하는 것이 권장된다. 이런 방식으로 리소스의 이름을 지으면 매우 직관적인 URI가 된다.
[GET] /bookmark-list
[POST] /bookmark-create
[DELETE] /bookmark-destroy
위 URI 규칙은 일단 띄어쓰기에 대한 표현을 하고자 언더바(_)가 아닌 하이픈(-) 표시에 대한 규칙은 잘 되었습니다.
하지만 resource의 명칭에 있어 문제가 있습니다. 이를테면 bookmark-create 처럼 말입니다.
- 컬렉션이라 불리는 메인 CRUD 명칭인 bookmark는 하나가 아닌 복수 개의 bookmark를 가지고 있으므로 bookmarks라고 표현하는게 적절합니다.
- CRUD의 행위에 대해선 동사를 넣지말 것, 즉 만들다(create) 등과 같은 CRUD를 표현하지 말 것이라는 규칙이 정의됩니다. 그래가지고 /bookmark-create 는 적절치 않습니다. (어차피 CRUD의 역할은 Method로 표현되어도 충분하기 때문입니다.)
위 규칙을 근거로 다시 URI 규칙을 정의해보면 다음과 같습니다.
[GET] /bookmarks
[POST] /bookmarks
[DELETE] /bookmarks
사실 이 외에도 URI 규칙에 대해 더욱 생각할 것은 많습니다.
하지만 지금 개발 케이스에 있어 적절한 예시가 없다보니 해당 글에서는 위 예시 하나로 마치고자 합니다.
이 외의 케이스는 부록에 첨부된 문서를 참고해주세요.
4. NULL VS ""
NULL이랑 ""는 전혀 다른 표현입니다.
표현 | 의미 |
NULL | 초기화 조차 되어있지 않은 표현 |
"" | 정의는 되어있으나, 비어있는 상태로 초기화 |
하루는 저와 클라이언트 개발자와 이런 약속을 따로 명확히 짓지 않다가, 한번 사고가 난 적이 있었습니다.
웹서버에서 어떤 값에 대해 ""로 Return이 되었었는데, 하필 앱에서 ""의 처리를 따로 내려주지 않았다 보니 앱이 이를 제대로 해석하지 못해서 맛이 갔다는 겁니다..ㄷ
이 이후로 저희는 Return되는 값이 아예 없다 싶으면 NULL로 Return하는 것으로 프론트/백엔드 개발자 간에 서로 약속을 했습니다.
5. Response Code 표현
앱에서 요청(Request)을 하게되면 웹은 당연히 응답(Response)을 하게 됩니다.
하지만 응답의 내용물인 Json을 받으면서 응답 코드 또한 기본으로 받게 되어있습니다.
응답코드는 각 성격에 따라 다양한 의미를 암시하고 있습니다. 클라이언트와의 통신에 있어서도 저희는 응답을 할 때 이 응답이 무슨 의미인지를 클라이언트에게 암시를 해줘야 할 필요가 있습니다.
응답코드 | 의미 |
200 | 데이터 작업 성공 |
201 | 데이터 작업 성공 (Post 작업인 경우) |
400 | 클라이언트가 부적절한 요청을 한 경우 |
401 | 클라이언트가 인증되지 않은 상태에서 요청을 한 경우 (비로그인 상태에서 요청 등) |
403 | 인증여부에 관계없이 응답하고 싶지 않은 요청을 해낸 경우 |
404 | 존재하지 않는 URI |
405 | 정의되지 않은 Method를 통해 요청한 경우 |
500 | 서비스(서버) 장애, 절대 사용자에게 눈에띄게 하지 말라. |
6. Json Response 정리
요청을 보낸 후, Json 방식으로 응답을 내뱉을 때 있어서도, '잘' 정리해서 응답을 내뱉어야 할 필요가 있습니다.
사실 이 내용은 어떻게보면 Body Parameter 규칙때의 설명과 비슷한데, 성격에 맞게 Json 형식을 '잘' 정리해서 응답을 하는게 좋다고 생각이 듭니다.
옳은 예시
## [옳은 예시] 북마크 생성 시
{
"message": "북마크가 생성되었습니다.",
"payload": {
"hitProduct" {
"id": 1532,
"title": "오리진 엑세스 베이직 내일까지 1018원입니다."
}
}
}
나쁜 예시
## [나쁜 예시] 북마크 생성 시 Response
{
"message": "북마크가 생성되었습니다.",
"bookmarkHitProducId": 1532,
"bookmarkHitProductTitle": "오리진 엑세스 베이직 내일까지 1018원입니다."
}
- 마무리
진짜 이번에 서비스를 개발하면서 느낀게, 제가 조금만 잘못해도 모든게 흐트러져버린다는 것을 깨닫게 됩니다.
아무래도 데이터베이스를 가지고있는 주체이다 보니 이런 상황이 벌여지게 겪는 것 같습니다..ㅠ
Restful API 설계를 함에 있어서 정말 이상한 상황에 대해서도 대비를 할 줄 알아야 하고, 앞으로 미래에 새로 생겨날 기능을 대비해야 하는, 그야말로 앞을 내다볼 줄 아는 설계가 크게 요구되는 경험이었습니다.
마지막으로, 이런 흔치않은 기회를 캐치딜을 통해 겨우 경험하게 되었는데 저의 뒤치닥을 해주면서 개발에 있어 많은 성장을 돕게 해준 프론트 개발자 형님께 정말 감사합니다.
- After Sotry (2020. 2. 7)
또 혼났다..ㅠㅠ
테스트를 더 꼼꼼히 해야겠습니다... 흑
- 읽으면 유익한 이야기
1. 프론트엔드와 백엔드가 소통하는 엔드포인트, RESTful API
- 캐치딜 개발 이야기 연결고리
1. 캐치딜 백엔드 개발이야기 : 좌충우돌 서버 설계 및 운영 이야기
5. 캐치딜 백엔드 개발이야기 : Restful API 설계의 다양한 고민
6. 캐치딜 백엔드 개발이야기 : 나에게 맞는 합리적인 서버 비용을 찾아서..
'개발 포토폴리오 > 캐치딜(백엔드) 개발 이야기' 카테고리의 다른 글
캐치딜 백엔드 개발이야기 : 나에게 맞는 합리적인 서버 비용을 찾아서.. (6) | 2020.04.11 |
---|---|
캐치딜 백엔드 개발이야기 : 크롤링 (3) | 2020.02.04 |
캐치딜 백엔드 개발이야기 : 디자이너와의 협업 (2) | 2020.02.04 |
캐치딜 백엔드 개발이야기 : 문서화 (0) | 2020.02.03 |
캐치딜 백엔드 개발이야기 : 좌충우돌 서버 설계 및 운영 이야기 (6) | 2020.02.03 |