엘리스 SW 트랙에서 총 2주간 진행되는 1차 프로젝트를 진행하고 있다. 랜덤으로 인원이 매칭되어 우리 조는 나를 포함한 2명의 백엔드, 3명의 프론트엔드로 구성되었다. 현재 매일 오전 11시에 팀 디스코드에서 모여서 당일 수행할 작업에 대해 의논하기 위해 스크럼 회의를 진행한다. 또한 현재 우리 팀 프로젝트의 방향이 제대로 흘러가는지, 놓치고 있는 것은 없는지 등에 대해서도 팀원들과 얘기를 나눈다. 약 일주일 간 오전 11시부터 새벽 2~3시까지 작업을 진행하고 있는데, 이 과정에서 내가 알게된 것은 다음과 같다.
팀 내 규칙을 정할 때는, 프로젝트의 규모도 고려해야 한다.
팀프로젝트 1일차에는 팀 협업과 관련된 다양한 규칙을 정하는데 시간을 썼다. 예를 들면 코드 컨벤션 정하기, 팀 협업 툴 결정하기, 커밋 메시지 형식 정하기, 브랜치 전략, 코어 참여 시간 등등... 팀에서 지켰으면 하는 것들을 모두 정하였다. 그리고 당일 저녁에 진행된 백엔드 코치님과의 오피스아워 시간에 '2주짜리 프로젝트에 너무 과도하게 많은 규칙을 정하는 것은 오히려 개발 속도를 늦출 수 있다.' 라는 조언을 받게 되었다. 앞으로는 팀 규칙을 짤 때 팀 프로젝트 기간을 고려해야겠다는 생각이 들었다.
정확한 목표 설정과 구체적인 작업 과정을 정리하는 것이 당장 개발을 시작하는 것보다 훨씬 중요하다.
본격적으로 개발을 시작하기 이전에 구현할 기능 정도만 정리하고, API 명세서를 작성한 뒤 바로 개발에 들어갔다. 그렇게 전반적인 어플리케이션의 흐름도를 그려보지 않고 각자 맡은 부분을 개발하다보니 개발 중간에 팀원들끼리 생각한 기능의 동작 방식이 달라 어떤 방식으로 구현할지를 그때그때 정하는 일이 빈번해졌다. 그럴수록 전반적인 앱 동작 방식에 대해 모두가 공감하고 도식화해서 갖고 있는 것이 중요하다고 생각했고, 앞으로는 최대한 도식화된 흐름도를 만들어 팀원들 모두 앱 동작 방식을 이해하고 개발을 진행해야겠다고 생각했다.
CSR 방식으로 개발하는 방법
기존에 내가 개인적으로 진행해온 프로젝트는 모두 서버에서 사용자가 볼 화면을 그려주는 SSR(Server Side Rendering) 방식이다. 그런데 이번 프로젝트에서는 프론트엔드 팀원들의 의견으로 CSR(Client Side Rendering) 방식을 사용하게 되었다. CSR은 단순히 데이터만 전달해주면 되는 거 아닌가? 라는 생각을 갖고 있었는데, 생각보다 흐름이 복잡해서 CSR 방식 자체에 대해 공부하게 되었고, SSR과 CSR의 전반적인 흐름 차이에 대해 배울 수 있었다.
SSR 방식과 CSR 방식의 차이점은 정리하면 다음과 같다.
SSR 방식은 브라우저로부터 HTTP Request를 받은 서버가, 알맞은 라우팅 핸들러에 이를 전달하고, 라우팅 핸들러는 자신이 맡은 일을 수행한 뒤에, 브라우저가 표시할 화면이 담긴 html 파일을 res.render 통해 그려준다.
CSR 방식은 브라우저로부터 HTTP Request를 받은 서버가, 알맞은 라우팅 핸들러에 이를 전달하고, 라우팅 핸들러는 브라우저의 표시할 화면이 담긴 html 파일의 위치를 돌려준다. 그 후 html 파일에 연결된 js 파일에서 현재 화면에 필요로하는 데이터를 서버의 API로 fetch를 통해 요청하면 서버는 res.json으로 브라우저가 요청한 데이터를 제공하고, 원하는 데이터를 제공 받은 브라우저는 해당 데이터를 이용해 브라우저에 표시할 화면을 그린다.
핵심은 각 HTTP 요청에 대해서
SSR 방식은 서버가 직접 브라우저에서 표시될 화면을 그려준다는 점이고,
CSR 방식은 일단 html 파일을 불러오고, html 파일에 연결된 js 파일에서 fetch를 통해 서버로부터 직접 데이터를 받아와서, 자신(js 파일)이 원하는 대로 화면을 그린다는 점이다.
JWT 토큰을 이용한 로그인
나는 기존에 세션을 이용하는 Stateful 로그인 방식에 대해 익숙해져 있었는데, 이번 프로젝트에서 JWT 토큰을 이용하는 Stateless 한 로그인 기능을 구현하게 되었다. 이론적으로 JWT 토큰을 사용하는게 크게 어렵다고 생각은 하지 않지만, 이를 CSR에 접목하려다보니 많은 경우를 고려하게 되었다. 이를테면
SSR + JWT 토큰 방식은 서버가 HTTP Request를 받으면, 일단 유저가 갖고 있는 쿠키에서 jwt 토큰을 찾아 jwt 검증을 수행한다. 검증에 성공한 경우 로그인한 유저 정보를 DB에서 찾아 다음 미들웨어로 넘기면, 해당 미들웨어에서는 이전 미들웨어로부터 받은 유저 정보를 이용해서 브라우저에게 화면을 그려주면 된다.
하지만 CSR + JWT 토큰 방식은 서버가 화면을 그려주지 않고, 프론트에 존재하는 JS파일이 서버로부터 받아온 데이터를 이용해 직접 화면을 그리기 때문에 해당 JS파일에게 JWT 토큰의 검증 결과로 로그인한 유저를 돌려줘야 해당 유저 정보를 이용해 화면에 그려낼 수 있다. 따라서 앱에 존재하는 모든 html 파일에 연결된 js파일에서, 일단 서버로 JWT토큰에 대한 검증 요청을 보내고, 서버로부터 JWT 토큰 검증 결과로 로그인 한 유저를 받아온 뒤에, 서버로부터 받은 유저 정보를 이용해서 화면을 그리도록 하였다.
이렇게 같은 JWT토큰 방식이어도 앱이 SSR으로 동작하냐, CSR로 동작하냐에 따라 많은 부분이 바뀐다는 것을 알게 되었고, JWT토큰에 대한 이해와 함께 SSR/CSR 의 차이점에 대해서도 배울 수 있었다.
RESTful한 API 설계 방식
기존에는 URL의 path 값으로 동사가 들어가면 안된다고 배웠다. 하지만 특정 데이터를 생성하기 위해 또는 수정하기 위해서는 필수적으로 생성 form 또는 수정 form 이 들어간 화면이 그려져야하는데 이럴 때는 예외적으로 동사가 들어갈 수 있다는 것을 새로 알게되었다.
예를 들어 상품 생성 페이지와 상품 수정 페이지에 대한 요청 URL은 다음과 같이 정할 수 있다
상품 생성 페이지 : /products/create
=> 상품의 생성 form이 있는 페이지
상품 수정 페이지 : /products/:pid/edit
=> pid번 상품의 수정 form이 있는 페이지
이 밖에도 라우터 배치 순서의 중요성, 4계층(Router <-> Controller <-> Service <-> Model) 구현 방식, 에러 처리 미들웨어 동작 방식, mongoose 스키마 생성 시 유의할 점 등 많은 것을 배웠지만, 모두 정리하기엔 힘들 것 같다. 이것들은 모두 좋은 개발자가 되기 위한 경험치라고 생각해야겠다.
생각보다 팀 프로젝트에 쏟는 시간이 많기 때문에, 마감 기한인 토요일 오후까지는 팀 프로젝트에 올인하고, 주말에 지원할 기업에 대해 찾아보고, 개인 프로젝트를 진행하고자 한다.