개발자로서 첫 실무 Nest.js 서버 리팩토링 회고
2023 2월 8일 드디어 개발자로 첫 출근을 했다!
국비지원 코딩 교육을 마치고 한 달 만에 취업에 성공하여 매우 기뻤던 기억이 아직도 생생하다.
직무전환에 성공했으니 이제 나의 가치 증명과 동료의 인정받으며 압축 성장을 해야 할 시기가 도래한 것이다.
그래서 첫 미션에 열정적으로 임했고, 잘하고자 노력했다.
이제 그 첫 실무, "리팩토링"을 회고해 보겠다.
Nest.js와의 첫 만남
6개월간의 국비지원 코딩교육에서 Node.js 기반의 프레임워크는 Express만 경험한 상태였다. 3번의 팀 프로젝트와 풀스택으로 진행한 개인프로젝트 모두 Express를 사용했던 것이었다. 하나의 프레임워크에 집중한 덕분에 단순 CRUD 외 에러 로깅이나 오류 발생 시 디스코드로 메시지를 보내주는 등과 같은 실제로 도움이 되는 기능을 구현하며 실무처럼 생각하며 공부할 수 있었다.
하지만 Nest.js는 OOP에 대한 이해가 필요했다.
감사하게도 현 직장에서 나의 러닝커브를 좋게 평가해 주셨고, 아직 경험은 없지만 Nest.js를 빠르게 학습하여 실무에 투입될 수 있을 것이라고 믿어주셨다. 개인적으로도 Java, Spring도 학습하는 것으로 계획하고 있었고, Nest.js를 학습하면 이 계획에 도움이 될 것으로 기대하고 있었다.
즉, 팀의 기대와 개인적인 목표의 방향이 잘 맞아떨어진 최상의 조건이었다.
예기치 못한 일정 변경
온보딩 기간은 2달로 계획되어 있었다. 온보딩 기간동안은 Nest.js 학습과 현재 서버의 비즈니스 로직을 숙지하고, 3달 차부터는 리팩토링에 참여하여 그 서버의 유지보수 업무를 인수인계받고 신규 프로젝트에 참여하는 일정이었다.
입사 ~ 2개월: Nest.js 학습 + 현재 서비스 중인 서버의 비즈니스 로직 숙지
3개월 이후: 리팩토링 참여 후 인수인계를 통해 해당 서버 담당 + 신규 프로젝트 참여
하지만, 2주가 되었을 때, 크리티컬한 버그가 발견되었고 이로 인해 Full QA 일정이 약 한 달 뒤로 잡히는 일이 발생되었다.
해당 서비스는 총 3개 팀의 서버가 유기적으로 얽혀있어서, 트러블슈팅도 쉽지 않았다.
버그가 발생되었는데, 팀은 Full QA일정에 맞추어 벼르고 있던 리팩토링을 할 생각에 오히려 에너지가 넘치는 모습이 인상적이었다.
이로 인해, 2달로 예정되어 있던 온보딩은 2주 만에 종료되었고 바로 리팩토링에 참여하게 되었다.
1인분의 역할을 빨리하고자 온보딩 기간에 열정적으로 임하고 있던 덕분에 참여할 수 있었던 것 같다.
역시, 기회는 준비하고 있는 자에게 찾아온다.
처음 보는 Stored Procedure
버그의 원인으로 지목된 것이 비즈니스 로직의 파편화이었다. 유저가 한 작업을 할 때 총 3개의 팀에서 운영하는 서버가 유기적으로 연결되어 요청을 처리하게 된다. 이때, 우리 서버에서 다루는 비즈니스 로직의 일부를 타 부서에서 DB 내 Stored Procedure로 작성해 놓아 책임과 권한이 분산된 것이 화근이었다.
위의 문제를 해결하기 위해 내가 맡은 임무는 아래와 같다.
1) Stored Procedure를 Service 내 비즈니스 로직에서 구현
ㄴ 여러 DB를 수정하는 로직이 존재하여 Transaction 시 TypeORM의 Query runner 활용
2) 기존 코드를 AOP관점으로 Nest.js의 Request Lifecycle을 적극 활용
- Middleware:
ㄴ ELK를 이용한 Log 검색에 용이하도록 Winston을 이용한 Request Logging 구현
ㄴ 추적가능성을 위해 요청에 대한 UUID를 부여하여 각 단계와 Response Logging 시에도 동일 UUID 사용
- Guard:
ㄴ IP White list 로직을 기존 Middleware 위치에서 이동하여 구현 및 개선
ㄴ NginX를 퍼블리셔에서 당당하는 관계로 우리 팀에서 추가적으로 White list를 구현함)
ㄴ White list 확인 로직을 기존 for문에서 Trie 자료구조를 활용하는 것으로 변경하여 속도 개선
- Pipe:
ㄴ 특정 요소에 대해 우리 회사 DB와 퍼블리셔 DB에서 사용하는 코드 번호가 상이한 것에 대한 변환 로직 추가
ㄴ 비즈니스 로직에서는 우리 회사 DB에서 사용하는 코드 번호로 통일
ㄴ Pipe의 적용 순서가 DTO 이전인 문제가 발견되어 구현한 코드 미적용 (마음이 아픔ㅠㅠ)
- Interceptor(post-controller):
ㄴ Response를 수신하는 서버의 요청 형식을 적용하는 로직을 기존 Util 위치에서 이동하여 구현
- Filter:
ㄴ ELK를 이용한 Log 검색에 용이하도록 Request와 동일한 UUID를 포함한 Logging 구현
3) Jest.js를 활용한 Unit/E2E Test code 작성
4) Functional Programming이 적합한 로직에 한하여 적용
구매한 Nest.js 강의가 생각보다 부실해서 공식 문서와 ChatGPT를 적극 활용하며 해결했다.
위의 문제를 해결하는 동안 사수는 ELK를 구현하고, 기존 Bitbucket를 활용하는 CI/CD에서 Github action을 활용하는 CI/CD로 변경, 그리고 추가되는 기능들을 구현하고 있었다.
사수가 하는 일에 대해서 계속 공유를 해주어서 ELK와 CI/CD에 대해서도 이해도가 높아졌으며, 개인 프로젝트에 적용해보고자 하는 의욕이 생겨났다.
내가 작성한 코드가 실제 서비스에
국비지원 코딩교육을 6개월간 수강하면서 3번의 팀 프로젝트와 1번의 개인 프로젝트를 진행했고 AWS, GCP, OCI 그리고 On-Premise 환경에서 배포를 직접 해보는 경험을 해보았다. 나름 실제 서비스와 비슷하게 공부해 봤을 것이라고 생각했는데 전혀 아니었다.
1. Local환경에서 Docker로 띄운 Test DB를 활용여 Test 및 개발 진행
2. develop 브랜치에 Merge를 하면 Dev 서버에서 테스트
3. release 브랜치에 Merge를 하면 QA 서버(staging server)에서 QA분들에 의해 테스트 진행
4. master 브랜치에 Merge를 하면 Live 서버(production server)를 통해 유저에게 서비스 진행
위와 같은 순서로 진행되었으며, 한 단계씩 넘어갈 때마다 버그가 나오진 않을까 조마조마하며 한쪽 모니터에 ELK에 'event.original.keyword error'를 검색해 두고 모니터링을 하며 작업했다.
Production Server에 내가 작성한 코드가 올라가니
버그에 대한 걱정과 뿌듯함이 몰려오면서 짜릿한 기분이 들었다.
리팩토링을 진행하면서 느낀 점 (feat. ChatGPT)
Nest.js라는 프레임워크와 기존 코드를 2주만 학습하고 투입되면서 혼자 진행하기는 벅찼던 것이 사실이었다. 그렇다고 사수에게 계속 질문을 하면서 하기에는 사수도 바쁘다는 걸 알았기에 ChatGPT와 Copilot을 적극적으로 활용하면서 문제를 해결해 나갔다. 그 과정에서 GPT4가 공개되는 등 큰 이벤트도 있다 보니, 개발자의 미래에 대해서 생각을 해보게 되었던 것 같다.
AI가 빠르게 발전해서 GPT10이 공개된 시점에 개발자는 어떤 역량을 갖고 있어야 할까?
그렇다면 나는 지금부터 어느 역량에 집중을 하며 성장을 해야 할까?
그 역량을 갖추기 위해서 당장 오늘은 무엇을 하면 될까?
압축성장이라는 것이 절실하게 갖고 싶어 졌다.