소프트웨어 개발자들은 ‘해서는 안 될 일’을 경고하는 ‘안티패턴(Antipattern)’이라는 개념을 만들어냈다. 중세 시대 지도의 ‘용이 있는 지역이니 조심’ 표시 같은 것이다. 코드를 구성할 때 적용해서는 안 되는 방법, 아키텍처로 적용해서는 안 되는 방법, 데이터베이스 스키마 디자인(고안)에 적용해서는 안 되는 방법 등이 이에 해당된다. 이런 안티패턴은 오늘날 여러 개발자들이 기능적 디자인 패턴으로 존중을 할 만큼 유용해졌다.
소프트웨어 프로젝트에도 고유의 ‘안티패턴’이 존재한다. 물론 프로젝트 운영과 팀 관리는 코드 개발과 같이 특정한 체계를 적용하기 어려울 수 있다. 또 일부 안티패턴은 서로의 ‘거울상’이다. 같은 것을 놓고, 수용하라기는 이야기와 피하라는 이야기가 공존할 수 있다. 그러나 실제 요구하는 것은 ‘중용’이다. 제 아무리 좋은 개념도 지나치면 팀 관리에 도움이 되지 않는다.
지금부터 소프트웨어 개발 관리와 관련된 11가지 안티패턴을 소개한다. 개발자들을 인도하거나 관리할 때 피해야 할 행동이나 행태로 생각하면 된다.
‘팀 플레이’라는 안티패턴
로버트 프로스트는 ‘좋은 울타리가 선한 이웃을 만든다’는 말을 즐겨 했다. 사람은 자신만의 공간이 필요하며, 이는 개발자도 마찬가지이다. 사람이 많으면 일이 쉬워질 것이라고 기대하면서, 팀에 더 많은 개발자를 추가 영입하려 들기 쉽다. 그러나 지나칠 경우, 개발자들이 서로 반목하면서 동일한 코드를 업데이트하려 경쟁하게 된다. 그러면 검토할 코드가 많아지고, 그 누구도 코드를 일일이 검토해 통합하기 원하지 않게 된다.
마이크로서비스 아키텍처는 여러 단점도 가지고 있지만, 개발자에 숨쉴 공간을 준다. 독립적으로 자신이 맡은 코드 작업을 할 수 있다. 코드를 커밋하고, 테스트를 생성하는 등 작업을 해 나갈 수 있다. 이런 단계들을 동조시키려 노력할 필요가 없다. 개발자들이 각자 자신의 공간에서 마음 편히 일을 하도록 만들면 큰 성과를 거둘 수 있다.
‘분할 관리’라는 안티패턴
개발자를 분리시키는 경우, 최종적으로 코드가 서로 함께 작동하도록 만들어야 할 때 문제가 발생할 수 있다. 한 API는 스트링(문자열)을 전달하는 데, 다른 API는 정수(Integers)를 원하는 식이다. 또는 한 팀은 열 데이터를, 다른 팀은 행 데이터를 기대한다. 화이트보드에 급하게 그린 스케치가 다양하게 해석될 수 있다. 그러면서도 각자의 결과물이 모든 테스트를 통과한다. 각 그룹이 각자의 비전을 사용해 자신의 코드에 대한 테스트를 만들기 때문이다.
해결책은 더 중앙에서 통제를 하고, 더 중앙에서 테스트를 하는 것이다. 일부 개발자를 지정, 부분들이 가능한 원활하게 함께 작동할 수 있도록 통합을 지속적으로 모니터링하는 일을 맡긴다. 부분들이 함께 작동하도록 만드는 일은 부분들을 구현하는 것만큼 힘든 일이다. 개발자들을 동일한 방향으로 계속 유도하는 것 자체가 하나의 ‘일’이다.
‘비전을 따르라’는 안티패턴
충분한 ‘돈’이 있다면 무언가 멋진 코드를 만들 개발자들을 채용할 수 있을 것이다. 모든 개발자가 전체 스택에 대한 전체 비전을 전달하는 창의적인 천재성이 폭발하는 것을 상상한다. 동시에 모든 개발자가 이런 상상 후, 단 몇 줄의 코드로 모든 기능을 구현하는 ‘초능력’에 대해 상상한다. 코드 편집기를 실행시키고 이런 신기루를 향해 달려간 적이 몇 번이나 되는가?
우리에게 방법론이 필요한 이유가 이것 때문이다. 멋진 신기루를 한쪽으로 치워 놓고, 상세한 계획을 구상하도록 만드는 도구를 의미한다. 멋진 상상의 다음 날에 문제점을 파악하기 시작할 수 있다. 계획 수립은 번거로운 일이다. 그러나 나중에 코드를 디버깅하는 것보다 빨리 할 수 있다. 때로는 다짜고짜 저지르기보다 그저 앉아 있는 게 나을 수 있다.
‘교과서대로’라는 안티패턴
모든 방법론에 ‘반드시 해야 할 일’, ‘반드시 피해야 할 일’을 규정하는 가이드라인, 컨퍼런스, 컨설턴트들이 존재한다. 이런 원칙, 규칙들은 종종 절대적인 권한을 부여받을 채로 강제된다.
문제는 이런 ‘법규’에 완벽하게 들어 맞는 것이 단 하나도 없다는 것이다. 스펙을 만드는 데 몇 달을 소비하고도, 모든 것이 거의 마무리되었을 때 새로운 각도나 문제를 발견하게 된다. 유연함과 민첩성을 유지하려 시도할 수 있지만, 계획 수립 단계에서 더 쉽게 문제를 해결할 수 있는 것을 예상하지 못하는 실수를 저지른다. 항상 깨닫는 순간이 있다.
유능한 관리자는 방법론을 선택한 후, 이 방법론이 실패할 가능성에 대비한다. 어느 누구도 항상 성공할 수는 없다. 대비가 중요하다.
‘프로세스 신뢰’라는 안티패턴
창의성을 방해할까 두려워 세부 사항을 계속 추적하지 않으면 악성 결과가 초래될 수 있다. 새 데이터베이스 설치에 얼마나 많은 시간이 소요되었을까? 팀이 SSO(Single Sign On) API를 다시 디자인하기로 약속했던 때는 언제일까? 마지막 코드 스프린트에 남겨진 ‘기술 부채를 리팩터(리라이팅)하기 위해 코드를 확인하는 데 투입된 사람은 몇 명인가?
책임자는 항상 지연을 초래하는 많은 장벽, 장애물, 문제에 직면하게 된다. 책임자의 도전과제는 효율적으로 일어나는 일을 모니터링하고, 현명한 결정을 내리기에 충분한 정도로 세부사항을 계속 추적하는 방법을 찾는 것이다. 소프트웨어 개발 매트릭스가 부정확할 수 있다. 그러나 지나치게 많은 기대를 하지 않으면, 누가 무슨 일을 하고 있는지 추적할 수 있도록 도와준다.
‘측정하지 않은 것은 관리할 수 없음’이라는 안티패턴
데이터의 중요성을 강조되면서 새롭게 회자되는 오래된 격언이다. 매트릭스가 나쁘다는 의미는 아니다. 모든 것을 포착할 정도는 되지 않는다는 의미이다. 오래 전, 관리자들은 개발자가 생성한 코드 줄의 수를 계산하려 시도했다. 그러자 개발자들은 주석이나 기능과 상관없는 부분을 추가해 아웃풋(결과물)을 배가시키는 방법을 생각해냈다.
최근 들어, 일부 관리자들은 업무에 추상적인 ‘점수’를 할당하고, 분기 또는 연도 별로 이러한 점수를 합산한다. 그러나 적합한 점수를 파악하는 것은 애초 문제를 해결하는 것만큼 어렵다. 정말 지독한 팀은 더 정확한 평가를 위해 서로를 경쟁시키기도 한다. 이는 팀웍이나 협업에 도움이 되지 않는다.
가장 큰 위험은 개발자들이 힘든 일이나 예측하기 어려운 일을 피하게 되는 것이다. 분기말, 연말에 충분한 점수를 얻게 되지 못할까 우려하는 행태가 번기는 것이다. 해결책은 이런 매트릭스를 지나치게 신뢰하지 않는 것이다. 점수를 추적 관리할 수는 있다. 그러나 이런 점수를 절대적인 척도로 간주해서는 안 된다.
‘어리석은 일관성은 편협한 사람들의 망상’이라는 안티패턴
개발자는 자유로울 필요가 있다. 개발자들에게 질문을 하면, 멋진 새 코드를 혁신적으로 만들어내는 자신의 능력을 억누르지 않았으면 좋겠다는 답이 종종 나올 것이다.
문제는 개발자를 방치하면 전혀 다른 방향으로 나갈 수 있다는 것이다. 일정한 기준이 필요한 이유가 여기에 있다. 코드에 어느 정도 일관성이 있을 때의 장점은 잘 알려져 있다. 패턴과 시각적인 리듬의 예측성이 높을 때, 코드를 더 쉽게 판독할 수 있다.
꽤 괜찮은 해결책이 자동으로 적용될 수도 있다. 규칙을 사용, 규정한 규칙에 부합하도록 모든 코드의 형식을 바꾸는 아톰(Atom) 같은 코드 편집기 등이 있다. (참조: ESLint.) 개발자는 이를 활용, 기준의 세부 사항을 걱정하지 않고도 충분히 깨끗한 결과물을 만들 수 있다.
‘기준이 구원자’라는 안티패턴
현재 소프트웨어 기준이 정말 많다. 신입 개발자들은 항상 더 많은 코딩 규칙을 만나게 된다. 예를 들어, 에어비엔비의 자바스크립트 코드 버전이 인기를 끌고 있다.
그러나 기준이 분노와 적의를 이끌어내고 개발자에게 싸울 또 다른 이유를 주는 경우도 있다. 에어비엔비를 예로 들면, 누군가 코드 사이의 스페이스 위치에 대한 규칙에 많은 시간을 투자했다. 스페이스를 중괄호(Curly brackets) 사이에 집어넣어야 한다(19.11), 꺾쇠 괄호 사이에 집어 넣는 것은 금지되어 있다(19.10).
주의 깊게 살피면, 개발자들이 이런 사소한 문제 때문에 시간을 낭비하고 있다는 것을 알 것이다. 이들은 기준이라는 말을 사용하는 것을 좋아한다. 기준이라는 말을 사용하지 않으면 큰 일이 일어날 것 같은 생각이 들게 만든다.
사실 이른바 기준이라 불리는 것들 가운데 상당수는 보기 좋게 만드는 역할을 할 뿐이다. 코드 실행 속도, 코드로 적절한 답을 얻는 것에는 차이를 만들지 못한다. 추가적인 여백(화이트 스페이스)는 컴파일러나 인터프리터에 의해 무시된다.
실행 코드의 품질에 거의 영향을 주지 않는 기준을 강제하는 것은 좋지 않다. 스페이스의 위치 같은 것은 사람을 위한 것이다. 사람들이 지나치게 많은 것을 주장하지 않도록 만드는 데 목적이 있다. 기준을 사용하고 싶다면, 적용하기 쉽고, 실제 유의미한 세부 사항만 신경 쓰도록 단순하게 만들어야 한다.
‘스택 단순화’라는 안티패턴
코드 기반에 원칙을 확보하는 가장 단순한 방법 중 하나는 단 하나의 언어만 허용하는 것이다. 그러면 모든 것이 일관되고, 모든 사람이 쉽게 이해를 할 수 있다. 해당 언어에 대한 스킬이 있는 사람이라면 누구나 채용할 수 있으며, 모든 사람이 함께 협업을 할 수 있다.
멋진 생각이다. 이를 적용하는 것이 합당하게 느껴진다. 문제는 이를 깨뜨리고 싶을 때이다. 매번 자신이 원하는 것을 할 수 있는 기능이 풍부한 오픈소스 코드, 새로운 라이브러리가 등장한다. 문제는 다른 언어로 작성되어 있다는 것이다.
엄격히 코드 기반의 ‘순정함’을 유지하면, 그 대가로 속도와 효율성을 잃게 된다. 사용자가 코드를 보고 읽을 일은 없다. 코드가 하는 일만 중요하게 생각할 뿐이다. 사용자를 만족시킬 수 있다면, 코드 기반의 이탈을 어느 정도 용인하는 것이 합리적이다. 도전과제는 절충의 가치가 있는 때를 파악하는 것이다.
‘개발자가 직접 도구를 선택’이라는 안티패턴
크리스는 새로운 함수형 언어를 좋아한다. 더 엄격하고, 더 ‘type-checked’ 방식일수록 더 좋다. 반면 패트는 머신 코드에 아주 가까운 ‘클로즈 투 더 메탈’ 코드를 사용하기 좋아한다. 그리고 밥은 최신 헤드라인에 있는 것이면 아무 것이나 상관이 없다.
잘 어울릴 수 있을까? 여러 언어의 코드를 플로우차트에서는 충분히 깨끗하게 보이는 마이크로서비스 형태로 묶을 수 있을지 모르겠다. 각자 좋아하는 언어를 대충 하나로 연결하는 것이다. 언어 선택에 ‘유연성’을 허락하면 새로운 프로젝트를 시작할 때에 인기를 얻을 수 있을 것이다.
그러나 나중에 문제가 발생한다. 코트린(Kotlin)을 좋아하는 개발자가 팀을 떠나고, PHP를 좋아하는 사람이 코드를 물려 받으면 이를 해독할 수가 없다. 적합한 스킬을 가진 사람들로 팀을 구성해 유지하는 경우에도, 자바스크립트 개발자들은 스위프트(Swift)로 작성된 코드를 확인할 때 고생을 하게 된다.
지나치게 개방적으로 모든 것을 수용해서는 안 된다.
‘성공의 열쇠는 동기 부여’라는 안티패턴
내 옆에 앉은 동료가 표준 라이브러리에 한 줄로 가능한 코드 대신, 2배나 많은 코드를 쓴 이유가 무엇일까? 그럴만한 이유가 있었다. 상사가 기트(Git) 레포지토리에 라이브러리 디렉토리에 추가되는 것에 대한 추가적인 검토 계층을 강요하는 덫을 놓았고, 검토를 담당한 사람은 변덕이 심하기로 유명한 사람이기 때문이었다.
몇 주 뒤, 나는 이 동료가 한 장의 티켓을 여러 티켓으로 분리해야 한다고 주장하는 것을 보았다. 봉급에서 보상을 받기 위해서이다. 이 동료는 풀 리퀘스트, 지원 티켓, 애자일 매트릭스를 ‘조종’하는 데 있어 ‘달인’이었다.
소프트웨어 프로젝트가 성공하기 위해 팀에 동기를 부여하는 것이 아주 중요할 수 있지만, 개발자들에게 진짜 동기를 부여하는 것은 수수께끼 같은 난제이다. 개발자들은 흔히 자신만의 생각을 갖고 있으며, 누구보다 도구를 잘 이해한다. 우리가 할 수 있는 최선은 ‘파트너십’에 대한 의식을 불어넣고, 큰 그림을 이해하도록 만드는 것이다. 그런 후, 이들이 추상적인 목표를 여러 수 많은 깨끗한, 테스트가 완료된, 버그가 거의 없는 코드로 바꿔 놓도록 바래야 한다. dl-ciokorea@foundryco.com