본 프로젝트를 마친 후 끄적여보는 회고
ft_transcendence
는 42 공통과정의 마지막 프로젝트이다. 본 프로젝트의 목표는 실시간 웹 Pong game 서비스를 만드는 것이다. 웹 사이트는 Single Page Application 이어야 하며, 42 intranet OAuth 로그인을 통해 계정을 생성할 수 있어야 한다. 유저 인터페이스를 통해 친구 기능, 차단 기능, 프로필 기능 등을 제공해야 하며, 실시간 채팅, 실시간 Pong game을 할 수 있어야 한다.
웹개발이 처음인 5명이 모여 프론트 3명, 백 2명으로 나눠서 javascript 공부부터 시작했다. 2주 정도 다 같이 스터디하면서 기초적인 문법만 훑고 바로 typescript로 넘어갔다. 그리고 백은 NestJS와 PostgreSQL, 프론트는 React와 각종 라이브러리 사용법을 각자의 방식으로 익혔다. 숙달될 때까지 공부만 하면 한도 끝도 없기 때문에 어느정도의 사용법만 익히고 역할 분담을 하여 무작정 시작했다. 모두가 처음이기 때문에 디자인, 문서화, API 설계 등의 형식과 기준들을 처음부터 체계적으로 정하지 못하고 하면서 그때그때 필요에 따라 회의를 거쳐 정하고 수정했다.
프론트는 로그인, 유저 / 채팅 / 게임으로 역할분담을 했고 백은 로그인, 유저, 게임 / 채팅으로 나눠서 진행했다. 물론 막판에 가서는 역할 분담의 경계가 흐려지긴 했다.
로그인은 42 intranet OAuth를 통해 최초 계정 생성 후 할 수 있게 구현했다. 채팅과 게임은 SocketIO를 통해 실시간 서비스를 구현했다.
구현만 3개월 가량 진행하면서 정말 많은 시행착오와 난관들을 겪었지만 결국 목표한 바대로 프로젝트를 완성했고 고된 과정 속에서 많은 것을 배웠다. 오로지 구현하는 것에만 집중했기 때문에 사실 올바른 방법으로 구현했는지는 모르겠다. 너무 무지한 상태에서 시작했기 때문에 끝난 시점에는 아쉬운 점도 많았고 다시 하면 더 체계적이고 효율적으로 잘 할 수 있을 것 같았다. (그래서 끝나고 경험자가 많은 팀에서 같은 프로젝트를 한 번 더 진행했다.)
처음에는 행복한 프론트 나라에서 혼자 즐겁게 개발을 하고 있었다. 하지만 실질적으로 백 나라에 API 요청을 하기 시작한 이후로는 모든 응답을 무수한 시뻘건 에러줄로 받았다. 눈을 씻고 찾아봐도 요청 코드에는 문제가 없었다. 평화롭던 프론트 나라에 CORS라는 빌런이 나타난 것이다. CORS가 무엇인지 알고나서는 백엔드 개발자에게 부탁해서 손 쉽게 해결할 수 있었지만 당최 CORS가 뭔지 모르던 시절의 나에게는 가혹한 나날들이었다. CORS 넌 도대체 누구냐?
Cross Origin Resource Sharing
CORS는 한 도메인 또는 Origin의 웹 페이지가 다른 도메인 (도메인 간 요청)을 가진 리소스에 액세스 할 수 있게하는 보안 메커니즘이다.
CORS는 서버와 클라이언트가 정해진 헤더를 통해 서로 요청이나 응답에 반응할지 결정하는 방식으로 CORS라는 이름으로 표준화 되었다. CORS는 최신 브라우저에서 구현된 동일 출처 정책(same-origin policy) 때문에 등장했다.
동일 출처 정책은 동일한 출처의 리소스에만 접근하도록 제한하는 것이다. 출처(Origin) 라는 것은 Protocol 과 Host 그리고 Port 까지 모두 합친 URL이다.
동일 출처 정책은 브라우저에서 임의로 하는 것이다. 즉 브라우저를 통하지 않고 요청을 보내거나 브라우저에서 동일 출처 정책이 아니라면, 동일 출처가 아니라도 요청을 보내고 응답을 받을 수 있다. 브라우저는 보안상의 이유로 HTTP 호출을 동일한 출처로 제한했다.
가뜩이나 쓰는 라이브러리가 많은 프론트엔드에서 웹 개발이 개발이 처음인 나에게 사용하는 모든 라이브러리들의 공식문서를 본다는 것은 엄청난 부담이었다. 그래서 사용법이 간단하게 설명되어있는 블로그들만 참고해서 빠르게 구현하는 것을 목적으로 개발을 했다. 처음에는 생각한대로 다 구현이 되서 신나게 만들었다. 하지만 기능들이 추가되고 서비스가 무거워질 수록 에러들이 잦아졌다. 엉뚱한 길로 열심히 달리고 있었던 것이다. 멀리 간만큼 돌아오는 길도 멀었다. 애초에 잘못된 방법으로 설계하고 구현하고 있었기 때문에 잘못됨을 직감하고 나서는 전체 구조를 흔들어야 하는 끔찍한 현실을 마주했다.
하나의 사건으로는 리액트 훅 규칙 위반 에러가 있었다. 상황 별로 여러가지 커스텀 훅을 만들어 재사용하고 있었을 때였다. 훅 사용 규칙 따위는 가뿐하게 간과하고 코드를 짜고 있었는데 컴포넌트가 많아지고 기능들이 추가되면서 또 처음보는 에러들이 등장했다. 리액트 훅 규칙을 위반했다는 에러였다.
리액트 훅 규칙이라고 해봐야 함수 최상위에서만 훅을 호출해야 한다는 것과, 리액트 함수 내에서 훅을 호출해야 한다는 간단한 2가지 규칙 밖에 없었다. 조건문과 중첩된 함수 내에서 훅을 실행하려고 했던 내 로직은 훅 1번 규칙을 위반한 것이다. 애초에 이런식으로 설계를 하고 구현하던 나였기에 로직 자체를 엎어야 하는 상황이 발생했다. 사실 공식문서의 훅 사용 규칙 몇 줄만 읽어봤어도 일어나지 않았을 일이었다.
이 외에도 react query를 사용하면서 공식문서를 제대로 참고하지 않아 골머리를 앓은 시간들이 많다.
프레임워크나 라이브러리 등을 사용할 때는 공식문서의 정확한 사용법을 참고해야 함을 뼈저리게 느꼈다.
나는 로그인과 유저 부분을 맡았고 다른 프론트 두 분이 각각 채팅과 게임을 맡았다. 다들 프론트 개발이 처음이기도 하고 초반에는 각자가 맡은 부분만 신경쓰기도 버거웠어서 회의도 자주하지 못하고 서로의 코드도 자세히 리뷰해주지 못했다. 각자가 자신이 맡은 바를 잘 해내고 있다는 안묵적인 믿음이 있었다. 정기적으로 모여 현황을 나누고 어려움이 있다면 같이 고민하고 해결했어야 했는데 그러지 못했다. 사실 했다고 생각했는데 턱없이 부족했었던 것 같다. 게임을 맡으신 분과 나는 적어도 이틀에 한 번씩은 만나서 상황을 공유했는데 채팅을 맡으신 분은 거의 혼자 작업하시는 타입이라 소통이 부족했다. 그럴수록 더 적극적으로 연락하고 물어보고 현재 작업 상태 공유를 요구했었어야 했는데 워낙 내향적이신 분이기도하고 무소식이 희소식이라고 잘하고 계시겠거니 내 것에 집중했다.
시간이 꽤 지나고 나는 기능구현을 거의 다 끝내고 백엔드와도 합쳐 테스트 해보고 있을 때 채팅을 맡으신 분은 이제 백엔드와 붙이기 시작하고 있었다. 서로 각자 개발하다가 막바지에 합치려니 의견 충돌이 꽤 있는 것 같았다. 그때서야 나도 채팅 쪽 코드를 자세히 보게 됐는데 꽤나 문제가 많아보였다. 결국 의견차이를 좁히지 못하고 채팅을 맡으시던 분이 하루아침에 연락이 두절되어 버렸고 그 역할을 내가 떠안게 되었다. 짜여진 코드가 좋은 상태도 아니었어서 다시 처음부터 다 짰다. 백엔드 채팅 분과 매일 만나 최대한 빠르게 구현하긴 했지만 완성은 원래 일정보다는 많이 늦어지긴 했다.
갑자기 나갔다고 해서 그 분만 탓하기엔 나머지 인원들에게도 책임도 있다. 애초에 정기적인 회의를 갖고 프로세스를 문서화하고 개인간의 소통을 중요시해야 했다. 개인의 개발 능력보다 중요한 것이 소통임을 깨달았다. 결국엔 다 사람이 하는 일이기 때문이다. 처음이라 몰랐던 부분이긴 하지만 다들 반성해야 할 부분이다.
ft_transcendence
을 마지막으로 42 본과정을 시작한지 2년만에 공통과정을 돌파했다. 홀가분하면서도 이제는 진짜로 실전을 마주해야 한다는 부담감이 몰려왔다. 2년간 느끼고 배운점이 참 많지만 ft_transcendence
을 하는 3개월이 조금 넘는 기간 동안 제일 느끼고 배운점이 많다. 전부터 해보고 싶었던 웹 프론트엔드를 공부하고 실제 서비스를 구현할 수 있어서 힘들고 어려웠지만 동시에 보람과 재미도 있었다. 모든 프로젝트 통틀어서 애정을 갖고 제일 열심히 했던 것 같다. 분명 아쉬운 점도 많다. 리펙토링과 최적화가 필요한 부분이 정말 많다. 애초에 로직이 좀 어색한 부분도 있다. 당연한 결과이다. 애초에 시작할 때 최대한 시행착오를 많이 겪어보고 개발 인생 마지막 대실패작을 만들어보자는 생각으로 했기 때문에 후회는 없다. 이 경험을 살려 이번엔 실제 배포까지 계획하고 있는 팀에 합류해서 한 번 더 본 프로젝트를 진행하게 되었다. 이미 웹 서비스 배포를 해본 팀이어서 확실히 체계적이고 개개인의 실력들이 뛰어나 배울 점이 많다. 올해 늦여름 42파리로의 트랜스퍼를 계획하고 있는데 트랜스퍼 준비하면서 가기 전까지 새로 합류한 팀에서도 끝까지 열심히 해야겠다.