서론
안녕하세요! 저는 쿠키런: 마녀의 성 서버를 담당하고 있는 5년 차 게임 서버 개발자 주윤아입니다.
이직을 고민하고 계신가요? 새로운 팀에 합류하거나, 전혀 다른 코드베이스에서 일하게 된다는 건 많은 개발자에게 큰 도전으로 다가올 수 있습니다. 저 역시 같은 고민을 했습니다. 전 직장에서는 하나의 프로젝트에 4년 동안 몸 담으며 처음부터 끝까지 모든 과정을 경험했기 때문에, 새로운 환경에서 타인의 코드를 이해하고, 빠르게 적응해 성과를 낼 수 있을지 걱정이 컸습니다.
하지만 그런 두려움에도 불구하고, 저는 데브시스터즈에서 1년 동안 두 개의 프로젝트에 참여해 각기 다른 코드베이스를 학습하고, 저의 것으로 만드는 과정을 거쳤습니다. 그 과정에서 크고 작은 기능 구 현과 업데이트를 성공적으로 완료 하며 팀에 완전히 녹아들 수 있었죠.
본론에 들어가기 앞서, 첫 번째 팀이 아닌 두 번째 팀인 쿠키런: 마녀의 성 코드베이스 적응 과정에 집중하려고 합니다. 그 이유는, 두 번째 팀에서 경험한 것이 저에게 더욱 큰 도전이었기 때문입니다. 이전 팀에서는 익숙했던 C# 기반의 객체 지향 프로그래밍 언어를 사용했지만, 두 번째 팀에서는 함수형과 객체 지향 멀티 패러다임 언어인 Scala 를 처음 접하게 되었고, 더불어 새로운 아키텍처를 학습해야 했습니다. 또한 당시 혼자서 학습을 해야 했던 특수한 상황이었기에 그 과정은 더욱 까다로웠습니다.
이번 글에서는 제가 새로운 코드베이스에 적응하고, 그것을 내 것으로 만드는 과정에서 느꼈던 고민들과 배운 점들을 공유하려 합니다. 이직 후 새로운 팀에 적응하는 것이 막연하게 느껴지는 주니어 개발자들에게 이 글이 작은 도움이 되길 바랍니다.
본론
공부의 순서 정하기
새로운 팀에 합류하면서 낯선 코드 베이스와 프로그래밍 언어를 어떻게 효율적으로 익힐 수 있을지 고민이 컸습니다. 사람 마다 학습 방법이 다르겠지만, 저처럼 정석보다는 꼼수에 의존해온 사람에게는 특히나 공부의 순서를 정하는 것이 어려웠습니다. 제가 정한 학습 흐름은 크게 세 가지 단계로 나눌 수 있었습니다.
- 문법 학습 : 새로운 언어의 기본 문법을 익히는 것이 가장 중요했습니다. 이 과정에서 사내에서 모든 스칼라 개발자가 완독했다는 빨간 책이라는 scala 관련 서적을 참고했습니다.
- 프레임워크 학습 : 서버 개발을 위해 사용되는 ZIO 프레임워크의 구조와 동작 방식을 파악했습니다.
- 상업 코드 분석 : 실무에서 작성된 코드를 분석하고 작은 퀘스트들을 수행하며 경험치를 쌓았습니다.
기존에 알고 있던 객체지향 언어들과 달리 새로운 패러다임을 익히는 과정은 고통스럽기도 했지만, 사내 상업 코드를 보며 월급을 받으며 새로운 언어를 학습할 수 있다니, 완전 럭키비키🍀 였습니다.
새로운 팀의 코드 아키텍처
현재 팀의 코드베이스는 제가 익숙했던 기본 아키텍처와는 달랐습니다. 헥사고날 아키텍처와 도메인 주도 설계(DDD)를 기반으로 한 방식은 개념으로만 알고 있었고, 실제로 적용해 본 적은 없었습니다.
처음에는 낯선 함수형 언어와 새로운 아키텍처에 당황하기도 했습니다. 마치 대학 시절 객체 지향 프로그래밍 언어를 처음 배웠을 때의 혼란스러움이 떠오르더군요. 그 당시 “그래서 인터페이스가 뭔데?”라는 질문을 던졌다면, 지금은 “모나드가 뭔데?”라고 묻고 있는 상황이죠. 이러한 개념들은 여전히 머리로는 이해하기 어렵지만, 경험을 통해 가슴으로 이해하게 되는 순간들이 있었습니다.
낯선 코드 속에서 길 찾기
새로운 코드베이스에 적응하기 위해 협업 미팅을 통해 약 일주일간 스칼라 문법과 프레임워크를 학습했고, 그 후 3주간 실제 퀘스트를 진행했습니다. 이 과정에서 가장 많이 사용한 방법은 코드 분석과 디버깅이었습니다. 디버깅 방법도 과거의 저와 달라졌습니다. 예전에는 오로지 printf
디버깅만으로 문제를 해결했었는데, 이제는 디버거 없이는 작업하기 어려운 상황이 되었죠. 물론 콜스택이 많이 쌓이는 경우에는 여전히 printf
를 찍어 가며 분석하는 경우도 있긴 합니다. 😊
새로운 언어, 새로운 패러다임, 새로운 프로젝트이기 때문에 모든 것이 낯설었습니다. 특히, 이미 출시된 게임 프로젝트의 방대한 코드와 구조를 빠르게 파악하는 것은 쉬운 일이 아니었습니다.
그래도 게임 서버 개발자로서의 핵심 역할은 유사할 것이라는 믿음으로, 우선 SignIn
기능에 집중했습니다. 로그인은 어떤 게임이든 필수적인 통신이며, 이 프로토콜을 완벽히 이해하면 팀의 구현 프로세스를 파악하는 데 도움이 될 거라 생각했습니다. 기획 문서를 파고들 필요 없이, 한 가지 프로토콜만 잘 이해해도 프로젝트 전반에 대한 감을 잡을 수 있으니까요!
첫 번째 퀘스트 : 코드 분석과 기본 익히기
가장 먼저 한 작업은 서버 컴파일 및 서버 실행이었습니다.
모든 개발의 첫 단계는 프로그램이 로컬 환경에서 컴파일되고 실행되는 것입니다. 팀마다 개발환경이 다르기에 이 과정에서 많은 시간을 할애하게 되었습니다. 로컬 문제인줄 알았던 것이 팀 문제였고, 팀 문제인 줄 알았던 것이 로컬 문제로 판명되는 재밌는 상황도 펼쳐졌죠. 일반적이지 않은 의존성 문제나 데이터베이스 프로토콜화 변환이 익숙지 않아 처음에 많이 헤매기도 했습니다.
두 번째 퀘스트 : 로그인 보상 기능 구현
로그인 시 보상을 주는 기능은 단순해 보이지만, 함수형 프로그래밍 패러다임에 익숙해질 좋은 기회였습니다. 이 퀘스트의 핵심은 이벤트를 발생시키는 liftEvent
함수의 사용이었는데, 이는 함수형 프로그래밍에서 사이드 이펙트를 관리하는 일반적인 패턴 중 하나입니다.
liftEvent
는 이벤트를 처리하기 위한 사이드 이펙트를 함수형 패러다임 내에서 안전하게 발생시키기 위해 사용됩니다. 함수형 패러다임의 기본 개념인 함수는 하나의 기능을 수행해야 한다
는 원칙을 따르면서도, 하나의 함수 내에서 이벤트 발생이나 로깅 등의 사이드 이펙트를 처리할 수 있는 방법입니다. 즉, 순수한 계산의 흐름 속에서 이벤트 발생과 같은 부수 효과를 끼워 넣을 수 있는 형태로 구현 되는 것이죠.
Scala 에서 암묵적 매개변수(implicit parameter)가 컴파일러에 의해 자동으로 전달되는데, liftEvent
와 같은 함수에서 이러한 암묵적 매개변수가 함수의 동작에 필요한 Context 를 제공할 때 특히 유용합니다. liftEvent
함수는 보상 이벤트를 처리하는 데 필요한 환경을 암묵적으로 받기 때문에, 코드가 간결해지고, 함수형 설계 원칙을 유지하면서도 필요한 사이드 이펙트를 효과적으로 관리할 수 있습니다.
세 번째 퀘스트 : gRPC 프로토콜 이해와 연습
운영툴 프로토콜에서 gRPC 생성 후 print 찍기는 간단한 수정 작업이었지만, Scala 에서 타입 일관성을 유지하는 스칼라 로직의 특징을 익히는 데 중요한 역할을 했습니다.
특히, ZIO
에서 사용되는 for
표현식에서의 타입 불일치 문제를 이해하고 프로토콜 작업의 기본 구조를 익혔습니다.
scala 에서 println
과 같은 사이드 이펙트는 zio.succeed
로 감싸서 ZIO 모나드 형태로 만들어야 합니다. zio.succeed(println("example"))
는 ZIO[Any, Nothing, Unit]
타입의 값을 변환하여 안전하게 사이드 이펙트를 처리하는데, 이는 함수형 프로그래밍의 원칙을 유지하면서도 로그 출력과 같은 작업을 가능하게 합니다. 특히 for
표현식에서는 flatMap
, map
, withFilter
등의 연산이 순차적으로 올바른 타입을 반환해야 하므로, 타입 불일치를 방지하기 위해 각 연산에 맞는 형태를 유지하는 것이 중요합니다.
네 번째 퀘스트 : 운영 gRPC 에서 운영로그 남기기
gRPC로 로그를 남기는 작업에서는 특히 로그의 중요성을 새삼 느꼈습니다. 게임 운영 중 발생하는 CS 요청이나 버그 분석을 위해서 꼼꼼한 로그 작성은 필수적입니다. 처음에는 분석 로그 구조와 삽입 위치를 몰라 디버깅이 어려웠지만, 지금은 분석 로그 클래스 계층을 상속받아 liftEvent
로 필요한 시점에 이벤트를 발생시키고, 이를 처리하는 함수에서 케이스를 추가하는 패턴을 익혔습니다.
이제까지의 과정은 새로운 코드베이스와 프로그래밍 패러다임에 적응하며 프로젝트 전반에 걸쳐 필요한 기초를 다지기 위한 시간이었습니다.
Scala 와 함수형 프로그래밍에 익숙해지기 위해 첫 주는 문법과 개발 환경을 설정하는 데 집중했고, 이후 실제 퀘스트를 수행하며 코드를 분석하고 로컬 환경에서 컴파일과 실행을 반복했습니다. 특히 SignIn
기능 구현을 통해 기초 프로토콜의 흐름을 파악하고, 이벤트 처리를 위한 liftEvent
를 활용하면서 사이드 이펙트를 제어하는 패턴도 실습했습니다.
약 3주 간의 집중적인 학습과 디버깅 과정을 통해 새로운 언어와 시스템에 적응하고, 코드 베이스의 핵심 구조와 팀의 개발 방식을 이해하는 중요한 발판을 마련할 수 있었습니다.
작은 피처에서 큰 피처까지
팀 이동을 성공적으로 마친 뒤, 작업의 첫 단계에서는 광고 시스템 관련 작은 피처를 수정했습니다. 비록 간단한 수정 작업이었지만, 프로토콜 추가 및 기획 데이터 테이블 연동 과정에서 코드베이스의 구조를 이해하는 데 많은 도움이 되었습니다. 이후 조금 더 큰 작업인 쿠키 퍼즐 챌린지 작업에 착수했을 때는 더 복잡한 로직을 다뤄야 했고, 아키텍처 간의 상호작용을 이해하는 것이 필수적이었습니다.
작은 피처들을 작업하면서, 제가 한 동안 사내 개발자들 분께 입버릇 처럼 하는 말이 있었죠. “작업 하긴 하는데, 머리가 아니라 본능대로 손이 코드를 짜는 기분이에요-”
프로젝트 내에 원하는 로직을 조립하는 것에는 익숙해 졌지만, 코드 전체 흐름은 전혀 보이지 않던 상황이었습니다.
점차 작업의 난이도가 높아졌고, 특히 유적 탐험 이벤트 작업은 워크타임만 약 2-3주가 걸렸습니다. 이 작업을 통해 코드베이스의 큰 그림을 완전히 파악할 수 있었습니다. 그 이전에는 나무는 보였지만 숲은 보이지 않았던 상황이었다면, 이제는 큰 틀 안에서 작은 피처들을 이해하고 구현할 수 있게 되었습니다.
이렇게 차근차근 작은 작업부터 큰 프로젝트까지 경험하면서, 팀의 코드를 내 것으로 만들 수 있었고, 새로운 환경에 대한 두려움도 서서히 사라졌습니다.
도전과 극복
함수형 프로그래밍 패러다임 자체가 낯설어 개념 이해에 시간이 많이 소요되었습니다. 기존에 익숙했던 객체지향 패러다임과 달리, 스칼라는 문법이 복잡하여 한 가지를 이해했다 생각해도 다른 부분을 보는 순간 백지가 된 기분이었습니다.
가장 어려웠던 점은 문서화의 부족이었습니다. 게임 프로젝트 팀이라면 다들 공감하실 텐데, 초기에는 탄탄한 아키텍처와 문서화 작업을 해놓아도, 출시가 가까워지면 급변하는 요구 사항으로 인해 계획이 엎어지기 마련이죠. 그러다 보니 복잡한 코드와 생소한 언어를 문서화 없이 익히는 데 꽤 고전했습니다.
학습 과정에서 많은 팀원분들의 도움을 받았으며, 특히 파트장님께 질문을 자주 던져 문제를 해결했습니다. 질문을 할 때 꿀팁이 있다면, 무작정 안된다고만 하지 않고 스스로 ‘이건 왜 작동이 안되는 걸까-?’ 사고해보며 이런 저런 액션을 취한 후, 본인이 생각했을 때 동작이 되지 않는 이유 혹은 동작하기 위해 어떤 작업을 했는지 머릿속에 정리 한 후 질문을 드린다면 좀 더 명쾌한 답을 얻으실 수 있으실 겁니다.
다행히도 저는 출시 이후에 합류했기 때문에 이러한 혼란 속에서도 새로운 코드베이스를 익히면서 어려운 부분들을 체크해 가이드 문서를 작성할 수 있었습니다.
팀과의 협업 : 코트 통합과 소통의 중요성
코드 리뷰와 피드백 과정을 통해 성장할 수 있었습니다. 코드 리뷰를 두려워하지 않고, 오히려 팀원들과의 소통을 통해 배워나가는 과정에서 많은 발전을 이룰 수 있었습니다.
또한, IT 업계 중 특히나 게임업계에서는 타 직군과의 소통 또한 중요한 요소로 작용했습니다. 게임 개발은 다양한 직군들이 협력해야 하기 때문에, 원활한 의사소통이 프로젝트 성공의 중요한 키가 되기도 하죠.
마무리
팀의 코드베이스를 처음 접했을 때는 모든 것이 생소하고, 새로운 환경과 도구에 적응하는 데도 시간이 걸렸습니다. 초기에는 작은 작업을 하나 할 때마다 기획서부터 꼼꼼히 준비해야 할 만큼 낯설었지만, 6개월이 지난 지금은 팀의 코드 흐름 과 아키텍처에 대해 이해하게 되어 비교적 자유롭게 작업할 수 있게 되었습니다. 심지어 팀 내에서 가이드 문서를 작성할 수 있을 정도로 익숙해졌습니다.
앞으로는 요구사항 구현을 넘어 시스템 개편에도 도전하고 싶습니다. 특히, DB 및 캐시 구조를 개선해 게임 성능을 최적화하는 프로젝트를 진행해 보고 싶습니다. 또한, 지금처럼 학습할 수 있는 기회가 있을 떄 근본적인 질문을 던지며 새로운 호기심도 품어보고 싶습니다. 적응 초기 단계의 질문은 성장의 원동력이 되기도 하니까요.
이번 적응 과정을 통해 깨달은 점도 많습니다. 게임 서버 개발자가 근본적으로 해야 할 일은 크게 다르지 않다-
라는 것처럼요. 결국 개발자는 소통하고, 필요한 프로토콜을 설계하고, 이슈를 해결해가며 끊임없이 나아가야 합니다.
또한, 팀에 새롭게 적응하는 데는 두 가지 접근법이 있다고 생각합니다.
시간적 여유가 있다면, 언어와 아키텍처를 충분히 학습한 뒤 작은 기능을 하나씩 구현하며 점진적으로 팀에 적응하는 것이 정석적인 방법이라 생각합니다.
그러나 빠른 기여가 요구되는 상황에서는 프로젝트와 언어를 동시에 익히면서 진행할 수 밖에 없는 경우도 많습니다. 이렇게 빠른 적응법을 사용하면 즉각적인 팀의 기여는 가능해지지만, 기초적인 개념이 머리에 남지 않을 위험도 크기 때문에 이후에도 지속적인 학습이 필요합니다.
마지막으로, 팀 적응과 언어, 아키텍처에 대한 깊은 이해는 별개의 문제임을 항상 기억했으면 합니다. 팀 적응에만 안주하지 말고, 내가 속한 프로젝트의 구조와 이론적 부분을 놓치지 않으려는 노력이 중요합니다. 그러한 지속적인 관심과 학습이 개발자로서의 성장을 이끌어 낼 것이라 믿습니다.