- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- EntityTransaction
- LazyInitialization
- JWT
- SPRING JWT
- 브랜치전략
- 프로젝트
- redis
- infra
- JPA
- Project
- 리뷰
- 팀네이버
- jenkins
- network
- Java
- 캐싱전략
- 팀네이버 공채
- Spring Security
- chrome80
- 후기
- 스프링
- 젠킨스
- websocket
- SpringBoot
- Kotlin
- spring
- 만들면서 배우는 클린 아키텍처
- 책
- container
- docker
PPAK
[프로젝트 리뷰] 공개SW 개발자 대회 참여를 하면서 (feat. 이웃사이) 본문
아직 대회와 프로젝트 개발이 끝난 것은 아니지만 MVP 레벨의 기능 개발도 어느 정도 마무리가 된 것 같아서 최근 약 두 달간 어떻게 개발을 진행해 왔는지 살펴보고 쉬어가며 소감도 한번 작성해보고자 합니다 !!
프로젝트 시작 전
복학 후 두 학기를 정말 학교 생활에 집중했던 것 같습니다.
열심히 하고자 다짐한 것도 있지만 예상보다 CS 공부나 코딩이 조금 더 저에게 잘 맞았고 덕분에 두 학기 모두 좋은 성적으로 마무리할 수 있었던 것 같습니다.
무슨 자신감이었는지는 모르지만 3학년 1학기에는 회사 이곳저곳에 포트폴리오를 작성하여 내보기도 하고 코딩 테스트를 응시하기도 했습니다. 크게 기대는 안했지만 역시나 모두 광탈을 했고 그 과정에서 제가 무엇이 부족한지에 대해 성찰을 했던 것 같습니다.
어떤 개발자가 되고 싶은가에 대한 자문을 자주 하지만 현재까지 나름의 결론은
1. 제품 개발 간 소통과 협업을 잘 하는 능력
2. 문제를 발견할 줄 알고 끈임없이 문제해결에 대해서 고민하는 능력
3. 변화에 적응하고 응용할 수 있는 능력
위 세 가지 능력을 바탕으로
1. 나의 경험이 어느 누군가의 개발 초석이 되는 것
2. 나의 아이디어로 사회 문제(특히 교육, 경제) 를 해결하는 것
3. 새로운 분야를 개척하고 트렌드를 만드는 것
등의 조금은 당연하지만 그래서 더 솔직한 목표를 가진 좋은 개발자가 되리라 다짐했습니다.
프로젝트 시작까지
학교에서 듣는 강의는 어디까지나 지식을 습득하는데에 초점이 맞추어져 있어 활용을 하고 아이디어를 구체화하는 경험을 하기에는 부족하다는 생각을 하고 있었습니다.
작년 CS 지식이 전무한 상태에서 진행한 프로젝트에서도 많은 배움이 있었기 때문에 올해에도 두 개 이상의 프로젝트를 완성하고자 하는 목표가 있었습니다.
지난 겨울에는 학교 생활에 치이느라 이렇다할 프로젝트를 진행하지 못해 큰 아쉬움이 있었기 때문에 이번 여름에는 꼭 프로젝트 하나를 완성해 봐야겠다고 생각을 했습니다.
어떤 프로젝트를 하면 좋을까 고민을 하던 찰나에 고맙게도 뮌!지, 썩, 아양이 공개SW 개발자대회에 같이 참여하자고 제의를 해주어서 함께 팀을 꾸렸습니다.
본격적인 시작
이번 프로젝트를 참여하면서 다짐한 것은 프로젝트를 "잘" 하자는 것이였습니다.
당연히 잘 해야지...?
맞습니다. 하지만 여기서 잘 하자는 것에는 여러가지 의미가 담겨져 있습니다.
1. 토이 프로젝트의 티를 최대한 걷어내보자
단순히 동작하는 제품을 완성하는 것에 초점을 두는 것이 아닌 오픈소스화 시킬 수 있을 정도의 확장성을 가진 제품을 만들고자 했습니다. 실제로 본 요구사항을 만족시키기 위해서 코드를 작성하는 시간보다 시스템 아키텍처, WAS 레이어, 도메인 설계과정에 시간을 더 쏟아부은 것 같습니다. 또한 클라이언트와 서버 개발자가 협업하는 환경을 만들고자 했습니다. 이를 위해서 개발 일정을 조금 더 세밀하게 작성하고 빅테크 기업에서 재직중인 선배님 5명을 직접 찾아뵈어 개발 싸이클이 어떻게 이루어지는지 대해서 자문을 구하기도 하였습니다.
2. 기록을 잘 남기자
지난 프로젝트를 회고하면서 반성했던 것 중 하나가 기록을 꼼꼼하게 남기지 못한 것이였습니다. 그 당시에는 제품 개발 데드라인을 맞추기 위해서 문서 작성을 생략하였는데 단단히 잘못된 생각이란 것을 시간이 지나고 문서를 작성하려고 할 때 깨달았습니다. 생각보다 새로운 지식이라는 것은 보는 것 만으로는 제 머릿속 깊이 새기는 것이 힘들다는 것을 깨달았습니다. 그 때부터 블로그 포스팅, 특히 제가 느낀점과 함께 배웠던 기술 지식을 기록하기 시작하였습니다. 본 프로젝트에서도 역시 새로운 기술을 배우고 도입해볼 예정이 있었고 단순히 기록하는 것에 그치지 않고 다른 사람, 특히 팀원들과 공유할 수 있는 문서를 작성하는 것에 초점을 맞췄습니다.
3. 상 타자!!!!!
한정된 시간 내에서 목표하는 바를 잘 달성하는 것 또한 중요한 개발자 역량이라고 생각합니다. 저희 팀은 개인 프로젝트를 진행하는 것이 아니라 대회에 출품하는 프로젝트를 완성하는 것이였기 때문에 대회의 요구사항을 충족하며 완성도 있는 프로젝트를 만드는 것에 집중하고자 했습니다. 대회에서도 좋은 결과를 받는 것 또한 참가자로써의 가장 큰 바램입니다.
아이디어 구상 (7월 중순)
저희 팀이 대회에서 참여한 과제는 사회문제형 중 생활/안전 파트입니다. 사실 처음에는 건강을 택하고 해외 방문이 어려운 상황인 사람들에게 도움이 될 만한 서비스를 구상하였지만 구체화 과정에서 기술상의 어려움과 다들 아이디어에 큰 공감을 하지 못해 일주일 뒤 비상대책 회의를 열어 주제를 다시 정했습니다.
각자가 준비해온 내용을 바탕으로 사회 문제를 논의하다가 "취약 계층 1인 가구에서 발생할 수 있는 문제" 를 해결해보는 것은 어떨까하는 의견을 바탕으로 문제와 관련된 실제 사례와 그 원인을 조사해봤습니다.
크게 저희 팀이 규정한 문제와 그 원인은 아래와 같습니다.
1. 이웃간의 소홀함, 무관심 대두 - 개인화된 성향, 대면 소통의 부담감, 온라인 기반 소통의 부재
2. 홀몸노인 무연고 사망자 증가 - 고령자 1인가구 증가, 위급 상황시 골든 타임을 지키기 힘든 상황
3. 아파트 단지 내 공고물 열람의 비효율성 - 온라인 기반 알리미 기능 부재
팀원 모두 위와 같은 문제를 해결해야 한다는 것에 공감을 했고, 따라서 "이웃 간의 단절과 고령 1인 가구 증가로 인한 아파트 단지에서 발생하는 다양한 문제를 해결하자" 라는 목표를 가지고 기획을 하였습니다.
기획단계에서 스마트폰과 아파트 세대 빌트인 기기로 들어갈 수 있는 애플리케이션을 구상하였고 MVP 기능 요구사항은 아래와 같이 설정했습니다.
1. 온라인 소통 창구 기능
2. 온라인 알리미 기능
3. 카메라를 통한 연령 추정 결과를 바탕으로 인터페이스 다각화 기능
4. 비상 호출 버튼 사용 시 관리실 및 이웃에게 긴급 알림이 전송되는 기능
이를 바탕으로 기능 요구사항 명세서를 작성했었습니다.
개발 준비, DevOps 셋팅 (7/18 ~ 7/25)
항목 별 적용 방식은 기술 포스팅 을 확인하시면 되고, 더 자세한 이야기는 본 티스토리 게시물에 기록을 남겨놨습니다.
작업 현황 공유는 노션을 통해서 공유하였습니다.
확실히 공유문서가 있다보니 팀원 각자가 현재 개발하고 고민하는 부분을 파악하기 용이했습니다.
브랜치 관리는 Git-flow 에서 제시하는 형태로 관리하고 브랜치 간 병합은 Github 의 PR 을 통해 진행하였습니다.
서버 개발자가 저를 포함해 2명밖에 없었기 때문에 다이나믹한 경험은 못했지만 git 을 활용하는 능력이 정말 많이 상승했던 것 같습니다.
배포환경 및 CI/CD 환경을 gcp, jenkins, webhooks 을 통해 구축했습니다.
아양님이 "이게 이렇게 쉽게 된다고?" 라며 놀라던 모습이 생각납니다. 설정 파일이 추가될 때 마다, 혹은 타겟 브랜치가 변경될 때 마다 아주 가끔씩 jenkins 서버를 수정한 것 외에는 배포과정에서 아무것도 한 것이 없습니다.
현 시각까지 jenkins 님이 저희 제품을 배포하신 횟수입니다. 99번의 배포코드를 손으로 작성했을 것을 생각하면 정말 끔찍합니다...
개발 (7/26 ~ 진행 중)
MVP 개발이 어느정도 마무리된 현재까지 사용한 기술 스택은 크게 아래와 같습니다.
런타임 환경은 도커 컨테이너로 구축했고, 런타임 애플리케이션 통신은 아래와 같습니다.
스프링 부트 애플리케이션으로 들어오는 HTTP 요청, 응답, 예외 발생시 원인 등을 따로 머신 디스크에 로깅을 하였는데 정말 큰 도움이 되었습니다. 실시간으로 콘솔이 아닌 외부 파일로 저장되는 점과 에러는 파일을 따로 분리해서 로깅할 수 있기 때문에 클라이언트 개발자와 같이 라이브 코딩을 할 때 특히 유용했습니다.
JWT 를 바탕으로 인증/인가 로직을 구현했습니다.
적용 과정에서 CORS 정책과 관련한 정보 (브라우저 정책, preflight, https 등등) 에 대해서 다양하게 알아봤던 것 같습니다.
개발 중간에 access token 과 refresh token 을 어디에 저장을 해야하는지에 대해서 팀원들을 모아 세미나를 진행한 적이 있는데 부족한 제 세미나에도 잘 이해해주고 따라와준 팀원들에게 너무 감사하다는 생각을 했습니다.
실제로 access token 은 response body 로만 전달하고, refresh token 은 쿠키에 포함하여 access token 을 재발급 받는 방식으로 진행하였습니다. 또한 access token 재발급 시 refresh token 이 1/2 이상 유효기간이 지났다면 refresh token 도 재발급 합니다.
Spring Security 또한 자세히 살펴보았습니다. Authentication Layer 에서 제시하는 형태로 관심사 분리를 하고, 검증 필터에서 발생하는 예외는 핸들링 필터로 위임하는 형태로 설계했습니다.
WebSocket 과 STOMP 를 통한 구독/발행 기능을 바탕으로 같은 아파트 세대 사람들에게 긴급호출을 보내는 기능을 구현하였습니다.
WebSocket 은 다소 생소한 기술이고 레퍼런스도 다양하지 않아서 현재까지도 올바른 작동 방식인가에 대해서 완벽하게 확신을 할 수는 없습니다. 따라서 리팩토링 과정에서 조금 더 자세히 알아보고 개선할 예정입니다.
REST API 명세서는 Swagger 를 통해 제공했습니다. 사실 만들어 놓고 서버 개발자는 볼일이 많이 없는 반면(포스트맨으로 필요한 요청들은 저장해놓기 때문에) 클라이언트 개발자들이 Swagger 를 활용하고 있다고 새삼 느꼈을 때가 썩이 "API 문서에 ~~ 정보도 추가해줄 수 있어?" 라고 물었을 때 같습니다.
Redis 를 통해서 데이터 캐싱을 수행하였습니다. 실제 캐싱데이터 활용은 크게 아래 두가지로 나뉩니다.
- 회원가입용 인증 코드를 발급하고 해당 코드를 캐싱합니다.
- 코드 인증 시 해당 데이터를 불러오고 인증이 완료되면 데이터를 삭제합니다.
- 일정기간(5분) 이 지나면 데이터를 삭제합니다.
- 휘발성 인증코드 구현
- 재발송 기능 구현에 사용
- Access Token 발급 시 Refresh Token - Access Token 쌍의 데이터 캐싱
- Access Token 의 유효기간(2시간) 이 지나면 데이터를 삭제합니다.
- 호출 횟수가 잦은 요청
이 외에도 MVC 쓰리티어(Controller-Service-Repository) 및 엔티티 설계 과정에서 단방향 즉, 고수준에서 저수준으로 흘러가는 의존성을 띄어야 한다는 것에 크게 공감했습니다.
중간소감
약 두달간의 기간 동안 길다면 길고 짧다면 짧은 프로젝트를 진행하고 있습니다. 첫 스프링 프로젝트이자 두 번째 웹 애플리케이션 개발이여서 부족한 점이 많습니다. 캐싱을 더 적극적으로 활용하고, 커스텀 에러 코드 추가, 웹소켓 개선, 클래스 분리 등등 리팩토링 요소도 많이 보입니다. 하지만 매번 새로운 기술을 배우고 적용하는 것이 즐겁다는 생각을 하고, 현재는 제가 임의로 설계한(물론 레퍼런스를 참고한) 레이어들이 실제 실무에서는 어떻게 구현되어 있는지 궁금하고, 라이브 서비스 특히 트래픽이 높을 때 발생하는 문제에 대해서 더 공부해볼 필요가 있다고 생각합니다. 또한 Querydsl, 무중단 배포, 쿠버네티스 활용, 스프링 배치 등등 사용해보고 싶은 기술들이 많이 남았기 때문에 꾸준히 학습해볼 예정입니다.
외 티스토리 포스팅 참조
'프로젝트' 카테고리의 다른 글
Redis 캐싱 전략 개선 및 스케줄링 (3) | 2023.01.31 |
---|---|
[프로젝트 리뷰] 주어진 시간은 단 5일 (feat.핀플레인) (1) | 2022.10.08 |
[Spring/WebSocket] WebSocket 도입과 STOMP subscribe, send 인가 구현 (0) | 2022.08.31 |
[Docker] Docker Container(Spring, Redis) 간 네트워크 연결 (1) | 2022.08.27 |
[Server] Application Architecture(인증/인가, Header 값 분리, CORS 허용) (0) | 2022.08.17 |