2023년 돌아보기

 

당신은 누구십니까

Q.   어떤 일 하세요?

A1.  암호화폐 거래소에서 백엔드 서버개발 하고 있습니다.

 

Q.   어떤 일 하세요?

A2. 암호화폐 거래소 백엔드 기술연구팀에서 코어로직에 대한 성능 개선 및 추가 연구를 진행하고 있습니다.

 

어제까지 저는 A1로, 오늘부터 저는 A2로 대답합니다.

2023년에 진행한 모든 업무와 그동안 파고들었던 모든 공부들은 저를 기술연구팀으로 데려다 주었어요.

어떤 것들이 있었는지 함께 보시죠!

 

한 해 동안 실컷 파고들었던 공부

1. MySQL 8.0

2. 인덱스 튜닝

3. 인덱스 설계

4. 쿼리 튜닝

5. SQLP

 

5개 주제가 모두 하나의 분야라고요?

인정하겠습니다.

저는 DBMS 내부 구현을 공부하고 그 구조를 토대로 인덱스 설계와 튜닝, 쿼리 성능 개선하는 데에 조금, 아니 많이 설레는 사람입니다.

제 책상에는 가장 자주 보는 책들이 11권 놓여있는데요, 그 중 7권이 데이터베이스에 관련된 책입니다.

오라클, MySQL 그리고 SQLP 까지 전부 보기만 해도 기분 좋아지고, 생각만 해도 얼른 공부하고 싶어 엉덩이가 들썩이는 단어들이에요.

어쩌다 그렇게 되었는지 궁금하시죠? 다 사연이 있답니다.

 

취업 전 한헤더, 저는 FNF 라는 발표 모임에 들어갑니다.

유명한 책, 갖기만 해도 기분 좋은 책들을 여러 권 갖고 있었어요.

토비의 스프링, JPA, Real MySQL 8.0, 자바의 정석, Effective java 등 모두 익히 아는 그런 책들이죠.

 

어릴 때부터 유난히 발표를 좋아했던 저는, 발표자로 신청해 약 30분 간의 발표를 두 번 준비하게 됩니다.

첫 번째 발표에서 MySQL 의 B-Tree 에 대해 소개하고 인덱스 구조와 스캔 방식을 설명하려는 원대한 계획을 세웁니다.

발표를 하려면 먼저 발표자가 그 내용에 대해 잘 알아야 합니다. 제가 발표를 통한 학습을 가장 좋아하는 이유이기도 합니다.

그 때부터 Real MySQL 8.0 을 읽고 이해한 후 야심차게 PPT 도 만들고 대본이 필요하지 않을만큼 완벽히 이해했어요.

결과는 대성공!

 

사람이 뭔가를 잘 하게 되면 칭찬과 인정을 받습니다.

인정은 한헤더의 기본 욕구, 그 때부터 'DBMS 내부 구조를 공부하고 인덱스 설계, 스캔방식에 대해 이해하는 건 재밌는 일이구나' 하고 생각하게 됩니다. 그렇게 점점 파고들어 공부하고 또 더 자세히 공부하면서, 급기야 업무에 공부한 내용을 적용합니다.

 

탑 쿼리 중 문제가 되는 쿼리를 파악하고 튜닝을 통해 성능을 개선했다?

심지어 그냥 개선한 것도 아니고, 대기를 줄임으로써 3.5까지 치솟았던 AAS 를 0.5도 안되게 파격적으로 개선했다?

아주 칭찬을 많이 받았답니다.

 

위 이슈는 정렬 부하가 있음을 파악하고, 정렬 부하를 감소시킨 정도가 아니라 정렬할 필요가 없도록 만들어주는 것으로 해결했습니다.

모든 쿼리 튜닝이 그렇듯 대단한 패러다임이나 방법이 있다기보다 부하 지점을 파악하고 그 부하를 줄이거나 없애는 평범한 방법이었지만, 공부한 내용을 업무에 적용해서 성과를 냈다는 사실이 못견디게 뿌듯하고 자랑스러웠습니다.

그러니까 저는 공부가 업무에 긍정적인 영향을 미치고 또 그 성과가 제 공부에 아주 긍정적인 영향을 미치는, 선순환의 고리에 올라탄 거죠.

 

팀원 분들이 쿼리 튜닝, 테이블 설계나 인덱스 설계 등에 대해 저에게 의견을 구하시는 일이 많아요.

모든 일을 제가 해결하는 건 아니지만, 최대한 도움을 드리고 함께 고민하고 있답니다. 정말 정말 정말 재밌어요. 생각만 해도 설레죠.

 

그래서 저는 DBMS 내부 동작에 대해 공부하고 그걸 토대로 인덱스를 설계, 쿼리를 튜닝하는 일을 좋아해요.

내년에는 조금 더 깊이 공부하고, 자격증도 취득해보려고 해요.

하지만 너무 DBMS 에 치우치지 않도록 다른 것도 공부할 생각이랍니다.

Webflux 가 그 다음 타자예요. 저의 2024년도 많이 기대해주세요!

 

프로젝트 명예의 전당

1. 아아 그 이름도 찬란한 Affiliate System.

2. 내가 Micro Service Architecture 를 설계하는 아키텍터?

3. 그렇게도 써보고 싶다던 MQ를 이용한 사람을 만나보시죠

4. 쿼리 튜닝과 성능 개선, 더이상 다른 사람의 성과가 아닙니다.

5. 데이터 준비와 정제를 즐기는 사람이 있다는데?

 

1. Affiliate System

트리가 있어요. 깊이와 너비에 제한이 없답니다.

요구사항이 그랬어요. 자식 노드를 가질 수 없는 단 하나의 조건이 있다면, 상위 노드의 속성 중 하나인 커미션율에 제한을 두는 거래요.

하지만 커미션율 제한은 변경할 수 있고 심지어 0%로 설정할 수도 있기 때문에 사실상 무제한, 무한 확장이라고 볼 수 있어요.

탐색은 DFS 로 해결했어요. 가지치기 조건을 더했죠.

 

관계형 데이터베이스를 사용하기 때문에 트리를 document 로 그대로 저장할 수 없었어요.

트리 형태를 구현할 수 있도록 테이블을 설계하고, 그걸 메모리에서 트리로 구현했습니다.

이 트리는 Affiliate System 의 코어 구조이기 때문에 매번 요청이 발생할 때마다 데이터를 불러와 구현하면 성능에 문제가 생겨요.

루트의 아이디를 key, 트리 전체를 value 로 해서 로딩 캐시를 이용해 캐싱했습니다.

 

코어 구조만 잘 설계하면 될 줄 알았는데 여러 문제가 터졌습니다.

원본 리스트를 getter 로 그냥 반환해버리는 바람에 원본 리스트가 손상되어 그 유명한 StackOverflow 에 빠지는 일도 있었고,

익숙하지도 않은 python 으로 정산 로직을 작성하는데 java 와 분명 똑같은 로직임에도 다르게 동작하는 걸 한참 쳐다보기도 했어요.

 

python 의 경우 a.addAll(b) 후 b.clear() 를 수행하면 a 에 더해진 b 의 element 들도 clear 됩니다.

하지만 Java 는 a.addAll(b) 를 수행하면 내부적으로 b 배열을 복사해서 a 에 추가하기 때문에 b 를 clear 해도 a 는 영향받지 않아요.

물론 파이썬에도 java 와 내부적으로 비슷하게 동작할 수 있도록 하는 메서드가 있었습니다.

하지만 파이썬 초심자 한헤더는, 이 내용을 공부한 후에야 그 메서드를 찾을 수 있었답니다.

 

파이썬으로는 정산되어야 할 레코드 데이터를 만들고, 실제 지급 로직은 java 로 작성했어요.

지급되고 나서 부모-자식 관계를 변경한다든가 회원들을 이동시키거나 커미션율을 변경하는 이벤트들을 처리하죠.

 

여기까지 하면 코어 자료구조, 로직을 모두 작성했습니다.

이제 필요한 데이터를 서빙해야 하는데, 큰일입니다.

필요한 데이터가 여러 데이터베이스 인스턴스/스키마 곳곳에 나누어 저장되어 있어요.

심지어 거래 체결 건과 같이 하루에도 어마어마하게 많은 데이터가 저장되는 테이블 여러 개를 조회해야 합니다.

어떻게 해야 할까요? Affiliate System 을 위한 DW 시스템을 만들었습니다.

 

daily, weekly, monthly 이렇게 세 개의 기준을 두고 건별 데이터를 집계했어요.

1분, 3분, 10분마다 스크립트를 실행해 daily, weeklly, monthly 를 기준으로 집계되는 데이터를 서빙했습니다.

하지만 동일한 데이터가 4개 테이블에 나뉘어 저장되니, 가져오는 것도 기준을 잡아 가져와야 했어요.

2023.02.01 18:00:00 부터 2023.03.20 16:00:00 이 범위 내의 데이터를 가져와야 한다면 세 개 테이블을 모두 조회해야 합니다.

2월 한 달은 monthly 에서, 3월 2개 주는 weekly 에서, 나머지는 daily 에서 조회해야 하죠.

하지만 이것도 일관적으로 적용할 수는 없습니다.

daily 에서 조회해도 되는데 weekly, monthly 를 조회한다면 오히려 성능이 저하될 수 있기 때문입니다.

그래서 한 달이 넘는 기간인지, 한 주가 넘는 기간인지 먼저 검사한 후에 저 로직을 태울 수 있습니다.

 

이 모든 로직들을 사수님과 함께 한 달 만에 개발했어요.

야근에 휴일 근무에 주말 근무까지, 할 수 있는 모든 시간을 끌어다 썼습니다.

데이터 모델링, 테이블 설계, 코어 자료 구조와 코어 로직은 메인 작업자인 제가 했고, 데이터 서빙과 API 개발은 사수님이 도와주셨습니다.

 

힘들었던 작업이었지만 그만큼 기억에도 많이 그리고 오래 남는, 그 이름도 찬란한 Affiliate System 이었습니다.

 

2. MSA 설계해보기

이 태스크는 1번 Affiliate System 의 토대를 준비하며 진행했습니다.

 

우리 거래소 시스템은 모든 서버 애플리케이션 및 라이브러리들이 Java 11 과 Spring Boot 2.X.X 를 사용합니다.

시스템 리뉴얼을 목표로 하기 때문에 이번 프로젝트를 기점으로 앞으로 차차 버전 올릴 준비를 시작해야 했어요.

Spring Boot 버전을 3.X.X 로 올리려고 하니 Java 17 지원이 필수였고, 그렇게 버전을 바꾸게 되었습니다.

(Java 17 로 버전을 바꾸고 잘 사용하는 것 중 하나는 Stream.toList() 예요. UnmodifiableList 를 반환하는 이 API 는 참 편리합니다.)

 

Java 17 을 사용해 빌드하기 위해서는 Java 17 이미지를 만들어줘야 했습니다.

centOS 에 Java 17 을 직접 다운받고 심볼릭 링크도 설정하도록 스크립트를 작성해 빌드에 사용할 이미지를 만들었습니다.

Java 17 이미지로 서버 애플리케이션들을 빌드하기 위해 CI 파일도 건드려봤어요. 역시나 재미있었습니다.

 

토대 작업을 마치고 Affiliate pod 를 띄우기 위해 gRPC Client Pool, 여러 제반 코드들을 가져오려고 보니 세상에.

MSA 로 구성된 약 2-30개의 서버 애플리케이션이 5개의 라이브러리에 의존하는 구조였어요.

심지어 라이브러리(jar 로 패키징하는 애플리케이션들)가 다른 라이브러리에 의존하면서 애플리케이션 간 의존도가 굉장히 높았습니다.

 

잘 와닿지 않으실 것 같아요. 간단하게 네 개의 애플리케이션(a, b, c, d)으로 설명해보겠습니다.

 

a와 b는 서버 애플리케이션입니다.

c는 라이브러리고, c에 의존하는 다른 라이브러리 d가 있습니다.

c가 변경되면 c에 의존하는 d를 다시 빌드해줘야 합니다.

그러면 d에 의존하는 서버 애플리케이션 a와 b도 다시 빌드, 배포해야 하죠.

c를 조금 수정했을 뿐인데 줄줄이 소시지들처럼 딸려나옵니다.

 

이건 마치 MSA 의 모습을 한 거대한 Monolithic 시스템, 즉 생명주기만 다르게 구성된 모놀리식 시스템이라는 생각이 들었어요.

이대로는 안되죠. 진정한 의미의 MSA 를 위해 '공통 라이브러리'를 만들기로 했습니다.

 

지금은 K8S namespace 별로 xxx-proto, xxx-lib 가 있고 그 라이브러리에 의존하는 xxx-common 이라는 라이브러리가 있어요.

이제는 proto 와 lib 을 하나로 구성하고 서버 애플리케이션에서 저 두 가지 라이브러리에 직접 의존하도록 변경할 참이었습니다.

 

하지만 본격적인 작업 이전에 남아있는 것이 있죠. 엔지니어들을 평생 따라다니는 숙제, 네이밍입니다.

이름을 정하는 데에도 참 고민이 많았어요.

 

  1. 이전 아키텍터가 이렇게 네이밍한 데에는 의도가 있지 않을까?
  2. common 이라고 함은 어떤 범위까지를 말하는가?
  3. 두 서버 애플리케이션이 공통으로 의존하게 된다면 그것도 결국 common 이 아닐까?

 

결국 common 이라는 단어를 사용했지만, 세 가지 의문에 대한 답을 명확하게 내렸기 때문에 실장님도 제 의견에 동의해 주셨습니다.

  1. 아키텍터가 이 시스템을 설계할 당시에는 없었던 라이브러리들이 필요에 의해 생겨난 흔적이 있다.
    namespace-common-lib 뿐 아니라 xxx-yyy-common 등 비슷한 기능을 하는데 네이밍 방식이 다른 라이브러리가 있다.
    시스템이 분화되면서 당초 아키텍터의 의도는 이미 흐려진 것으로 보고 시스템 리뉴얼을 진행한다.
  2. 모든 서버 애플리케이션에서 사용하는 것을 common 이라고 부르자.
  3. 라이브러리를 멀티모듈로 구성해서 필요한 모듈만 가져다 쓸 수 있도록 하면 common 이라는 이름을 사용하는 데에 문제가 없다.

이제 이름도 정했고, 거대한 라이브러리들을 분리하는 일이 남았죠.

목표는 애플리케이션 간 의존도를 낮추는 것이었습니다.

 

그런데!

 

라이브러리를 common-proto, common-lib 으로 분리하고 나니 하나가 더 거슬리는 것이 아니겠어요?

바로 여러 서버에 중복된 Entity, Mapper 및 데이터소스 구성파일들이었습니다.

 

스키마만 20개 이상을 사용하는 이 거대한 시스템은, 당연히 하나의 서버 애플리케이션에서 여러 개의 데이터 소스를 참조합니다.

같은 데이터 소스를 참조하더라도 서버 애플리케이션마다 각각 데이터소스를 설정해줘야 하니, 서버 애플리케이션마다 데이터 소스 구성파일이 존재했습니다. Entity, Mapper 도 당연해요.

 

어떻게 해야 할까요?

일단 common-data 라는 라이브러리를 만들었습니다. 이제 우리의 common 은 세 가지 갈래가 된 거예요.

 

  • 에러코드나 여러 유틸 코드들이 존재하는 lib
  • proto 파일들이 존재하는 proto
  • database 에 접근하기 위한 data

common-data 를 구성할 때에도 여러 문제가 있었지만, @ConditionalOnProperty 를 사용하고 이 라이브러리 역시 멀티 모듈로 구성해 해결했습니다.

 

물론 아직 모든 서버 애플리케이션에서 세 가지의 common 라이브러리들을 사용하지는 않아요.

Affiliate System 부터, 그 이후에 진행되는 신규 프로젝트들은 모두 common 라이브러리를 사용한답니다.

 

이 경험으로 MSA 를 구성하기 위해 어떤 고민을 해야 하는지, 설계한 아키텍터가 없더라도 계속 잘 유지되게 하려면 어떤 이름을 갖고 또 어떤 구조를 가져야 하는지 참 많이 생각해봤고 많이 배웠습니다.

 

한 마디로 정리하면, 재미있었어요!

 

3. MQ

가장 최근에 구현한 기능에서 MQ 를 사용했습니다.

produce 부분부터 전부 구현한 것은 아니고, produce 지점을 찾아내 해당 메시지를 consume 하는 consumer group 을 만들고 멀티 스레딩을 통해 로직을 구현했습니다.

 

요구사항은 이상 가격 체결 건에 대한 모니터링을 위해 알림을 발송해달라는 거였어요.

그러면 비교할 기준이 필요하고, 체결 건이 필요합니다.

모든 체결 건을 실시간으로 받는다는 건, MM 체결 건을 포함하기 때문에 무지 많은 데이터를 처리해야 한다는 뜻이기도 했어요.

비교 기준은 특정 interval 의 K-line 이었는데, 가장 짧은 인터벌이 1분이기 때문에 1분보다 짧은 주기로 가져와야 함을 의미해요.

이 기능의 핵심은 데이터의 정확도였습니다.

 

체결이 10시 9분 40초에 발생했는데 10시 9분봉이 아니라 10시 8분봉을 가져오면 어떻게 될까요?

1분 차이로 기준이 달라지고, 기준이 달라지면 변동률 계산에 오류가 생기게 됩니다.

 

물론 서버에서 1분은 매우 긴 시간이기 때문에 잘못 가져올 일이 없다고 생각하실 수 있지만, 체결 건과 실시간 K-line 은 둘 다 매우 많은 데이터입니다. 심지어 모든 거래 페어의 체결 건을 모니터링해야 하기 때문에 데이터는 페어 수에 비례해 증가하죠. 중간에 잘못 끼어들었다가 데이터 정확도고 뭐고 다 무너지는 상황이 발생하는 장면을 머릿속에서 수도 없이 그려보았습니다.

 

로직을 설계합니다.

이미 체결 내역을 produce 하는 부분이 구현되어 있었어요. 그 말은 어디선가 이 메시지를 consume 하고 있다는 의미이기도 합니다.

MQ 마다 이 구현이 다른지는 잘 모르겠지만, 이 시스템에서 사용하는 RocketMQ 는 하나의 메시지를 여러 consumer group 에서 받을 수 있었습니다. consumer group 내부에서는 BROADCASTING, CLUSTERING 전략을 선택하면 되죠.

 

그렇다면 필요한 것은?

새 consumer group, 스레드풀 그리고 가장 중요한 정교하게 계산할 수 있는 로직, 기준이 되는 1분봉 kline.

필요한 것들을 나열했을 뿐인데 벌써 설레고 막 들떴습니다.

 

로직을 작성하면서 생각하는대로 되지 않을 때도 있었고 문제가 생긴 적도 있었지만, 그토록 해보고 싶은 것들을 쓴다는 생각에 하나도 지치지 않았습니다. 안풀리던 로직을 글로 풀어서 쓴 노트는 지금 봐도 뿌듯해요.

 

이 기능 구현으로 얻은 건 이것들입니다.

  • 두 로직 간 의존을 낮추고 실행되는 서버 애플리케이션도 분리해, 비동기로 동작하도록 MQ 를 사용해 본 것
  • 정교한 조건을 검증해야 하는데 데이터량이 매우 많을 때에는 두 가지 방식의 조건 검토를 사용해 2개 layer 로 작업할 것
  • 많은 데이터를 실시간으로 다뤄야 할 때에는 예외를 발생시키는 것보다 특정 값을 리턴하는 방식으로 처리할 것

정교함이 생명이었지만 구현해야 하는 규모가 큰 기능은 아니었기에 개발 기간은 여기 나열한 다섯 개 중 가장 짧았습니다.

가장 최근에 구현한 기능이기도 하고 새로운 수단을 사용해봤으며 실시간 데이터를 다뤘다는 점에서 두 번째로 행복했던 업무였어요.

(첫번째는 단연코 Affiliate System 입니다. 많이 고생한만큼 많이 배웠고, 기억에도 오래 남을 것 같아요.)

 

4. 쿼리 튜닝을 통한 성능 개선

이 부분은 공부중인 내용에서 실컷 자랑했기 때문에 넘어갈게요. 자랑도 정도껏 해야지, 더 했다가는 그만 읽으실 것 같으니까요!

 

5. 데이터 준비의 달인

저는 거래소 내부 시스템에 구현된 데이터 정제 파이프라인을 가장 잘 아는 사람 중 한 명입니다.

파이썬으로 된 스크립트들(사실상 100줄 이상의 SQL 들이 거의 전부인 SQL 실행기)을 분석하면서, 이 무지막지한 데이터들을 빠르게 서빙하기 위해 이전 작업자들이 했던 노력을 엿볼 수 있었어요. 정말 존경합니다.

지금은 이 회사에 안계시지만 이 시스템을 구현하신 분들, 어디 계세요... 정말 꼭 한 번 만나뵙고 싶습니다!

 

그 분들의 노하우를 많이 습득했어요.

그걸 토대로 1번 Affiliate System 의 DW System 을 구축했고, 세 단계로 정제되는 데이터 파이프라인을 가장 먼저 파악해 추가로 필요한 데이터를 정제하는 일에도 많이 기여했습니다.

 

데이터를 준비하고 정제하는 일은 정말 재미있어요.

데이터가 준비되어야 로직을 전개할 수 있다는 점에서 데이터 준비는 개발의 시작, 그 이전에 있는 것 같습니다.

또 기획에 맞게 데이터를 준비하고 정제해야 하기 때문에 기획과 개발 사이에 있다고 할 수도 있죠.

 

여기 적지 않은 다른 프로젝트들에서도 제가 직접 데이터를 준비하고 정제해 사용했고,

이번에 다른 분이 작업하는 프로젝트에서도 제가 미리 준비해 둔 데이터를 쓴다고 합니다.

정말 정말 뿌듯해요. 데이터를 정제하는 일에는 SQL 작성도 빠질 수가 없기 때문에 이것 역시 제가 가장 좋아하는 일입니다.

 

프로젝트는 여기까지 정리하고, 이젠 저의 작은 딴주머니를 열어 보여드리겠습니다.

 


 

살짝 찼던 옆주머니

사이드 프로젝트, 토이 프로젝트 그리고 자아 실현의 장이라고 불립니다.

이 프로젝트는 일주일에 한 번 진행했는데, 진도에 전혀 연연하지 않고 하고 싶은 것들을 전부 다 해보는 데에 의의를 두었습니다.

가장 기억에 남는 건 이슈로도 정리했던 gRPC 예외 처리에 관한 것인데, 내부 라이브러리 코드를 뜯어보면서 정말 재미있었던 기억이 아직도 생생합니다.

 

gRPC 의 예외 처리에 대해 깊이 이해해 본 경험은 업무에서도 당연히 도움이 되었습니다.

회사에서 처음 배운 gRPC 를 이제는 사이드 프로젝트에 적용하며 사이드 프로젝트 동료 작업자에게 알려줄 수 있게 되다니...

이것 또한 얼마나 재미있는 경험이겠어요. 이쯤되면 제가 재미없어하는 걸 찾는 게 더 빠르다는 것... 눈치채셨을까요?

 

지금 저희의 자아실현 주제는 진정한 MSA 구현이에요.

토큰 발행 및 관리는 security 모듈에서, 로그인은 user 모듈에서 하고 다른 로직이 있다면 다른 모듈에서 로직을 전개하도록 구성해요.

각각의 서버 애플리케이션들을 경량화하면서도 각각의 역할이 잘 드러나도록 설계를 변경하고 있습니다.

 

회사 시스템과는 다르게 gradle 기반으로 작업하고 있어서 조금은 낯설지만, 이것도 정말 정말 재미있어요.

현실과 타협하느라 하지 못했던 걸 여기서 다 쏟아낸다...! 는 마음으로 임하고 있습니다.

(이 마음가짐을 '시골마을에 8차선 고속도로를 뚫는 일은 피하자' 로 항상 자기소개에 넣고 있는데, 다른 글에서 더 자세히 적어볼게요.)

 

연말이라 지금은 잠깐 쉬고 있지만, 앞으로도 꾸준히 진행할 생각입니다.

 


 

개발문화를 위해서

제가 입사하고, 다섯 명의 백엔드 개발자 분들이 저희 팀에 합류했습니다.

제가 입사할 때만 해도 실장님을 포함한 백엔드 개발자가 넷 뿐이었어요. (실장님, 사수님 두 분 그리고 한헤더)

코드리뷰는 비동기 방식이 아니라, 프로젝트를 릴리즈하기 전에 (물론 동기식으로) 회의실을 잡고 진행되었다고 합니다.

 

저는 위에 말한 방식의 코드리뷰를 경험하지는 못했어요.

당연히 비효율적이었을 그 코드리뷰는 제가 입사함과 동시에 없어졌습니다.

그런 코드리뷰라도 있었다면 제 코드를 누군가는 봤을텐데,

저는 입사 후 약 1년 3개월 간 아무도 보지 않고 그 로직은 오로지 나만 알고 있는 코드를 작성했습니다.

 

유지보수를 용이하게 하는 코드가 좋은 코드이다.

유지보수가 쉬우려면 먼저 읽기에 편해야 한다.

읽기에 편하다는 것을 어떻게 알 수 있지?

누군가 내 코드를 읽고 피드백을 해 주면 좋겠다.

우리에게도 코드리뷰가 필요하다!

 

이런 생각의 흐름대로, 저는 코드리뷰의 필요성을 기회가 있을 때마다 주장했어요.

그 결과 올해 12월, 저희 팀에도 공식적인 코드리뷰 프로세스가 생겼답니다.

이전부터 코드리뷰가 이미 체계화된 곳과 비교한다면 한참 더 나아가야 하겠지만, 누군가 제 코드를 업무시간에 읽고 피드백한다는 건 정말 행복한 일이었어요.

 

단순히 피드백이 아니라, 혹시 있을지도 모르는 오류나 로직의 결함 등도 발견할 수 있는 좋은 기회니까요.

저는 아직 제가 작성한 코드들을 많이 사랑하지만, 더 좋은 방법이 있을 때에는 그 방법으로 주저없이 바꾸려고 해요.

그런 과정을 거쳐 제게 체화될테니까요.

 

요즘은 또 한가지 필요하다고 열심히 피력하고 있는 게 있습니다.

바로 테스트코드예요.

 

기존 시스템의 애플리케이션 간 의존도가 높다보니, 시스템 리뉴얼 전까지는 로컬에서 실행해 볼 수 없습니다.

로그를 한 줄 출력해보고 싶어도 무조건 DEV 서버에 배포해야 해요.

또 기존 레거시에 대한 문서화도 전혀 되지 않은 상태였습니다.

API 스펙도 규격화되어 있지 않고, 어느 한 부분을 바꾸면 그 영향도를 파악하기 위해 해당 부분을 참조하는 곳을 모두 읽어봐야 합니다.

 

이런 환경에서 점차 테스트코드를 작성해나가다보면,

문서화가 완벽하지 않더라도 API 스펙을 규격화할 수 있을 거라고 생각했습니다.

또 어느 한 부분을 바꿔서 다른 부분에 영향이 미친다면 테스트를 통과할 수 없기 때문에, 장애의 확률도 낮출 수 있겠죠.

 

테스트코드 작성이 당연시되는 환경이 아니기 때문에 아직 환영받는 의견은 아니지만,

저는 꾸준히 의견을 낼 거랍니다.


 

휴!

길고 긴 2023 회고가 끝났어요.

회고라 쓰고 지 자랑이라고 읽어야 할 것만 같지만, 저는 다양한 일을 하면서 무척 재미있었고 그만큼 많이 성장했습니다.

 

내년에는 어떤 일을 하게 될까요?

저는 얼마나 많이 배우고 또 다른 개발자들과 얼만큼의 선한 영향력을 주고받으며 성장할까요?

 

궁금하시다면 저의 2024 회고가 나올 때까지, 아 아니다.

앞으로는 이렇게 몰아서 쓰지 않고 각각을 포스트로 나누어서 여러 번 적어보려고 해요.

 

내년에는 본격적으로 코어 로직 성능 개선 및 연구 개발을 맡을 예정이라,

제 성과들을 prometheus 나 grafana 지표를 통해 보여드릴 수도 있을 것 같아요.

얼만큼 기여할 수 있을지 모르지만, 제 삶의 모토는 이거거든요.

순간순간 행복하게, 순간순간 최선을 다하자.

 

2023년은 순간순간 충분히 행복했어요.

매 순간 최선을 다했기에 회고가 이만큼이나 길어질 수 있었죠.

저는 아마 앞으로도 순간순간 행복하기 위해 매 순간 최선을 다할 거예요.

 

그럼, 여기까지 긴 글을 읽어주셔서 감사합니다.

다음 글 또는 2024 회고에서 만나요.