뒤늦게 백엔드 개발자라는 꿈을 갖게 되면서, 최근 3개월 동안은 조급한 마음이 마음 한구석에 계속 남아있었던 것 같다. 그래도 주변의 좋은 사람들과 많은 이야기를 나누면서 고민하여 결론적으로 차근차근 하나씩 곱씹으면서 성장해보자! 라는 마음을 갖게 되면서 한 학기를 마무리 할 수 있었다.
그렇게 종강하자마자 바로 교내 해커톤인 동국톤...! 에 백엔드 파트로 참여하게 되었다. 최근 들어서 내가 기획에 참여할 수 있는 날이 학부 이후로 또 있을까 싶은 생각이 들면서 기획도 열심히 보조했던 것 같다. 그러면서 내가 아이디어를 내고 설득하는 과정에도 즐거움을 느끼는 것도 알게 되었다. ㅎㅎ
어쨋든, 배운 것도 많고 반성한 것도 많았던 동국톤을 다시 살펴보고자 이 글을 작성하게 되었다.
동국톤 주제는 아래 두 가지 중 하나를 선택하는거였다.
몇 번의 회의와 우여곡절을 거친 후 우리 팀이 생각한 아이디어는,
"다가오는 연말, 못 다 전한 진심을 전하는 투표 서비스 - 플러팅"이었다.
(다시 봐도... 디자이너가 너무 열일해주셨다. 새내기셨는데도 시험기간에도 시간 투자를 해주셔서 이렇게 예쁜 결과물이 나올 수 있었던 것 같다. 🙇🏻♂️)
주요 기능은 아래 4가지이다.
그룹 생성
: 플러팅에 가입한 사용자는 먼저 그룹을 생성하고, 초대링크를 주변 친구들에게 공유하여 그룹을 생성할 수 있다.
투표
: 그룹 안에서 주어지는 질문을 보고 가장 먼저 떠오르는 사람, 잘 어울리는 사람을 고를 수 있다.
투표 맞추기
: 투표가 끝나고 그룹 안에서 어떤 질문에 대해 가장 많이 득표한 사람은 누구인지, 또 나는 몇 표를 얻었는지 결과를 확인할 수 있다. 이 때 1표 이상 얻으면 나를 뽑은 사람을 추측하여 맞춰볼 수 있다.
눈꽃 크레딧
: 투표를 맞출 때 사용하는 눈꽃 크레딧이다. 한 번 투표를 맞출 때마다 10씩 사용하고, 만약 나를 투표한 사람이 누군지 맞춘 경우는 다시 15 크레딧을 얻게 된다. 그룹을 생성한 사람이 초대장을 보냈을 때, 그 초대장이 수락되었다면 초대장을 보낸 사람의 크레딧이 20씩 증가하도록 하였다.
여기서 나는 소셜 로그인을 제외한 나머지 API들을 맡아서 구현하였다.
명세는 위와 같이 url, method 뿐만 아니라 API 담당자, Web 담당자를 명시해서 더 빨리 소통이 이루어지도록 하였다. 무슨 API를 붙이다가 문제가 생기면 그 담당자에게 문의할 수 있도록 했다.
또 API 이름이 비슷해서 혼동이 있을 수 있을 것 같아 피그마 링크를 상단에 첨부하고, 그 피그마에 나온 화면 번호를 같이 기재해서 확실하게 알 수 있도록 하였다.
API 구성도 확신이 들지 않는 부분은 1안, 2안을 만들어서 프론트 분들께 제안하고, 상의 후에 결정하였다.
이번 프로젝트에서는 투표 질문 리스트를 한번에 전달하여 프론트 단에서 하나씩 넘기면서 처리할 수 있도록 할 것인지, 아니면 페이지 전환이 일어날 때마다 GET 요청을 보내서 투표 질문을 하나씩 받아올 것인지 물어보았다.
나는 처음에 한 번에 모든 질문을 주면 요청 횟수가 줄어들어서 그게 좋을 수도 있겠다고 생각했는데, 협업하시는 프론트 팀원 분은 뒤로 가기도 해보고 싶어서 질문을 하나씩 받아오는게 좋겠다고 하셨다...! 완전 생각 못하고 있던 부분이어서 물어보길 잘했던 것 같다
사실 이번 프로젝트를 하면서, 이렇게 코드를 작성하면 안될 것 같다는 생각이 계속해서 들었다.
try-catch로 에러를 처리하다 보니 어디서 에러가 발생한건지 파악할 수 없어 디버깅 시간도 오래 걸리고, 에러를 반환해야 하는 상황인데도 잡아내지 못하는 상황, 그리고 에러 응답에 중복되는 필드도 있어서 어떻게 고쳐야 할 지는 모르겠지만 어쨋든 고쳐야 한다...! 라는 생각이 강하게 들었다.
그래서 프로젝트가 끝난 후, 예외 처리 부분부터 뜯어보면서 알맞은 때에 에러를 반환하고, 클라이언트 입장에서 보다 직관적으로 이해할 수 있도록 ResponeDto를 재정의하고, Exception handler를 사용하도록 고쳤다.
완전 베이직한 API 구현만 할 줄 아는 상태에서, 에러는 그냥 어느 도메인에 속하는 일련의 컨트롤러-서비스가 던지고 처리하는 줄로만 알았다. 슬픈 일이지만 그 때 당시 나에게 예외 처리란 곧 try-catch 그 자체였기 때문에... 직접 정의한 custom error를 throw 한다고 해도 그 에러가 반환되지도 않는 상황이었다.
또 서버 내부 에러인 5xx 에러가 아닌, 다른 4xx 에러는 클라이언트에 책임이 있는 경우가 대부분이라고 알고 있었어서 서버에서 별도의 처리 과정을 거치지 않고 시스템 상에서 다른 처리 과정을 거치지 않을까? 라고 생각했었다.
[문제 정의]
동국톤 제출 마감이 2시간 전인 상황에서 동국톤 멘토를 찾아가서 4xx 에러도 서버에서 처리를 할 수 있는지, 또 스프링에서는 어떻게 예외 처리를 하는지 조언을 구했다.
그 때 말씀하신 내용을 간략하게 정리한 내용이다.
Global Error Handler
사용Custom ResponseDto
를 만들어서 쓰자@JsonIgnore
처리추가로 intercepter에 대한 언급과 boiler plate를 잘 짜놓는게 좋다는 등의 말씀도 해주셨다. ^_;
위 내용들을 중심으로 고수들의 깃허브를 뜯어보고 에러 핸들러 부분까지 리팩토링을 거치면서, 다른 사람의 코드를 뜯어보는게 얼마나 많은 도움이 되는지 다시 한 번 깨달았다. 생각해보면 깃허브에는 잘하는 사람이 엄청엄청 많을텐데, 그 사람들이 어떻게 코드를 짜는지 시간 공간 제약 없이 볼 수 있다는게 엄청난...! 기회라는걸 잊고 있었던 것 같다.
프로젝트를 진행하면서, 좋았던 점, 부족한 점, 새롭게 시도해 볼 점을 정리해보았다.
클라이언트(프론트) 분들과의 소통
: 프론트 개발 경험을 생각하면서 API를 호출하는 입장에서 더 좋은 API를 짜기 위해 여러 대안을 제시하고, 컨펌을 받았다.
API 명세
: API, Web 담당자를 명시하여 이슈에 대한 소통이 원활하도록 하였다.
주석 작성
: 내가 봐도 헷갈리는 부분에 주석으로 설명을 붙이거나 프로젝트 이후에도 개선해야 하는 점을 Todo 주석으로 달았다.
대면 만남 지향
: 팀 프로젝트에 있어서 가장 중요한 것 중 하나는 네트워킹이라고 생각한다...! 몇 번 만나서 개발하다보니 같이 밥도 먹고 친해지면서 더 잘 진행될 수 있었던 것 같다.
불명확한 에러 핸들링
: 가장 심각한 문제였다... 문제가 있어도 에러가 반환되지 않기도 하고, 내가 의도한 에러가 반환되는 것도 아니어서 테스트를 거칠 때 문제가 많이 생겼었다. 시간이 생명인 해커톤에서 특히 더 치명적인 문제였고, 가장 먼저 고쳐야한다고 느꼈다.
직관적이지 않은 응답 형식
: 나름대로 직관적이라고 생각한 형식이었는데, 코드를 작성하는 입장에서도 복잡하고 응답을 받는 입장에서도 완전 올바른 형식은 아니었던 것 같다. 필요 없는 값을 먼저 제외하고, 더 좋은 응답 형식은 어떤 형태일지 코드도 참고하고 고민해봐야 할 것 같다고 생각했다. 보기 쉽게 느낀다는건 주관적인 영역이어서 적절한 지점을 찾아야할 것 같다.
global error handler 정의
: service나 controller단에서 던지는 에러들을 캐치해서 에러 응답 정보를 가져온 후 응답으로 반환하는, 에러 핸들러를 정의하고 사용하도록 수정하였다.
response dto 수정
: exception 응답에서 HttpStatus는 클라이언트가 이미 알고 있는 정보이므로 @JsonIgnore로 안보이게 처리하였다. 또한 응답 형식 포맷에 성공 여부(success), data, exception으로 구분해서 성공/실패 여부를 바로 확인할 수 있게 하였다.
service단 반환 형식 수정
: 지금까지는 service에서 받은 정제된 데이터를 controller에서 response dto로 변환하는 방법을 사용했는데, 괜히 controller에 역할을 부여하려고 했었던 것 같다. 다른 분들 코드를 보니 대부분 controller의 코드는 정말 response dto에 service의 반환 데이터를 넣어서 클라이언트로 전달하는 것 뿐이었고, 그래서 코드가 대부분 한 줄로 끝났다. 굳이 응답 형식으로 가꾸는 과정을 나누어서 service와 controller가 담당하게 하지 말고, 서비스에서 한꺼번에 처리하는 코드로 바꿔보아야겠다.
결론적으로 "플러팅" 팀은 인프런 우수상을 수상했다~! 이번 동국톤의 협력사 중 하나가 인프런이었는데, 상금과 함께 인프런 수강권 쿠폰을 받게 되었다. 팀원들이 각자 최선을 다한 나름 이상적인 팀플이었던 것 같다. 지금 상태의 나로서는 받을 수 없었겠지만, 기획 디자인과 개발팀이 모두 합심해서 얻을 수 있었던 것 같다. 상에 걸맞는 사람이 되도록...^^ 열심히 해야겠다는 외적 동기를 마구마구 받을 수 있었다.
"플러팅"은 외국에서 먼저 흥했던 GAS라는 앱을 벤치마킹 해서 제안한 아이디어였다. 처음에는 팀원 모두의 동의를 얻지 못했던 아이디어기도 하고 구현을 다 할 수 있을지 걱정이 많았는데, 결국 수상까지 할 수 있어서 너무 좋았다... ;_; 그리고 심사위원 분께서 GAS를 벤치마킹한 건 좋은 시도다! 라는 말씀을 해주셔서 기분이 조금 더 좋아졌던 것 같다 ㅎㅎㅎ
연말을 기쁘게 장식해준 동국톤 플러팅 팀원들, 특히 제일 고생해준 기획과 디자인 파트분들 모두 앞으로도 하시는 일이 다 잘 되었으면 좋겠다. 다들 너무 감사합니당 🙇🏻♂️🫶🏻