👨💻 올해 첫 팀프로젝트
학교에서 캡스톤 디자인(졸업 작품)으로 첫 팀프로젝트를 하게 되었습니다. 처음에는 6명이 모였지만 마지막에는 5명으로 끝냈습니다. 한 분은 소통이 잘 안되고 개발 시작 후 학교도 잘 안나와서 결국 그 분에게 맡긴 분야는 다른 분들이 나눠서 가지게 되었습니다. 그래도 우여곡절 끝에 잘 마무리하여 다행입니다.
언어와 기술을 학습과 동시에 사용한다는 것은 많은 노력과 시간이 필요하지만 어떠한 부분에서는 간단한 것도 많았습니다. 공식문서의 위대함도 알았으며 잘 정리된 문서는 가독성이 있어서 빠른 이해와 개발을 할 수 있었습니다. 개발하면서 생기는 에러들과 다양한 프로젝트에서 만날수 있는 공통적인 경험들이 쌓이면서 빠른 대처도 가능해졌습니다. 역시 경험은 무시할수 없네요. 또한 학습하고나면 어떠한 것이든지 만들어봐야 제대로 이해가 되는것 같습니다. 추후 다시 학습하더라도 '그 땐 그랬었지' 라면서 빠르게 이해가더라고요.
그렇다면 첫 팀프로젝트를 하면서 생겼던 이슈들은 뭐가 있을까요? :)
🚀 첫 번째 위기, 기술 스택
당시 기술 스택과 실력을 생각해보면 다음과 같습니다.
- Java (기초)
- Spring Boot (기초)
- Node.js (대부분 잘 모름)
- Vue.js (기초)
- React.js (아무도 모름)
- SQL (기초)
- JPA (나만 알고있음)
미리 공부하기는 했지만 제대로 된 방향을 못잡고 JPA부터 학습했었습니다. 백엔드 3명, 프론트 2명에서 무슨 기술을 사용하여 프로젝트를 개발할지 정해야 했었는데, 저는 백엔드여서 Spring Boot 와 JPA를 사용하자고 하여 선택되었고, JPA를 먼저 학습한 만큼 같이 스터디하고 필수 정보는 문서화하여 공유했습니다. 프론트는 제가 "Vue보다 React가 커뮤니티도 크고, 많이 사용하여 문제해결하기 쉽고, 국내 유명 스타트업에서도 많이 사용하고, 추후 React Native의 기반이 되므로 앱을 만들 때 빠르게 개발 가능하다"라는 의견에 React를 사용하게 되었습니다.
지금 생각해보면 이 때를 되돌리고 싶습니다. 당시 교수님께서도 Vue.js를 가르쳐주셨기에 인터넷보다는 교수님께 바로 물어보고 에러를 고치는게 좋았던 것 같습니다. Vue.js의 장점을 생각해보면 다음과 같습니다.
- 교수님으로 인해 빠른 피드백과 에러 해결
- 학교 성적도 자연스럽게 챙김
- 학교 수업 때 사용했기에 React보다 쉬움
- 다른 프로젝트 조들도 Vue.js를 사용했기에 물어볼 친구들이 있음
위 장점들을 생각해본다면 더 빠른 개발을 했지 않았을까 싶습니다.
React 학습하면서 CSS도 적용, 카카오 맵과 정부 Open API 등 활용한 여러 페이지들을 생각해본다면 어려운 부분들이 많았습니다. 그래서 백엔드도 같이 페이지 개발을 하면서 React를 배웠습니다. 다행히 UI 라이브러리인 Material-UI를 사용했기에 빠른 CSS를 적용하며 개발했습니다. (React 넘 재밌던데....) 새로운 기술을 학습하면서 개발에 적용시키던 프론트 팀원들이 힘들어하는 모습을 보니 모두가 저처럼 공부만 하는게 아니라 휴식도 가지면서 천천히 나가는 것을 알게 되었고, 팀원들을 좀 더 객관적으로 생각해서 기술 스택 선정에 좀 더 깊은 고민을 해야했다는 것을 깨달았습니다. (Vue 잘 몰랐는데도 React랑 공통적인 부분들이 있었던 것 같아서 A학점 받았다는 사실)
또한, 다음 위기에 말할 보안에 대해서도 오버 엔지니어링을 한게 아닐까 싶었습니다.
오버 엔지니어링은 당장 필요한 것을 넘어서서 개발 확장성, 서비스 성장 가능성을 고려하면서 부가적으로 기술을 사용하는 것
현재 서비스와 비즈니스 상황에 따라서 적절하게 타협하면서 적정 엔지니어링을 하는게 중요했지만, 처음 하는 팀 프로젝트여서 여러가지 신기술도 써보고 싶었고 하나를 만들 때 다양하게 고민하면서 그에 대한 대안을 사용해보고 싶었습니다. 결과적으로는 엄청난 오버 엔지니어링이 아닌가 싶습니다. 기술 부채를 쌓더라도 적절하게 기술 스택을 선정하는 것 그것이 개발자가 생각해야 할 판단력인 것 같습니다.
🚀 두 번째 위기, 로그인과 보안을 어디까지 해야할까요?
제가 맡은 분야에서 로그인과 보안이 있었습니다. 잠깐 학습했던 Spring Security가 있었기에 바로 도입하여 간단하게 로그인을 구현했지만 더 찾아보니 보안에 대해 너무 쉽게 생각하고 있었습니다. 바로 "해커의 존재"와 "멀티 서버"를 생각하지 않았기 때문입니다. 사실 서버 1개만 돌리기에 Scale-Out을 생각하지 않아도 되었고 그로 인한 단점이 명확했던 세션을 사용했어도 되었습니다. 그렇지만 세션 로그인보다는 Stateless하고 확장성이 높은 토큰 로그인이 좋아보였습니다.
로그인을 하면 '인증'이 되었기에 토큰을 발급해줍니다. 서버는 더 이상 사용자의 정보를 유지하지 않으며, 사용자는 토큰으로 자기 자신임을 인증할 수 있습니다.
👍 JWT 토큰의 장점
- Stateless(무상태)하기에 서버 부담을 줄임
- 서버 확장의 용이성
👎 JWT 토큰의 단점
- Stateless해서 서버가 인증 작업을 수행하지 않음
- 그에 따라 서버가 인증 토큰에 대한 제어권이 없어서 관리할 방법이 없어짐
- 토큰 탈취 시 서버에서 없앨 수 없음
- 쿠키가 아닌 경우 localstorage와 같은 브라우저 내장 storage를 사용해야 해서 XSS로 인한 토큰 탈취 가능성 높아짐
✅ JWT 토큰 해결 방안
- Redis를 통해 JWT Blacklist 구현하여 서버에서 토큰에 대한 제어 수행
- Stateful 토큰을 추가하여 서버에서 Stateful 토큰을 통해 제어 수행
-> 결국 Stateless 토큰을 어느정도 Stateful하게 만들어주는 것이다.
이런 생각으로 인해 기존에 JWT 토큰을 Refresh Token과 Access Token으로 나누었고, Refresh Token을 발급받을 당시의 클라이언트 IP를 Redis에 저장시키고, 추후 Refresh Token이 들어오면 IP를 비교를 하는 로직을 개발하였다. 은행사이트에서 사용하듯이 Access Token은 만료시간이 짧게 주어지고 만료됐다면 Refresh Token으로 재발급해준다. 물론 HTTPS로 쿠키보안이 적용되어 있다.
지금 생각해보면 '퍼스널 모빌리티를 활용한 길찾기 서비스와 가게 선주문 및 결제'가 들어간 프로젝트인데 은행권처럼 Refresh Token까지 만들진 않아도 될 것 같다. 이걸 처음 구현하면서 엄청나게 코드가 복잡해졌고, 개발하는 것도 힘들었다. 결과적으로는 다 만들었지만 여기에 약 1주일은 거의 밤새면서 로그인과 보안에 대해 학습했었다. 하지만 JWT 토큰 로그인을 대체할만한 로그인이 요즘같이 멀티 서버에다가 OAuth2 까지도 만연하기에 마땅하게 생각나지도 않는다. 그러므로 적절하게 AccessToken만 사용하면서 Blacklist를 구현하는것도 나쁘진 않은 것 같다.
📚 느낀점
🚀 공식문서와 문서화
잘 정리되어 있는 공식문서는 교보재와 같아서 이해가 잘 되었다. 반대로 잘 정리되지 않은 공식문서는 정말 이해가 가지 않는다. (이는 추후 Socket.io를 학습하면서 깨달음) 그리고 회의나 느낀점 등을 가독성있게 문서화해놓으면 도움이 많이 된다. 특히 백엔드와 프론트엔드와의 협업에서 가독성있는 API 명세는 서로의 개발능력을 잘 끌어올리는 것 같다.
🚀 커뮤니케이션
팀원끼리 좋은 관계를 유지하면서 개발하는 것은 좋은 것이다. 개발이 즐거워지고 서로의 의견도 적극적으로 피드백할 수 있기 때문이다. 그렇다고 너무 노는 것은 절대 안된다.
'신뢰'와 '충돌'이라는 말이 있다. 서로에게 신뢰있는 토론은 좋은 토론이지만, 신뢰가 없는 토론은 서로에게 상처만 주는 충돌일 뿐이다.
커뮤니케이션의 중요성은 프론트와 백이 같이 협업할 때 더욱 크게 느꼈는데 '서버에서 데이터 가공 후 보내는 것'과 '브라우저에서 데이터 가공하는 것'에 대한 의견 차이도 생길 수 있기 때문이다.
🚀 개인적인 학습과 노력
나는 클린코드를 추구했다고 생각했지만 정작 작성한 코드는 여전히 잘 분리되지 않은 메소드들이 있었다. 내 코드를 보는 내가 이런 생각인데 같이 개발하는 팀원의 코드는 어떠했을까? 당연히 개발 방식에 대해서도 토론이 있었다.
- '굳이 그렇게 해야하나요?'
- '그냥 한 곳에다가 다 적으면 되지 않나요?'
- '굳이 서비스까지 보내는 것보다는 컨트롤러에서 다 처리하면 되지 않나요?'
- '객체를 기본 생성하고 Setter로 데이터 넣으면 안되나요?'
- '엔티티 반환하면 편한데 왜 DTO 만들어야 하나요?'
- 'Date나 Time쓰면 되는데 왜 LocalDate 이런걸로 바꿔야해요?'
강의를 보면서 배웠던 위험성, 노하우 등을 듣고 작성하려는 나와는 달리 학교에서 배운 것 또는 어떻게 사용하는지 기초만 학습한 것만으로 개발하는 것에는 여러가지 차이점이 보였던 것 같다. 이런 질문을 받을 때마다 어떨 때는 잘 대답했지만 어떨 때는 나도 제대로 된 답변을 하지 못했기에 의아함만 남았던 것 같다. 따라서 같이 인터넷에 검색해서 찾아보기도 했지만 잘 받아들여지지 않은 경우도 있었다. 내가 잘 알았고 잘 설명해줬다면이라는 아쉬움이 남기도 했다. 그래도 좋은점은 서로 질문과 답변을 주고받으면서 '배려'와 '존중'을 담았다는 것이다. 이 때 정말 좋은 팀원들을 만났다는 생각이 확실하게 들었었다.
🚀 끝내면서
팀 프로젝트가 끝나고 다른 팀 프로젝트 코드를 봤을 때는 신선한 충격이었다. 분명 JPA를 쓰는데 native query로만 가득찬 레포지토리와 DB 조회 후 바로 반환하는 것과 서비스 없이 컨트롤러에서 모든 코드를 적어서 천줄이 넘어가는 코드 등 '이게 맞나?' 라는 생각이 들어서 주위 친구와 팀원들에게는 매번 강의 때 배웠던 구조라든지 지식을 설명했었다.
학교에서 간단한 CRUD와 로그인 게시판을 만드는 시험을 쳤었다. 아직도 기억나는게 절반 넘게 통과하지 못했다는게 신선했다. 프론트만 학습했었다면 이해가 가지만 아니었던 사람들도 있어서 신기했다. 물론 나는 아직 취준생이지만 그들은 취업을 했다는 사실도 신기하다.
'역량이 더 높은 개발자'가 되는 것을 목표로하여 꾸준히 학습을 이어나가야겠다.
이 글을 보는 개발자와 친구, 동기들도 현재에 만족하지 않고
역량을 키워서 좋은 개발자로 만났으면 좋겠다
'회고록' 카테고리의 다른 글
창업아이디어 경진대회 동상을 받으면서 (0) | 2022.11.28 |
---|---|
[스터디] 자바를 가르치다 (0) | 2022.11.12 |
0년차 백엔드 개발자 회고록 (1) | 2022.11.10 |