트랜잭션 이야기 - 개발자 마다 다른 DB를 대하는 자세

내 입장에서 웹 개발자 분들과 같이 협업하고 대화하면서 아이러니 했던 두가지가 있었다.

10년도 더 넘게 지난 얘기지만, 한가지는 비동기 응답이 어렵다는 이야기였고, 그렇다보니 여러가지 고민들 중의 해결책인 Ajax라는 이름으로 화두가 되고 있다는 얘기였다.

Native Socket를 다루는게 너무나도 당연하던 나에겐 어째서 비동기 응답을 받을 수 없는걸까에 대해 당황했던 기억이 있다.

또 한가지는 바로 DB를 대하는 자세였다.


기본적으로 웹 서버는 DB에 모든 것을 기록하려 한다. (혹은 아예 정적 데이터를 사용하던지)

로컬 파일 IO, 로컬 메모리 사용을 할 경우, 로드 밸런싱시의 유실등의 우려로 임시 파일 혹은 임시 데이터로만 다뤘다.

이전 요청과 현재 요청이 같은 서버로 간다는 가정을 하는 것 자체가, 로드밸런싱을 가로 막는 제약이 되어버리기 쉽상이기 때문이다.

이로 인한 DB성능에 대한 제약을 웹은 지연된 응답, 즉 캐싱으로 대처한다.

심지어 브라우저마저 캐싱을 기본적으로 지원하며 이는 웹 서버의 부담을 줄이기 위해 클라이언트인 브라우저 마저 캐싱을 지원하다니!

이는 지난번에 언급한대로, 웹의 발전에는 다수가 같은 컨텐츠를 봐도 되는 상황, 소수의 편집자가 데이터를 변경하는 상황, 일시적인 지연을 용인하는 상황 등이 근거다.


반면 훨씬 더 짧은 시간 내에 수많은 변경을 다뤄야 하는 게임에서는 DB를 그렇게 사용할 경우, 쓰루풋을 따라잡지 못해 병목 포인트가 된다.

그래서 게임 서버에서의 흔한 선택은 메모리 캐싱 -> 캐시 서버 -> DBMS 다.

백섭, 돈복사, 아이템 복사 등의 이슈는 바로 캐싱을 위한 제약 (캐싱이 동시에 여러곳에서 이루어 지지 않게 한다거나, 캐싱된 데이터가 저장되기 전에 다른 곳에서의 변경이 이루어지지 않게 한다거나, 일정 시간 단위 저장을 한다거나, 일정 이벤트에 맞춰 저장 한다거나)을 위배하게 되었을 때, 혹은 제약 자체가 서버 장애 혹은 네트웍 오류, 타이밍 버그 등으로 인해 붉어졌을 때 발생하는 일종의 취약점이자, 리스크라고 할 수 있다.

이런 선택과 한계, 장단점을 듣고 의아해하고 신기해하는 웹 개발자 분들이 많았다. 오히려, 나로썬 당연했던 이런 이야기가 신기하다는 것이 놀라웠다.

게임 서버의 응답성이 중요한 데이터 처리량은 일반적으로 디비 서버의 쓰루풋으론 따라가기 힘들다. 심지어 여기에 트랜잭션이 묶으면 쓰루풋 지옥이 펼쳐지기 쉽상이다.

트랜잭션은 실질적으로 동시에 접근하는데, 특정 데이터 묶음의 일관성을 유지하기 위해 큰 비용을 소모해서 거는 잠금이다. 그렇다보니 의도치 않은 쓰루풋의 급감을 끌어내기도 하지만, 호출 구조가 받쳐주지 않는다면 어쩔 수 없는 필연적 선택이기도 하다.

웹에서도 중요 데이터에는 트랜잭션을 묶고, 데이터 무결성을 지키게 되는데, 이는 애초에 같은 DB를 바라보는 웹 서버를 여럿 띄워서 로드 밸런싱하는 것이 아주 일반화된 상황이기 때문이라고 할 수 있다.

시대가 바뀌어가며 잊게되곤 하지만, 데이터 베이스 개론과 같은 책에서 언급하듯 DB의 시작은 파일 시스템이며, DBMS에 모든 것을 위임하면 쓰루풋이 급감하므로, 어플리케이션이 테이블 구조, 연관관계, 접근 방식을 DBMS에 맞출 필요가 있었다. 여전히 DBMS 운용 비용은 싸진 않으므로, 모든 코스트를 DBMS에 위임하는 것은 아직까진 낭비의 영역에 있다.

반면 게임에서는 트랜잭션이 필요하지 않게끔 어플리케이션 레이어의 DB 접근 규약을 정리하거나, 캐시 서버 단계에서 순서 관리, 동시 접근 제어 등을 통해 트랜잭션을 우회하는 방법이 존재한다.

이는 웹보다 게임이 다루는 엔티티가 많고, 데이터 변화량이 잦고, 빠른 응답성을 위해 여러가지 해결책이 고안되었고, 발전해왔다고도 볼 수 있다.

만약 게임서버건, 웹서버건 어쩔 수 없이 트랜잭션을 사용해야 하는 아키텍쳐를 구성해야 하거나, 이미 구성된 서비스를 운용해야 한다면, DB단위를 격리하고 (수평 파티셔딩 등), 결합이 있는 상황만 별개의 방식으로 처리하는 것이 좋지 않나 싶다.


DB의 가용량이 서비스의 가용량이라는 점은 게임 서버나, 웹 서버나 동일한 제약이다.

그래서 여러가지 우회방법이 고민되고, 서비스의 특성에 맞게 트레이드 오프를 하게 되는데, 이 과정에서의 접근이 발상이 게임이 조금 더 극단적이라는 것은, 아마도 모든 자원이 한참 부족했던 시기에 어떻게든 반응성, 쓰루풋, 안정성을 확보해야 했던 게임이라는 특수한 환경에서 벌어진 이슈였다고 생각하고, 지금은 조금 더 안정적인 아키텍쳐가 필요한게 아닐까 싶은 생각이 드는 것도 사실이다.


시기적인 영향도 없다고 볼 순 없는데, 서버 머신 스펙이 부족하던 시기, 네트웍 트래픽이 부족하던 시기, 네트웍 장비 오류, 네트웍 장비 성능도 부족하던 시기에 할 수 있는 최적화는 어플리케이션 내부에 대한 최적화였던 것도 한몫 했다.

나 역시 도커가 활성화 된지 한참 후에야 사용하고 적용하게 되었고, 도커가 상태 기반 서버에 적합하지 않은 측면이 많다는 점도 함께 알게 됐다. (몇가지 제약을 통해 우회 가능하나, 근본적으로 상태 기반 서버가 되면 될수록 제약과 단점이 많이 생기는게 사실이다.)

애초에 상태 기반 서버에서의 스케일 아웃은 꽤나 많은 실수의 소지, 운용 비용, 관리 비용, 기술적 난이도가 상승한다. Akka와 같은 Actor 기반 모델을 사용해서 해소할 수 있는 부분도 있긴하지만, 상태 기반 서버에서의 많은 습관과 상식을 바꿔야한다.

지금처럼 DBMS를 IOPS만큼 비용 지불하고 관리해주는 서비스도 없었다. 어떻게 접근해야 DBMS의 성능을 극대화 시키면서, 무결성을 지킬 수 있는지 잘 알지 못했다.


결과론적으로 트랜잭션은 어플리케이션에서 동시 접근 할 가능성이 높은 상황에서의 무결성을 위한 고비용의 잠금 객체라고 볼 수 있다

이를 위해 크리티컬 섹션과 보다 더 큰 코스트를 소모한다. 결과적으로 DB의 성능 효율과 트레이드 오프하게 되는 것인데, 성능이 덜 중요하되 무결성과 관리 비용이 중요하다면 선택함직 하지만, DB 성능의 중요성이 있다면 어플리케이션 단계의 아키텍쳐로 트랜잭션을 제거하는 접근을 하는 것이 현재의 대용량 처리의 트렌드이기도 하다.

그런 선택지 중에 NoSQL이나, Cosmos DB, Spanner같은 선택지도 고민해볼 수 있다. 즉 RDB와 트랜잭션은 절대적 선택지가 아니라, 상황별, 요구사항별 선택지라고 생각하는 유연함이 안정성과, 쓰루풋 모두 잡을 수 있는 접근이라고 생각한다.

RDB와 트랜잭션이 필수 불가결한 요소라고 생각된다면, 자신이 주로 사용하고 있는 프레임워크나 엔진의 아키텍쳐 떄문은 아닌지 검토해볼 필요가 있다. 혹은 자신이 익숙한 것에 집착하고 있는 것일 수도 있겠다.

꽤나 많은 기술 도입 과정에서의 논쟁에서, RDB와 트랜잭션에 대한 집착적인 생각을 가진 분들을 많이 만났고, 성능이 중요해질 수록 트랜잭션에 고통 받으면서도 그 선택이 피할 수 없는 굴레라고 느끼는 분들이, 편견을 내려 놓는 계기가 되었으면 하는 바램이다.

Kubernetis 이야기

쿠버네티스가 이미 너무나 당연한 대세가 된지 꽤 됐으나… 여러가지 속설과 사용해본 분들의 단편적인 감상만으로는 부족했다.

나는 작년이 되서야 제대로 사용해보게 되었는데, 그에 대한 감상과 경험담을 써보도록 하겠다.

직접 사용해본 결과, 확실히 어려운 부분이 존재는 하지만, 대부분의 학습 곡선이 네트워크 구성이고, 나머지 구성요소는 어차피 도커를 쓰던, VM위에 바이너리를 올리던 거쳐야 될 과정들이며, 도커 이미지화에 성공했다면 낮은 학습 곡선이라고 볼 수도 있을 정도의 장점도 많았다.

쿠버네티스는 컨테이너화된 워크로드와 서비스를 관리하기 위한 이식성이 있고, 확장가능한 오픈소스 플랫폼이다. 쿠버네티스는 선언적 구성과 자동화를 모두 용이하게 해준다. 쿠버네티스는 크고, 빠르게 성장하는 생태계를 가지고 있다. 쿠버네티스 서비스, 기술 지원 및 도구는 어디서나 쉽게 이용할 수 있다.

출처: https://kubernetes.io/ko/docs/concepts/overview/what-is-kubernetes/

배포 환경의 진화


선언적 구성이라 함은 YAML과 같은 설정 파일로 설정으로 도커 이미지들을 쉽게 배포할 수 있다는 것을 말한다.

자동화라함은, 적용되어있는 설정을 유지하기 위한 노력을 쿠버네티스가 지원해준다는 것을 말한다.

당연하지만 YAML 파일 자체는 직접 작성하거나, 작성을 도와주는 도구를 이용해야 한다.

레플리카 개수 지정만으로 쉽게 스케일 인-아웃이 가능한데, 이 설정은 당연히 네트웍 트래픽, 도커위에서 운용중인 어플리케이션의 상태, 처리량에 따라 동적으로 결정지어야하며, 서비스 추가를 위해선 수십초 내지는 수백초가 소요될 수 있으므로 임계치를 향해 갈 징조를 파악해서 스케일 아웃 해야하므로, 다양한 모니터링 도구와 연동하는 것이 필요하다.

그 중 하나인 프로메테우스를 비롯한 다양한 도구가 존재하고, 이런 도구를 통한 자동화를 하지 못한다면, 전통적인 배포 환경과 크게 다르지 않게 되므로, 쿠버네티스를 쓰는 이상 꼭 구축해서 오토 스케일 인/아웃 환경을 구성하길 권장한다.

여기에 더 좋았던 점은 MS의 적극적인 오픈 소스 지원 정책의 일환으로 VS2019 (VS2017에서도 가능했다)에서 도커 지원 메뉴를 클릭하기만해도, 참조 로컬 프로젝트, nuget 패키지등을 끌어와서 빌드해주는 Dockerfile까지 짜잔하고 완성된다는 점이다.

내 경우에는 코드 공유 및 중복 제거를 위해서, 프로젝트를 작게 쪼개서 참조를 관리하고 있으며, 로컬 프로젝트 참조를 해야 하는데, 이를 Dockerfile 작성하는게 꽤나 귀찮고, 실수할 소지가 많다. 심지어 프로젝트 구조가 종종 바뀌기 마련인데, Dockerfile 작성은 꽤나 집중력도 필요하고 테스트, 검증이 시간이 소모되는 단순작업이면서도 중요한 작업에 속하는 불편함을 가지고 있는데, 이를 해결해주는 것이 좋았다.

물론 도커 관련 글에서 언급한 것 처럼, 이미 Jenkins와 같은 CI 도구 등에서 사용해야 할 빌드 명령을 알고 있다면, Dockerfile을 작성할 순 있지만, 안정적으로 자동 생성되는 Dockerfile은 시간과 노력을 아껴주는 편의기능이어서 아주 맘에 들었다.

.NET CORE가 아니더라도, Docker 지원에 대한 CLI 도구들은 넘쳐나게 된 실정이며, CLI로 빌드 가능한 대다수 프로젝트들은, 종속성 관리가 단순하면 단순할수록 쉽게 Dockerfile 작성, Docker 이미지만으로 가동에 쉽게 성공할 수 있다.


물리 머신이라도, 가상 머신이라도 네트웍은 어렵디 어려운 부분이고, 비용 문제도 크게 엮인 부분이니 학습이 필요함은 불가피하다.

반면 쉽게 이득을 가져갈 핵심 포인트는 자원 활용에 있는데, 경량 컨테이너의 활용의 정점은 자원 활용의 극대화라고 할 수 있다.

빠르게 사용량이 비례하여 자원 할당을 함으로써, 서버 비용 감소/리소스 효율 증대를 노리는 것인데, VM보다 훨씬 가볍게 배포/가동/중지가 가능하다는 점은 현재 기준에선 매우 합리적이며, 효율적인 운용 환경을 구축해주는 (쿠버네티스를 비롯한)오케스트레이션 도구 덕분이라고 해도 무방하다.

AWS나, Azure, GCP 등의 메이저 클라우드 서비스들은 당연하게도 지원하고 있다.

비용 관련 비교는 아래 글이 유용했다.

Azure 기준 동일 사양으로 VM 대비 60% 정도의 가격으로 운용할 수 있는데다가, 클러스터 관리 도구 자체를 무료 제공해주므로, 쿠버네티스와 도커에 익숙해졌다면 굳이 더 비싼 VM을 고집할 필요가 없다.

도커 관련 글에서도 언급한대로, 경량 컨테이너다보니 VM을 유지하기 위한 코스트가 온전히 내 어플리케이션이 활용할 수 있는 효율마저 높아진다.

과연 아직도 VM을 고집해야 할까?


아직 고민중에 있다면 회사에 남는 머신 두어개 받아서 쿠버네티스를 세팅해보고 운용해보며 그 장점을 몸소 느끼고, QA 서버, 테스트 서버등부터 옮겨가며 그 장점을 누리는 개발자가 늘었으면 하는 바램에서 정리해보았다.

이 글에서는 개념적인 이야기나 원론적인 이야기를 좀 더 많이했는데, 기술적인 이야기는 좀 더 다음번에 좀 더 자세히 다뤄보도록 하겠다.

Docker 이야기

도커가 대중화된지 꽤 오래됐으나 배포 빈도/ 새 환경 구성, 오토 스케일링이 덜 필요한 환경에서 일할 수록 도커의 필요성이 상대적으로 우선 순위에서 밀리는 일이 비일비재했다. 나 역시 그랬고, 가볍게 사용해보거나 일부 서비스에서 도입했을 뿐이었다.

대 다수 개발자들은 아직도 서버를 새로 띄울 때 Dockerfile을 작성하고 Docker위에 올리기보다는 바이너리 빌드 후, 바이너리를 업로드 하고, 서비스 스크립트 작성하고, 서비스로 가동 시키는 데에 좀 더 익숙했고, 그렇게 가동 하게 되는 일이 많았다.

일부 서비스라도 도커로 올려보자는 설득에도 수 많은 관리자들이 반색을 내비치는 일이 비일 비재했다. VM이 거쳐온 길이 그랬듯 기반 환경이 달라지는 데에 대한 부담이 아주 커서일 것이라고 본다.

VM이 오랜 시간 개발자들에게 리얼 머신을 대체제로 자리잡았음에도, 그런 VM마저 서비스의 온전한 격리가 이루어지지 않는 경우가 비일비재해, 동일 호스트 머신에서의 서비스가 CPU 사용량이 급증하면 장애가 전파되는 일, 네트웍 격리가 제대로 이루어지지 않아 네트웍 트래픽을 과다 사용하는 서비스가 있을 경우 영향 받는일, 떨어지는 캐시 히트률로 인한 성능 저하 등 VM에 대한 우려도 있는 마당에, 도커 구동 환경, 도커 호스트 머신 이슈에 대한 막연한 불신도 어느정도 자리잡혀 있지 않나도 생각한다.

또한 안정성이 최우선이어야 하는 서버 프로그램, 서비스를 도커라는 (잘 모르기 때문에)불안한 기술 스택위에 올리고 싶지 않음도 한몫한다고 생각도 하고.

역사는 반복됐지만, 프론티어이자 Tech Freak 들은 도커를 시도했고, 도커로 서비스가 VM보다 유연한 어플리케이션 구동 환경을 유연하게 만들어준다는 것을 증명했다.


그나마 VM이 빠르게 시장에 안착한 이유는, 가상화라는 불안요소를 제외하면, 리얼 머신과 동일하게 운용 전략을 가져갈 수 있다는 점이다.

반면 Docker는 기본적인 용법으로 사용시 Docker 내부 데이터를 확인하기 위해 다른 명령어를 이용해 확인해야하고, 저장소를 다루는 방식, 포트 연결등 익혀야 될 명령어가 있다는 것 자체만으로도 (막상 써보면 그렇게 어렵지 않지만) 심리적 저항감과, (귀차니즘과 시간 소모가 아무래도 더 되기 떄문에)실천적 저항감을 같이 가져다 준다.

Docker로 어플리케이션 구동시 가장 큰 장점은 격리된 환경이다. 리얼 머신은 자원 효율, 수급 문제, 비용 문제등으로 한 머신에 여러개의 인스턴스 혹은 서비스를 올리는 선택이 어느정도 있을 수 밖에 없다.

(너무 슬프지만) VM의 경우에도 한 VM위에 여러개의 서비스를 올리는 경우가 빈번하다. 세팅 이슈나 자원 조절, 디스크 공유 등의 여러가지 이유에서 말이다.

VM의 경우에 Chef와 같은 환경 구성 도우미가 있다지만, 이미지를 조금만 잘못써도, 패키지 저장소, 버전, 패키지 업데이트 상황등이 조금만 달라져도 스크립트가 오류 나기 쉽상이며, 같은 스크립트 임에도 연관 패키지들의 업데이트만으로 not working이 되기 쉽상이다.

이에 대응되는 환경 구성 도우미 도구를 지원해주는 클라우드 서비스를 이용하거나, 이미지를 구워놓고 가동하는 방법도 방법인데, 여전히 업데이트 시의 실패에 대한 구멍이 남아있으므로 번거롭고, 제약이 많다.


도커는 애초에 이미지를 생성 할 때 연관 패키지들을 모두 포함 시킬 수 있으므로 격리된 환경 구성에서 훨씬 유연하다.

VM 이미지를 복사해서 가동까지 필요한 시간에 비해, 도커는 가동 속도도 우수한데가, 격리가 훨씬 더 우월하다. 애초에 서비스마다 내부 포트로만 동작하며, 선택적으로 외부 포트로 바인딩되므로 포트 이슈나 설정 이슈에서 혼란을 겪을 일이 훨씬 적어진다.

종종 잊혀지는 사실인데, 도커는 (VM에 비해)경량 컨테이너다. 구동까지 필요한 자원이 VM보다 훨씬 적게 소모된다. 이에 대한 자세한 내용은 아래 글을 참고 하면 좋겠다.

디스크는 기본적으로 영속성이 유지되지 않고 휘발성으로 동작하는데, 이에 맞게끔 운용해주는 것이 필요하다. (특히 여러 오케스트레이션 도구를 통해 스케일 인-아웃 설정시 로컬 디스크 데이터는 사라진다고 보는 것이 옳다)

이런 몇가지 특성에 대해 이해를 하고, 도커를 통한 운용에 적응이 되고 나면, 자연스레 오케스트레이션 도구에 관심이 갈 것이다.

도커의 장점인 격리된 환경 구성, 빠른 가동을 잘 활용하려면 당연히 오토 스케일 인/아웃, 빠른 서비스 배포를 해야 한다. 이를 위해서 Docker 스크립트 셋으로 구축하는 것보다 이미 잘 갖춰진 오케스트레이션 도구를 사용하는 것이 더 효율적이며, 충분히 활성화 되어 생태계가 구축되어있으니, 잘 활용만 하면 아주 편한 배포/운용 환경을 구축할 수 있게 된다.

그 중 가장 유명하고, 많이 이용되고 있는 오케스트레이션 도구인 쿠버네티스에 대한 감상은 다음 글에서 자세히 다뤄보도록 하겠다.

2019년 회고

들어가며

한해를 돌아보기 위해선 기록이 많았어야했는데, 작년 한해는 기록이 많지 못했다. 여러가지 이유가 있었지만, 결과적으로 아쉬운 부분이다.

내년에는 많 것을 극복해 좀 더 나은 한해를 만들고 싶다.

회고

건강

애초에 건강하지못했기도 하지만, 다년간 누적된 정신적, 육체적 피로가 폭발했다. 그로 인해 한해의 반 이상을, 정해진 업무를 쳐내는 수준에 급급했다.

특히 이 건강 문제로 인해 이직도 하게 됐고, 이직한 회사에서의 업무 강도가 다행히 높지 않아 많이 회복했음에도 여전히 썩 좋은 컨디션이라고 보기엔 어렵다.

운동량을 늘렸음에도 썩 효과가 좋지 못한 걸 보면, 건강 관리란 미리 미리, 꾸준히 해왔어야 되는건데 하는 아쉬움도 그만큼 커진다.

앞으로도 좀 더 건강에 신경써야 한다는 것을 느끼게 된 한해였다.

개발 토이

사실 개발 토이의 갯수는 줄었으나, 작업한 양 자체는 비슷했던거 같다. 여러가지 이유로, 오픈 소스로 개발하지 않았다보니 github에 올리지 않았을 뿐…

규모가 큰 프로젝트 하나를 진행하다보니, 막히는게 많아서 완성까지 오래 걸리는게 역시나 개발 토이로써는 아쉬움이 있는거 같다.

조금 더 작게, 빠르게 완성할 수 있는 프로젝트와 함께 진행해야 겠다는 생각이 커졌다.

게임 개발

건강상의 이유와, 빌드업 될 프로젝트로써 웹 기반의 안정적인 게임 서버 아키텍쳐 구성, 평소 존경하던 분과다시 일할 계기 등의 여러 이유로 다시 시작하게 됐다.

역시 게임 개발은 재밌으면서 어렵다고 매번 느낀다.

프로그래머, 아티스트, 디자이너(=기획자)가 너무 많은 방면에서 다른 사람들이다. 나는 종종 다른 인종이라는 표현을 하는데, 발상, 접근, 행동, 우선 순위, 해결 방식 모두가 너무나 다르다.

가끔 변종으로 다른 분야를 이해하는 인터메디에이터가 등장하곤 하지만, 이들이 특이하다고 보는게 맞을 지이다.

그렇다보니 갈등이 없을 수 없다. 어떻게 프로젝트가 진행되어야 하느냐가 직군별로 같은 가치관과 방식을 갖지 못하기에 일반적인 같은 직군 내에서의 혼란보다 더 큰 혼란과 논란을 가져오기 때문이다.

그럼에도 재밌다. 그리고 그렇게 만들어진 결과물도 재밌게 보람차다.

아무래도 난제를 이겨냈던, 빗겨갔던 간에 난제를 해쳐나간 보람 같은 것이 아닐까 싶기도하다.

나 자신부터가 열혈 게이머다보니, 다른 프로덕트보다 게임이란 프로덕트가 덕업일치 측면에서 조금 더 보람찬면도 있는 것 같다. (물론 업무로 내가 만들고 싶은 게임을 만드는 일은 한번도 벌어지지 않지만…아마 앞으로도….)

자기 반성

나는 매번 주장한다.

자신이 잘한 것보다, 잘못한 것을 떠올리고, 자신의 위치를 제대로 파악하고, 반성하고, 개선 할 수록 성장 할 수 있다고.

다만 너무 지치지 않게끔 잘한 것도 함께 떠올려, 동력으로 써야 한다고.

그런 측면에서 나는 작년 한해 건강 관리를 너무 못했다. 아무리 상반기에 여러가지 고강도 업무와 업무 스트레스로 힘들었다곤 해도, 그 이후에도 딱히 잘 관리하진 못했다. 하루 필수 운동 시간을 1시간 이상씩 가져갔음에도 나아지지 못했다면 좀 더 많은 시간을 할애하던, 방법을 바꾸던, 식이요법을 동원하던, 다방면으로 병원에서 검사를 받거나 했어야 했던 것 같다.

여하튼, 좋지 못한 건강 관리의 반작용으로 집중력이 부족했고, 이로 인해 생산성이 전체적으로 좋지 못했다.

내가 만약 작년 하반기에 업무량이 폭발했다면, 아마 지금쯤 더 크게 아파 큰 위기가 왔을거란 생각도 든다.

내가 할 수 있는 부분에서의 건강 관리도 미숙했던 것은 철저히 내 잘못이므로, 반드시 좀 더 노력해서 건강해져야 한다.

잘한 일

C# 그리고 .NET CORE로 웹 서버 기반의 아키텍쳐로 게임 서버를 구축한 것은 아무리 생각해도 잘한 것 같다.

때마침 .NET 3.0 Preview 버전이 진행중이어서 (지금은 정식 릴리즈 된지 3달여 지났다) 이에 맞춰 구축했던 모든 시스템이 예상한대로 높은 생산성으로 유지되고 있다. 유니티도 .NET Standard 2.0을 지원함에 따라 코드 공유도 너무 매끄럽게 이루어지고 있다는 점도 맘에 든다.

Partial, Extend, Async-await, LINQ 등 C# 자체의 생산성은 물론이며, .NET CORE의 안정화, ASP NET CORE나, EF CORE를 이용한 생산성 확보는 여러모로 큰 힘이 되고 있다.

재밌는 일

요새 흥미를 가지고 있는 것은 지금쯤은 말할 수 있는 익숙해진 C# 환경에서 프로덕트화 하는 다양한 작업 자체에 재미를 느끼고 있다.

개인적으로 다양한 프로그래밍 언어, 프레임워크, 플랫폼 등 넓은 경험을 선호하는 편이긴하지만, C#의 생산성 기반하에 평소 해보고 싶었던 다양한 프로덕트, 또는 효율적 개발을 해보는 것도 괜찮겠다는 생각마저 들만큼 C# 환경에 만족도가 큰 상태라고 할 수 있겠다.

게임

작년 한해 클리어한 게임들이다.

데빌 메이 크라이 5 메트로 엑소더스 젤다의 전설 - 꿈꾸는 섬 2019 디트로이트 비컴 휴먼 바이오 하자드 2 RE

아우터 월드, 기어스5 를 비롯해서 엔딩은 못봤지만 천천히 하는 게임들도 꽤 되는데, 의외로 습작과 병행해서 플레이할 때마다 느끼는게 참 많다.

이외에도 클래식 게임들 혹은 그런 감성으로 개발된 게임도 한해간 다시금 들여다보았는데, 네버윈터나이츠, 발더스 게이트 등의 CRPG, 디비니티 오리지널 씬 1 & 2 등을 플레이하며 내 취향이 올드하지만 저런 투머치 텍스트 게임에서 재미를 느낀다는 것은 부정할 수 없는 취향이구나 싶더라.

머드 게임이라거나, 2D 클래식 RPG, 넷핵 등의 올드 감성 게임들 마저 찾아가면서 했었는데, 그 과정에서 내가 만들어보고 싶다는 생각도 함께 했고, 이를 천천히 개발 토이로써 실천에 옮겨보고 있다.

2020년 목표

  • 올 한해의 목표는 무엇인가?
    1. 위에서 언급한 건강 회복 및 유지다. 의외로 어렵다 이거.
    2. 내가 몸 담고 있는 프로젝트가 잘 진행되어, 출시해서, 우리팀, 더 나아가 우리 회사를 먹여살리는 것! (쉽지 않겠지만..)
    3. 내가 여러가지 현실적인 이유로 해보지 못했던, 프로그래머 관점에서의 실천들을 좀 더 매끄럽게 잘 해내는 것이다. 이건 잘 해낼 수 있을거 같기도 하다.
    4. 개발 토이로써, 내가 만들어보고 싶은 게임들을 만들어보는 것이다. 여가 시간을 잘 조정하면 가능하리라 본다.

매년 목표를 세울 때 조급한 마음에 과도한 목표도 세워봤고, 잠 줄여가며 노력도 해봤고, 한가지에 미쳐도 봤고, 몸도 마음도 지쳐도 봤다.

너무 멀거나, 낮은 확률에 운에 기대며, 막연한 앞을 내다보기 보다는, 내 주변에, 나에게 주어진 환경 위주로 목표를 세웠다.

그럼에도 나 혼자 힘으로 불가능한 것들, 내가 노력한다 해도 쉽지 않은 것들도 포함되어 있지만 그럼에도 꼭 이루어진다면 너무나 뜻깊은 한해가 되지 않을까 싶다.

개발자의 성장

얼마 전 지인들과 점심 식사를 하면서, 근황 이야기를 나눴다.

그 과정에서 성장에 대한 우려에 대한 이야기가 나왔다.

나 역시 성장에 집착(?) 하는 편이다 보니, 주의 깊게 듣게 됐는데, 포인트는 다음과 같았다.

팀바팀, 케바케라지만, 서비스를 하는 많은 회사는 변화를 두려워한다.

변화는 리스크로 인식되기 쉽고, 실제로 그런 측면이 없진 않다.


잠깐의 node.js를 필두로한 웹서버 유행의 바람이 불었었지만, 다시금 백엔드는 익숙한 언어를 사용하고자 한다.

게임 업계는 여전히 C++ 서버를 다시 선호하기 시작했으며, 웹 업계는 자바다.

언어 자체에 변화는 인력 풀 문제라고 쳐도, 그안에서의 경험마저 새로운 것을 하기 어려운 것이 현실이다.

많은 개발자들이 규모 있는 회사를 선망하는 이유는, 페이 측면도 있겠지만, 성장하기 좋은 환경이라는 얘기를 자주 하는 것을 볼 수 있었다.

실제로 소프트웨어 중심의 회사를 선호해, 더 처우가 좋은 회사에 합격했음에도 IT 회사로 입사하는 케이스도 적지 않은 것도 사실이다.

하지만 그런 환경을 선망해서 고르고 골라 입사한 경우라 할 지라도 원하는 성장을 하기 보다는 정체되는 상황을 겪는 개발자가 많다.

농담반 진담반으로 개발자의 가성비는 3년차가 최고다라는 말이 있듯이, 경험이 어느정도 쌓이고, 머리도 잘 돌아가며, 성장의 즐거움과, 자신감이 넘쳐날 시기에 퍼포먼스를 내는 경우가 많기 때문일 것이다.

헌데 의외로 이 시기에 갈증을 느끼는 개발자가 적지 않다는 것을 알 수 있었다.

보호라는 명목하에, 불안 요소를 줄이기 위해서와 같은 안전주의적 접근으로 주니어 개발자에게 업무의 범위를 지나치게 한정 지어, 성장 속도에 제동이 걸리는 경우가 의외로 많았다.

아이러니하게도, 이런 상황은 중견 회사 이상에서 더 많이 발견할 수 있었다.


반면 작은 규모의 회사 일 수록 업무의 범위가 넓어지는 대신 자율이 보장되는 케이스도 많았다. 그만큼 성장할 기회도 많이 맞이할 수 있다. 고 강도의 노동이나 무지의 영역에서 헤메는 일도 함께 말이다.

그래서 보통 작은회사에서 큰 회사로 가고 싶은 이유가 안정성이나 처우인 경우도 많지만, 많이 배울 수 있을거 같아서라는 이유도 그에 못지 않게 많다.

하지만 대부분 규모가 클 수록 업무의 범위가 한정되고, 한정된 경험을 반복하는. 즉 깊게 파고드는 경험을 하는 경우가 많다.

헌데 오히려 주니어때 이런 깊게 파고드는 경험이나 자율이 보장되고 넓은 업무 범위의 경험 둘다 못하는 경우가 많고 이는 결국 성장에 대한 불만으로 이어지게 되더라.


과연 개발자가 배우기 가장 좋은 환경은 무엇일까?

위에서 변화는 리스크가 있다고 말했지만, 리스크 보다 더 큰 가치를 가지고 있다.

변화를 두려워하면 발전도 없으며, 코드를 덜 고친다고 문제가 덜 생기지 않는다.

실수를 두려워하지 않기

안정적으로 변화를 주는, 안정적 개선의 기술이, 경험이, 시야가 늘어야 한다고 나는 매번 주장한다.

가장 좋은 성장 환경은, 안정적인 변화를 이끌어내며, 자신이 해오던 경험보다 깊이가 깊던, 방향이 다르던 색다른 경험과 함께 그 완성도에 대한 가이드라인을 제시해줄 수 있는 리더, 동료와 함께 하는 것이라고 생각한다.

문제는 이런 환경을 찾기 쉽지 않고, 이런 환경이라고 주장하는 곳이라고 해도 실제 받아들이는 입장에서의 갭이 있을 수 있고, 다른 부분의 단점이 있을 수 있다는 점이다.

내가 자주 주장하는, 모두를 위한 천국은 없다고 생각한다.

세상 어느 곳에서도 장단이 있는 만큼, 자신이 어느 가치에 중점을 두고 있는지 잘 알고, 그것이 개발자로서의 성장이라면, 자신이 어떻게 해야 성장할 수 있는지, 또 어떻게 하면 가장 많은 성장을 할 수 있을지 고민해두어야 한다고 생각한다.

그런 고민에 조금이나마 도움이 될 수 있지 않을까 하는 생각에, 지인들에게 해주었던 조언 일부를 글로 남겨본다.