저번주에 내내 머리를 쥐어뜯는 일이 있었다..
그래서 해당 문제에 대해서 뭐가 잘못됬으며 어떻게 해결했는지 정리하고,
관련된 req.param / req.query / req.body에 대해서도 포스팅을 해보려 한다.
우선 관련 개발 명세서는 이러했다.
명세서를 보고 되게 단순해서 금방 개발을 할 줄 알았다.
해당 유저가 키워드를 팔로우할 uuid를 req POST로 보내주면 끝이였다.
문제1
path: /api/follows/{uuid}
parameters: Body() , { “keyword_uuid” : ~~~ }
상황:
stg swagger, insomnia에서 같은 URL과 같은 Token 넣고 Post할 시 DB에 정상적으로 쌓임
하지만 개발중인 웹에서 같은조건으로 진행시 제대로 안됨.
DB에는 원하는 데이터가 아닌 NULL값이 쌓임.
이 같은 증상을 보고 URL에는 /api/follows/{uuid} 인 반면
Body()에는 “keyword_uuid”를 넣어서 맞지않아서 안될수도 있겠다 판단.
따라서 Path를 수정하기로함.
문제2
path: /api/follows — path 수정
parameters: Body() , { “keyword_uuid” : ~~~ }
DB에 값 아예 안쌓이고 stg swagger, insomina, 웹에서 전부 Error나옴
Body 여태 왜 명세서 req{"uuid"}랑 맞지않게 "keyword_uuid" 를 넣었지..? 이제서야 알아차림
@Param으로 req 해보기로 결정
문제3
path: /api/follows/{uuid}
parameters: Param() , uuid: ~~~ — Param으로 변경
드디어 정상작동. DB에 정상적으로 잘 쌓임
결론
이렇게 헤맬문제가 아닌데 너무 돌아와버렸다.
우선 첫 실수는 Param / Query / Body 를 제대로 알고 있지못해서 생겼다.
여태 많은 케이스를 안다뤄봐서 그런지 단순히 POST에는 body를 써야된다고만 인지하고 있었다.
path는 명세서대로 해서 /api/follows/{uuid} 지만 파라미터는 body만 넣어서 RESTful하지 못했다.
그러고 막상 넣은 Body의 내용은 "uuid"도 아니고 "keyword_uuid" 였다. 세상에나..
이 케이스에서는 Param을 쓰는게 맞는 방법이였다.
하지만 아직도 의문이 좀 있는건
왜 문제1로 했을때 swagger랑 insomina에서는 정상적으로 데이터가 쌓였을까..?
내 머리속에는 문제1에서도 문제2처럼 에러가 나오고 DB가 아예 안쌓여야된다고 생각한다.
이 내용을 chatGPT한테 물어보았다.
웹과 Swagger/Insomnia 간에 데이터 전송 방식에 차이가 있어 웹에는 null 값이 기록되고 Swagger/Insomnia에는 유효한 값이 기록될 수 있습니다.
한 가지 잠재적인 원인은 두 가지 방법에서 사용되는 데이터 형식 또는 인코딩의 차이일 수 있습니다. 예를 들어 데이터가 Swagger/Insomnia에서는 JSON으로 전송되지만 웹에서는 다른 형식으로 전송되는 경우 백엔드에서 데이터를 제대로 구문 분석하지 못하고 null 값을 기록할 수 없습니다.
Swagger/Insomnia에서는 Body의 JSON을 읽어서 잘나오고
웹에서는 다른형식으로 받아서 Body의 JSON을 읽지 못한다는 얘기인것 같은데 여기까진 알겠다.
그러면 문제2에서 전부 에러나오는건 Swagger/Insomnia에서도 JSON을 받지 못한다는건가..?
이부분에 대해서는 데이터형식과 인코딩과 서버 https통신에 대해서 좀 더 스터디를 하고 다음에 꼭 다시 확인해봐야겠다.
애초에 여기서 에러가 발생했으면 금방 해결했을텐데 여기서는 정상적으로 작동하니깐 다른 부분을 의심했다.
해당코드에 트랜잭션을 사용하고있었는데, 이부분에서 복잡하게 여러번 읽기와 업데이트가 이루어 지고있어서
유령데이터(phantom read)가 아닌가 코드를 전부 뜯어서 고치느라 시간을 많이 잡아먹었다.
무튼 이렇게 돌아오면서 하나씩 세세하게 확인하느라 req.param / req.query / req.body랑 트랜잭션에 대해서 많이 알게되었다.
그리고 아무리 급하게 하더라도 RESTful한지 고민하면서 개발을 해야겠다.
이제 문제의 시발점이였던 req.param / req.query / req.body 에 대해서도 제대로 정리를 해보자.
Request 객체는 API를 컨트롤하기 위한 메소드를 담고 있다.
1. req.param
Param은 셋중 제일 단순하다.
주소에 포함된 변수를 담는다.(엔드포인트에 일부이다)
원하는 조건의 데이터나 하나의 데이터를 받아올때 적절해서 Unique한 값이 들어와야한다
ex) GET /api/follows/{uuid}
2. req.query
엔드포인트 ? 이후에 나오며 변수를 담는다.
key = value로 이루어져 있고 &로 연결할 수 있다.
조건은 줘서 정제된 결과물을 얻어서 filtering, sorting 에 적절하다.
ex) GET /api/follows?keyword_type=normal
3. req.body
URL에는 보이지 않는 오브젝트 데이터(JSON,XML,등)를 담는다.
주로 POST를 사용하여 JSON 오브젝트를 req.body안에 넣어서 보낸다.
req.body에 key-value 데이터 쌍을 포함한다.
주소에서 확인할 수 없고 정의되어 있지않아서 미들웨어를 사용해야한다.
'Error' 카테고리의 다른 글
[Error] 504 Gateway Timeout Error 해결: Nginx와 로드밸런서 타임아웃 (0) | 2023.09.16 |
---|