개발 플랫폼 엔지니어링에 대한 4가지 고민

개발자 경험, 오너십, 추상화, 공격과 수비, 2024.12.07

플렉스팀 웹 프론트엔드 플랫폼 팀에서 일 한지 3년 가까이 되간다.

연달은 업무의 시작과 끝에서 개발 플랫폼 업무를 보는 관점 같은 것들이 생겨 소개해보려고 한다. 당연히 내 경험 위주다. 나는 스타트업의 매우 한정된 스테이지와 팀 규모만을 경험했기 때문에 다른 팀 실정에 맞는 이야기는 아닐 수 있다. 내가 무언가 전제하거나, 개념화하여 설명하려는 것이 독자에게 잘 납득이 안 될 수도 있으리라 생각한다.

여기서 말하는 "개발 플랫폼 업무"에는 다음과 같은 것들이 포함된다.

  1. 여러개의 배포 단위에서 사용하는 공통 구현체 혹은 프레임워크의 변경 혹은 마이그레이션
  2. 동료 개발자들의 일하는 방식과 생산성에 영향을 끼치는 툴링, 스크립트의 변경 혹은 마이그레이션
  3. 애플리케이션의 배포, 운영, 코드 관리 방식 등의 개발 인프라단의 변경 혹은 마이그레이션

이제는 일을 시작하거나 진행하는 시점에서 다음과 같은 것들을 고민하게 되었다.

개발자 경험

내가 맡은 일에서 DX를 조금이라도 개선시키거나 악화를 막으려면 어떤 관점으로 접근해야 하는가?

내가 맡은 일들 사이에서 DX는 어느정도 우선순위를 가지는가?

좋은 개발자 경험(Developer eXperience)이 오픈소스에서는 흔한 덕목이다. 많은 오픈소스들이 DX를 무지 신경쓴다고 자처한다.

그러나 스타트업 개발팀의 개발 플랫폼에서 DX 우선순위 높이기 어렵다. 개발자들의 불편보다는 서비스 안정성, 릴리즈 일정, 매출이 더 중요하다. 개발자들의 제품 인도 리드타임에 크나큰 하자가 있는 것이 아니면 투자할 리소스가 생기지 않는다. 내가 CTO쯤 되더라도 비관적일 것이다. 동료들은 개발 과정의 어떤 비효율을 꽤 오랜 시간동안 감수한다. 나는 이것을 주로 정상적인 상황이라고 생각한다.

플랫폼에서는 당장 집중하지 않으면 제품이 선채로 죽어버릴 수 있는 태스크들이 DX보다 우선순위가 높다. 장애 리스크 해결이나 설계 변경에 따른 운영 이슈 줄이기와 같은 일이다. 예전에 썼던 글에서, 회사에서 개발하는 MFA 초기 프레임워크의 DX 수준은 "개발 못해 처먹겠다." 수준보다 조금 높게 유지하려고 했다고 이야기했던 적도 있다. 당장 조금이라도 삐끗하면 즉발로 장애날 수 있는 상황이라 그랬다.

동료 개발자들도 그냥 불편한 정도의 수준이라면 견디는 쪽을 택하게 되거나 불가피하게 그렇게 된다. 당장 스쿼드에서 붙여야 하는 기능만 산더미라서 이슈 제기해서 개선 약속을 받아내는 것이 몹시 피곤하다.

결국 플랫폼 업무 담당자는 DX 개선을 약속하고 리소스를 받아낼 것이 아니라, 공통 플랫폼에 변경을 가하는 순간순간마다 DX 악화를 막고 조금씩 계속 챙겨야 한다. 매우 어렵고 높은 역량을 필요로 한다. 나도 이것 때문에 진짜 고생을 많이 한다.

그럼에도 어떤 DX 악화는 제품이 앞으로 나아가는 과정에서 불가피하다는 것을 인정해야한다. 더 우선순위가 높은 태스크 때문에 DX가 악화될 여지가 생긴다면 동료 개발자들에게 그 이유를 투명하게 밝히고 추후 개선 계획도 짜고 공표한다.

오너십

함께보다는 혼자 결정하고 진행해 나가는 것이 일의 진행을 수월하게 만드는가?

내가 동료 개발자들이 납득할 수 있는 수준의 솔루션과 설득을 제공할 수 있는가?

공통 플랫폼 변경 업무 중에서는 물리적인 한계나 때문에 기여를 받아야만 할 수 있는 일이 있다. 반면 어떤 일은 빠른 시간 안에 작업자 한 명의 주도적인 결정과 실행을 통해 문제를 해결해야 한다.

예컨데 모든 제품의 기반 프레임워크를 바꾸는 작업이고 여기서 도메인과 결부된 코드에 대해 변경이 필요할 수 있다. 그런 경우에는 해당 도메인을 아는 사람을 참여시켜서 일을 진행시키는 것이 더 효율적이다. 스케줄이 관리될 수 있는 티켓과 작업 진행 현황판을 만들고 담당자 지정을 각 세부 목적조직에 요구한다.

이때 목적조직에서 해당 작업이 빠르게 수행될 수 있도록 하는 유인도 같이 설계한다. 이는 당근(해당 업무를 빨리 진행하면 제품에 미치는 좋은 영향과 개발자 경험의 향상)과 채찍(빨리 진행되지 않으면 생기는 불이익)을 포함한다.

반면에, 특정 공용 구현체의 구현과 이를 사용하는 모든 제품의 의존성과 참조를 바꾸는 일을 생각해보자. 작업하는 구현체의 사용처가 10,000곳이 넘더라도 내가 자동화 스크립트를 짜서 일괄로 모두 바꿔버리고, 제품에 문제가 없음을 내가 보장하면 된다. 이런 식으로 일을 진행시키는 것이 더 효율적이다.

어떤 일이 이 둘 중 어느 유형의 일인지 정확하게 알고 있어야 한다. 알지 못하거나 오인한다면 리소스를 무조건 낭비하게 된다. 혼자 할 수 있는 일을 다같이 하면 팀의 커뮤니케이션 비용 낭비고, 다같이 해야 하는 일을 혼자 하는 것은 내 리소스의 낭비다.

"혼자 할 수 있는 일" 에는 전제가 하나 있다. 내가 충분히 좋은 솔루션을 제안하지 못하면 할 수 없는 일이 된다. 동료 개발자들에게 "제품 전체에 영향을 미치는 아주 광범위한 변경을 진행할 건데, 이렇게 진행될 것이고, 여러분들은 신경 쓸 필요 없고 제품의 안정성은 내가 책임질 수 있다." 라는 말을 해야하기 때문이다. 높은 역량 뿐 아니라 이미 갖춰진 신뢰가 필요하다.

추상화

동료 개발자들이 공통 구현체에 대해 어디까지 알아야 하는가?

동료 개발자들이 플랫폼의 어떤 한 부분에 기여할 수 있는 것이 그렇지 않은 것보다 나은가?

공통 구현체를 만들 때 어떤 레이어까지 추상화해야 하는지가 가장 중요한 관심사다.

너무 열어 놓으면 플랫폼이 유즈케이스를 통제하기 힘들어진다. 각 개별 제품에서 의도하지 않는 방식으로 사용될 확률이 높아진다. 추후 특정 인터페이스를 사용하지 못하게 하기 매우 어려워진다. Headless UI나 조합형 방식으로 제공하는 React Component에 이런 문제가 종종 발견된다.

너무 닫아 놓으면 사용처에서 커스텀이 어려워 해당 구현체가 선택되지 않을 수 있다. 각 애플리케이션에서 적당히 알아서 구현하는 방식이 되어 기능 파편화의 가능성이 높아질 수 있다. 더불어 이렇게는 사용할 수 없는지에 대한 문의와 민원이 속출하게 될 것이다.

일반적인 경우 최대한 닫아 놓고 동료 개발자들의 의견을 종합하여 천천히 하나씩 추상화 레벨을 낮춰나가는 것을 선호한다. 하지만 어떤 구현체는 아예 동료 개발자들의 의견을 받지 않겠다고 선언하고 플랫폼 팀이 강력한 오너십을 가지고 관리해야 한다.

특정 공용 구현체는 특정한 방식으로 사용되고 확장되어야만 기본 전제를 지킬 수 있는 경우도 있기 때문이다. 대규모 애플리케이션일 경우 프레임워크의 코어에 가까운 구현체일수록 변경 자체를 최대한 발생시키지 않아야 안정성을 담보할 수 있는 경우도 존재한다.

공통 구현체에 대한 기여를 열어 놓을 것인지, 닫아 놓을 것인지는 또 다른 문제다. 기여를 받기 위해 최초 구현자가 여러가지 정보를 제공하고 이를 계속 업데이트 해야 하는데 이게 또 리소스가 드는 일이다. 해주시는 기여를 거부할 필요는 당연히 없으나, 대부분의 경우에 팀이 강력한 오너십을 발휘하는게 일을 더 잘 해나갈 수 있는 방법이었다.

내가 있었던 팀에서는 기여 모델이 제대로 돌아가는 걸 한번도 본적이 없다. 제품을 담당하는 개발자는 항상 너무 바빠서 기여할 시간이 없다. 그러나 그것은 몹시 정상이며 올바른 방향일 수 있다.

공격과 수비

개선을 하기 전에 현재도 발생하고 있는 부채나 잘못된 유스케이스를 더이상 발생하지 않게 해야 하는가?

혹은 빠르게, 적은 부분만 개선할 수 있어서 그런 조치가 필요없는가?

기술 부채 청산이나 플랫폼 성격의 개선을 위해 공통 구현체를 사용처에서 특정 방식으로 마이그레이션 해야하는 경우가 있다. 이런 성향의 작업은 가끔 플랫폼 담당자가 특정 구현체들을 올바른 유스케이스로 바꿔놓음과 동시에 다른 제품 한켠에서는 이미 잘못된 유스케이스가 계속 재생산된다.

개선과 망침이 동시에 일어나는 것이다. 이런 경우에는 마이그레이션을 시작하기 전에 잘못된 유스케이스를 린트룰이나 CI에서 깨지게 하는 등 시스템에서 검출하지 않으면 잘못된 유스케이스는 계속 재생산되고 마이그레이션의 완료 시점도 늦춰진다.

마이그레이션 작업을 직접 수행하는 것을 일종의 공격, 잘못된 유스케이스가 발생하지 않도록 개발 프로세스에서 잡는 것을 일종의 수비로 보면, 수비를 먼저 해놓고 공격을 해야 하는 경우가 있다. 놓치면 말그대로 깨진 독에 물 붓기가 된다.

그러나 마이그레이션이 필요한 유스케이스가 특정 부분에 국한되어 점진적으로 진행할 수 있거나, 모노레포 등의 환경에서 원자적 커밋으로 마이그레이션을 빠르고 간결히 진행할 수 있다면 수비할 시간에 공격부터 하는게 더 효율적인 일 진행 방식일 수 있다. 개선과 망침이 동시에 일어나는 상황을 예상해볼 때, 개선의 속도가 망침의 속도를 충분히 추월할 수 있다면 역시 수비는 필요없다.

수비 자체가 개발의 불편함을 야기할 수 있기 때문에 진행하려는 수비가 동료 개발자들에게 납득 가능한 수준인지 혹은 양해를 구하고 불편함을 감수해야만 하는 상황인지 평가해보는 것도 꼭 필요한 과정이다.

공수 전환에 있어 어떤 전략을 짜고 어떻게 접근하면 좋을지 많이 생각해봤는데, 일반론은 없다. 약간 경험이나 감의 영역도 있지만 대부분의 경우 정보를 많이 확보할수록 좋은 결정을 내릴 수 있었다. 마이그레이션 난이도에 대한 평가, 마이그레이션 진행할 사용처의 개수, 수비가 야기할 개발의 불편함에 대한 동료 개발자들의 생각 등이 유효한 정보다.

(끝)


Written by 김맥스