마지막 10주차가 되는 지금, 항해플러스 과정을 회고한다.
대학 1학년 시절부터 BoB나 소프트웨어 마에스트로의 명성을 익히 들어왔던지라, 학부생 시절부터 난 부트캠프를 꼭 해보고싶었다.
성장을 갈망하는 집단에서는 라이벌, 선배의 존재만으로도 효율이나 이펙트가 어마어마하다는 것을 과거에 경험해봤었고, 간절한 사람들이 모인 집단은 적당히 성실한 다른 표본의 1년치 경험을 한달만에 해낼 수도 있다는 것을 알고 있었기에.
대학교 3학년때부터 취업도 안해본 개발자들의 창업이라는 진로를 두 번은 선택한 덕분에 해볼 기회가 없었다만,
만 3년차가 되려하는 현 시점 퇴직 전 부트캠프를 계획하고 퇴직했다.
하지만 사실, 부트캠프를 하겠다고 했을 때 주변의 시선이 곱지 못했긴 했다.
- 아니 이미 인재가 빨리 이직을 해야지 부캠을 왜 가냐?
- 엥? 니가 부트캠프 갈 짬이야? 넌 커리어도 있잖아?
하지만 항해 플러스는 2~3년차 재직자 대상 부트캠프라는게 메리트가 컸다.
실제로는 재직중 들으시는 분 반, 휴직하고 들으시는 분 반정도 있었던 것 같다.
다소 의외였던 것이 프론트엔드 개발자들의 비율이 20% ~ 30%정도는 있었던 것 같다.
취업보다 창업을 우선시했던 나는 남들보다 취업준비를 해본 경험이 더 적은 것이 사실이었고,
난 내가 이상적인 엔지니어들과 비교했을때 스스로 인재라고 생각하지 않았다.
B2B, SI, SM에서 오래 일을 하다보면 특화된 시야가 생기기 마련이고, B2C에 있어서는 테크 레벨이나 협업시 문제가 될만한 약점들도 있다고 생각했던 것 같다.
더욱이, 항해플러스 출신들의 이직 업그레이드 성공률이 높은 것도 메리트가 있었다.
165만원이라는 거금이 들긴 했지만, 그만큼 매몰비용 효과도 높은, 열정 많은 사람들이 모이지 않을까? 하는 기대와 함께 내심 안 맞으면 1주만에 환불할 계획으로 들어갔다.
10주간 행했던 모든 과정들이 나에게 있어서 도전이었다.
열심히 하는 사람들은 10 to 10으로 일하고도 연차 써가며 모든 교육과정을 수료해냈는데, 왜 재직중에 알고도 안했는지 후회했다.
야근했다가 참여 못하면 팀원들에게 민폐일 것이라는 생각으로 참여를 미뤄왔는데, 열심히만 하면 되는 시스템이었다.
항해플러스 교육 디자인
항해플러스 시스템은 성장에 최적화되어 있었다.
나는 4~5년 전부터 서까남 유튜브와 책, 조남호의 스터디코드를 참고하여 엘리트들의 학습 방법론을 꽤나 정리해왔었고, 이를 위한 자기주도 학습 시스템을 사이드 프로젝트로 여럿 기획/디자인 해봤었다.
- "몰입"하는 "순공"시간의 최대 증량
- 자신의 "최대 작업량"과 "최고 효율"과 "슬럼프 상태"와 "환경별 집중도"의 메타인지
- 스터디 그룹에서의 "라이벌"과 "선배"와 "멘토"
- 계획 "수립률 2배", 계획 "실천률 3배"의 "효율적인 자료"와 지름길로 가는 "개사기 스킬"의 확립
항해플러스의 시스템에는 혼자서 해내야하는것 빼고, 시스템이 해줄 수 있는 것들은 모두 고도화해서 학습자들에게 제공해주었다.
아니 이렇게까지 고민하고 심지어 이걸 사업으로까지 굴린 사람이 있다고?
기회만 된다면, 이 시스템을 디자인 하신 분이랑 커피챗 좀 해보고 싶긴 했다.
내 주변에는 부트캠프를 10년 전 국비지원에 빗대며 우습게보는 사람들이 많았는데, 놀랄 만큼 훌륭한 학습 시스템이었다라고 역설하고 싶다.
1주차 - 테스트
테스트 관점이 생기고, 테스트 코드 작성이 습관화되었다.
손으로 하던 테스트, 눈으로 찾아다니던 회귀이슈의 해결의 자동화는 이제 기술적 자산이 되어 안정성과 효율을 기여할 수 있게 되었다.
이전에는 API 개발/수정 때 마다 도커 컴포즈와 init ddl, init data 작성을 꽤나 자주 했었는데, 테스트 컨테이너와 테스트 코드로 이를 완전히 자동화하였다.
시간 없으면 테스트 못하잖아요?
재직자들이 많이 했던 질문인데 그렇지 않다. 요즘 테스트는 LLM에게 맡기고, 검토하면서 잘 관리하는게 트랜드다.
테스트코드 안 짜도 하던 테스트를 더욱 효율적으로 할 수 있는 시대가 되었고, 시간이 없을 수는 없다.
2주차 - 시스템 설계
다른 재직자들의 스펙 주도 개발 방법과 문서 관리 방법들을 배워볼 수 있었다.
항상 피그마로 시간들여서 문서 작성했었는데, mermaid.js 기반으로 문서를 관리하게되어 효율적으로 의사소통 하게 되었다.
DDL, Event Flow, 시퀀스 다이어그램 모두 해당됨.
또한, 개인적으로 가장 큰 자산이라고 여겨지는 Gemini Canvas로 시뮬레이터를 만들어 프론트엔드 HTML을 첨부자료로 쓰는 방법도 터득해낼 수 있었다.
3주차 - 클린아키텍처
가장 도전적이었고 힘든 과제였고 9주차가 될 때 까지 매주 수정하며 들여다본 주제였다.
비즈니스 스케일, 한정된 작업 기간 때문에 OOP를 잘 안하던 백엔드 개발자 입장에서 얻어간 게 가장 많은 주제였다.
협업, 테스트, 확장가능성을 위해서는 아키텍처 레벨을 높여야만 했다. 배워도 배워도 배울게 많은 OOP 원칙들을 배웠다.
대용량을 대응하는 시스템에는 아키텍처가 반드시 따라줘야만 했다.
개발자간 "코드리뷰"의 대상이 되어 호불호가 갈리기 때문에 불호를 걷어낼 수 있게 장단점을 이해하며 개선해야 했고, 레이어드 아키텍처에서 시작하여 클린 아키텍처, 최종적으로는 애플리케이션기반 EDA / 카프카 기반 EDA로 업그레이드 하게 되었다.
15년차 시니어들도 아직도 모르고 섞어 쓰는 사람 많습니다. DB 엔티티와 도메인 엔티티는 별도로 쓰는 객체들입니다. 왜 그럴까?
DIP 왜해요? 레이어드로 쪼개도 관심사분리 되잖아? Prisma 쓰면 클라이언트가 DB 엔티티도 주고 인터페이스도 주잖아? 이렇게 귀찮고 불편하게 쓰면 나중에 어떻게 편해질까?
현대 수많은 아키텍처들이 공통으로 하는 목적이 뭘까? 왜이렇게 힘들게 복잡하게 만들어 쓸까? 수정해도 되는거랑 수정하면 안되는게 뭘까?
4, 5, 6주차 - 데이터베이스와 레디스 락
대용량 트래픽을 다루는데 꼭 필요한 DB의 패러다임을 다시 들여다보며 자세히 볼 수 있었다.
MySQL과 엔터프라이즈급 DB(PostgreSQL)의 성능적 차이(Master 여러개, 샤딩 클러스터 여러개)를 알아볼 수 있었다.
DB의 확장성과 확장 한계성을 검토해보았다(Replication, Sharding).
분산DB의 도입 필요성(오버엔지니어링이 아님)을 명확히 인지하고, 분산DB의 대응방법(트랜잭션 분리, 제거, SAGA패턴)을 적용해보았다.
TypeORM을 뜯어보고(락 구현), Prisma ORM을 사용하며 편리성을 비교해보았다.
수정되면 안될 도메인 서비스가 써야하는 Repository Interface를 죽어도 수정하기 싫어서, tx를 안넘기고도 호출 context별 트랜잭션을 유지하는 Async Local Context 기반 트랜잭션 제어 유틸과 AOP 데코레이터를 개발하여 적용해보았다.
MySQL기준 쓰기 인스턴스가 1대, 정합성 보장을 위한 트랜잭션 패러다임 때문에 성능 한계가 매우 명확함을 확인하였다.
DB가 느려지는 지점, 트래픽이 발생하면 메모리 기반이 아닌 Disk I/O 발생으로 느려짐을 확인해보았다.
트래픽 별 락 한계와 DB부하를 분산하기 위한 고민을 해보고, 애플리케이션/외부인프라의 부하 분산을 익혀보았다.
인덱스가 왜 빨라지는지, 인덱스의 B+Tree 알고리즘을 뜯어보았다. UUID로 PK를 걸던 방식의 성능저하를 확인해보았다.
레디스의 가용성을 위한 백업방식과 클러스터링시 위험성, 레드락 알고리즘을 들여다 보았다.
PostgreSQL과 레디스의 성능을 비교해보았다(100만배).
레디스 락의 spin lock, pubsub lock(+ttl 연장 watchdog)을 직접 구현하여 실무 프로덕트에 쓸 레벨로 모듈링 해보았다.
컬럼 확장이 귀찮아도 낙관락의 메리트(데드락 확률 저하, DB 락/대기 부하 분산)와 디메리트(재시도시 고비용)를 이해하고 적절히 애용하게 되었다.낙관락, 비관락, 분산락을 나눠쓰며 제어해보았다. 데드락을 근본적으로 막는 방법을 들여다 보았다. 락 종류별로 바꿔써보며 Jest와 k6로 부하테스트를 주며 성능과 데드락 발생률을 직접 비교해보았다.
7주차 - 레디스 캐시 / NoSQL
대용량 트래픽 환경에서 예민할 수 있는 DB에 읽기 부하를 줄이기 위한 테크닉으로 앱 캐싱, 레디스 캐싱과 스탬피드 방지 처리로 DB부하를 분산시켜보았다.
Redis 자료구조로 랭킹 집계를 편하고 안정적으로 개선하면서 DB부하를 줄이고 스케쥴러를 걷어내는 개선을 해보았다.
Redis 자료구조로 데이터 저장하고, 트랜잭션을 구현하여 비즈니스 요구사항(TPS 10,000)을 안정적으로 대응하는 개선을 해보았다.
8주차 - Event Driven Architecture
지금 이직하게된 회사의 면접 준비를 하면서 동시에 밤낮으로 작업하고 꿈에서도 개발하며 아키텍처의 최종 리팩토링을 달성했다.
학습 루틴이 자리잡히고, 효율적 학습 방법들이 최종적으로 체화되는 지점이었다.
멘토링 중 들었던 테크기업들의 아키텍처 레벨이 집대성되었던, 내적으로 항해플러스 과정 중 가장 크게 성장했던 기간이었다.
파사드 패턴의 클린 아키텍처를 EDA로 마이그레이션 해보았다.
100% 관심사 분리를 달성해보았다. 책임분리를 100% 달성해보았다.
보상트랜잭션과 SAGA패턴을 적용하였고, 오케스트레이션 패턴과 코레오그레피 패턴을 비교하고 아키텍처에 녹여보았다.
애플리케이션 계층 왜 나눌까? 어떻게 쓸까? 순환참조 문제 해결을 위해 파사드를 썼다라, 파사드 패턴이 코드 수명이 긴 패턴일까? 한 서비스 고장이 한 API가 아니라 여러 API로 전파될 가능성이 있는 최악의 패턴임. 역할과 책임 분리를 명확하게 구분하는것이 EDA, 많은 대기업들이 EDA로 넘어감.
9주차 - Kafka Event Driven Architecture
귀가 따갑도록 들어온 카프카의 패러다임을 학습하고, 코드에 녹여보았다.
열과 성을 다해 완성해냈던 Event Driven Architecture의 이벤트를 카프카로 쉽게 마이그레이션 해보았다.
대규모 비즈니스 프로세스를 카프카로 분산하여 DB/인프라의 대기 부하를 브로커와 컨슈머에게 분산 시켜 보았다.
컨슈머 그룹을 확장하여 이벤트를 병렬 재처리하도록 비즈니스 프로세스를 개선해보았다.
메시지 키를 조정하여 병렬 처리와 레이스컨디션 방어 및 순서 보장(전달까지만)**** 을 해보았다.
At-Least-Once 패러다임으로 인한 이벤트 재처리 방지를 위해 멱등성 처리를 들여다보았다.
이벤트 처리 유실 방지를 위해 DLQ 토픽을 사용해보았다.
이벤트 발행 유실 방지를 위해 아웃박스 테이블을 고안해보았다.
더 써보고 싶은 주제 : 카프카 컨슈머 Pause / Resume 으로 DB 스케일업 무중단 처리
10주차 - 장애 대응
k6를 활용한 스모크 테스트 위주의 테스트 습관이 RPS, TPS 기준 p95/p99 테스트로 개선되었다.
endurance 테스트, stress 테스트, peak 테스트 부하로 발생한 SPOF 약점 진단 스크립트를 작성해보았다.
기존의 적당한 트래픽에 대응 되는 스케일아웃 기반 소프트웨어에서, 소프트웨어의 가용성 품질을 수치로 표현해보았다.
Grafana를 활용한 모니터링과 Grafana OnCall(전화) 전송 방법을 고안해보았다.
더 써보고 싶은 주제 : 인프라별 모니터링 지표 최적화
전 과정을 마치며
휴직 중 들었던 과정이라 시간을 많이 쓸 수 있었고, 18/20 PASS이므로 마지막 과제만 성공적으로 마치면 ALL PASS가 기대된다.
OOP를 안했었기에 내가 블랙뱃지를 받을 거라고는 기대하지 않았는데, 준다고 하면 내심 뿌듯하긴 할 듯 하다.
잘 고안된 교육 시스템 덕분에 많이 성장했다.
Typescript 백엔드라 그런지 타 팀과 교류할 수 있는 기회가 적어 아쉽긴 했다.
JAVA/Kotlin 스택은 기술이 명확히 호환되어 랜덤 팀 코드 리뷰 및 네트워킹이 수월해보였는데 우리 팀은 그러지 못했다.
후반 주차로 갈수록 회사일이 바빠 참여 못하는 분도 많아졌는데 이 때 타팀간 교류라도 해본다면 좋았을텐데... 하는 아쉬움이 있었다.
또, B2C / OOP 기반 스터디는 처음이었기에 초반에는 내가 아는게 많이 없어서 팀원들과 기술적인 교류에 많이 참여하지 못했다. 후반주차가 되어서야 관점과 기술수준이 꽤 끌어올려져 알고 있는 것과 새로 배운 것에 대한 교류를 하고싶었는데, 후반주차에는 얘기할 수 있는 팀원들이 없어지셨다... 다들 연말 일정이나 생업에 집중하시느라 나가셨기에.
팀원들의 부재로 후반 3주차는 팀멘토링을 혼자서 1:1로 받게 되었었다.
테크기업의 리더급 멘토의 관점을 1:1로 흡수할 수 있는 점은 정말 좋았지만, 내 성장에 +@가 되는 상호작용이나 고민 공유가 없었던것은 아쉬웠다.
아무래도 스케일있는 BE는 Java Spring이 성능상 이점(JIT)이 있고, 잘 고안된 오픈소스 생태계(node는 레디스 라이브러리가 공식과 실무표준 라이브러리가 다르며 pub/sub락 또한 직접구현해야함)가 있고, 개발자 풀이 많기 때문에 과반수의 재직자들이 스프링 기반으로 일하고 계신듯 하다.
Typescript 백엔드 또한 Application EDA에서 rxjs의 백프레셔, 컨텍스트 스위칭 비용 없음이라는 성능 이점이 있다곤 하는데 전통이 짧아서 그런지 국내에서 아주 인기가 있지는 않아 보인다.
과정 중 BP(Best Practice)도 한 번 받아봤는데, 딥다이브로 파고들어서 지식 공백을 제거하고 성능적으로 트레이드오프를 따져가며 개발하는 루틴, 어느 수준으로 딥다이브해야 테크기업 기술블로그 수준의 기술검토인지 관점도 자리 잡힌 듯 하다.
또 B2C에서 기술로 돈만드는 사람들의 시야와 관점이 내 자산이 되었다.
이 사람들의 기술 관심사가 무엇인지, 인재 관심사가 누구인지 시니어 엔지니어들에게 멘토링 받으면서 직관을 얻어볼 수 있었다.
혼자 공부하고 적당히 대학 친구들 / 직장 동료들에게 카톡으로 의견 나누는 정도였었기 때문에.
회사 외부에서 이렇게까지 깊게 스터디를 하고 네트워킹을 해본 적은 대학 졸업 이후로 없었던 것 같다.
단 네트워킹은 학술적인 교류가 일어나지는 않고, 유의미한 사건이나 성장은 스터디에서 발생한다.
네트워킹은 중요한 것을 놓치지 않게 해주는 정도로 활용하는게 적절하지 않을까 싶긴 하다.
네트워킹을 하면서도 나누었던 내용으로, 무언가 심도있게 스터디하거나 오랜기간 투자하지 않은 네트워킹은 99% 손실된다는 것.
앞으로는 TSBM에 참석하려 한다. 개발자는 평생 공부하는 직종이므로, 성장하는 루틴이 있어야 한다.
성장이 습관화된 고도로 훈련된 인력들과의 스터디는 과연 어떤 성장을 해낼 수 있을 지 기대된다.
---
최종 과제까지 패스해서, 블랙 배지 받았다.
