본 글은 책 소프트웨어 장인(산드로 만쿠소 저)을 읽고, 책 내용과 더불어 저의 생각과 제가 실무에서 가져갈 수 있는 것들을 저에게 가르쳐주기 위해 정리해놓은 글입니다. 아직 1.1년차 어린이 개발자이기 때문에 남을 가르치기 위해 작성한 것이 아님을 알려드립니다.
책 소프트웨어 장인은 소프트웨어 개발자로서 어떻게 하면 더 나은 프로그래머가 될 수 있을까?에 대한 물음에 힌트를 주는 책이다.
나는 야구를 좋아하는데, 최강야구에 출연하시는 김성근 감독님께서 돈 받으면 프로라고 하시는 걸 들었다. 개발자로서 취직하여 일하고 있는 우리 역시 프로 개발자이다. 근데 우리는 정말 개발자로서 프로페셔널할까?
개발자로서 프로페셔널하다는 것은 무엇일까? 책에서는 소프트웨어 장인 정신이 개발자로서의 프로페셔널리즘이라고 한다. 개발자가 코드를 잘 작성하는 것은 어찌보면 당연하다. 변호사가 변호를 못하고, 의사가 치료를 못하고, 디자이너가 디자인을 못하면 우리가 그들에게 비용을 지불하고 서비스를 받을 이유가 없다. 소프트웨어 개발자 역시 마찬가지다. 소프트웨어 개발자에게 개발을 비용을 일임하는 것은 변호사에게 의뢰하듯, 당연히 개발과 코딩을 잘 할 것이라고 믿는다는 것이다.
개발과 코딩을 나눠서 말했는데, 코딩과 개발이 동일한 것이라 보는 사람도 있을 것이다. 옛날에는 맞는 얘기였을 수도 있지만, 현재는 그렇지 않다. 물론 내가 옛날 소프트웨어 산업에 몸 담은 적은 없지만, 요즘 기업과 개발자가 추구하는 개발자 모델(?) 상(?)은 확실히 코딩만 잘하는 사람이 아니다.
AI의 발전으로 개발자들의 밥그릇이 위협받고 있다라고 하는데 이 부분은 조금 반대의 생각을 가지고 있다. 지금의 개발자는 단순 코더가 아니다. 예전에는 내향적이면서 남들과 단절되어 어려운 코드를 생성해내는 천재 개발자가 최고였다면 지금의 개발자는 테스트, 요구사항 분석, 비즈니스 이해, 커뮤니케이션, 고객 대응등을 적극적이며 외향적으로 해야하는 유기적인 직업이다.
전자의 개발자는 AI로 대체 가능하다고 생각한다. 어려운 코드를 작성하는 것은 AI가 빠르고 탄탄할 것이다. 하지만 후자의 개발자는 소프트 스킬이 중요하기 때문에 AI로 대체하기는 아직 멀었다. 그렇기 때문에 우리는 후자의 개발자가 되도록 노력해야한다. 물론 코딩 잘하는 것이 기본인 것은 변함없다. 우리는 후자의 개발자가 되면서, AI의 도움을 받아 좀 더 단단하고 좋은 소프트웨어를 고객에게 제공할 수 있어야 한다.
어떻게 하면 소프트웨어 장인이 될까?
소프트 웨어 장인은 개발 도구, 실행 관례 등을 마스터 해야한다. 자신이 성장하고, 프로젝트에 기여하고, 비즈니스를 이해하고, 팀원들의 성장을 돕기 위해서는 본인부터 마스터 해야한다고 한다. 이렇듯 장인이 되기 위해 매우 부단히 노력해야하겠지만, 장인 정신을 가지는 것 그 자체는 어렵지 않다. 그 방법은 바로 열정이다. 우리의 업무는 고객에게 가장 효율적인 방법으로 최고의 만족을 주는 것이다. "가장 효율적인 방법 + 최고의 만족"는 어떻게 달성할 수 있을까?
책에서는 이를 애자일 원칙으로 설명한다. 애자일 원칙은, 기민(Agile)하다는 뜻으로 소프트웨어 개발자로서 한 주름 하던 개발자들이 한 곳에 모여 선언한 원칙이다.
우리는 소프트웨어를 개발하고, 또 다른 사람의 개발을
도와주면서 소프트웨어 개발의 더 나은 방법들을 찾아가고
있다. 이 작업을 통해 우리는 다음을 가치 있게 여기게 되었다:
공정과 도구보다 개인과 상호작용을
포괄적인 문서보다 작동하는 소프트웨어를
계약 협상보다 고객과의 협력을
계획을 따르기보다 변화에 대응하기를
가치 있게 여긴다. 이 말은, 왼쪽에 있는 것들도 가치가 있지만,
우리는 오른쪽에 있는 것들에 더 높은 가치를 둔다는 것이다.
참조: 애자일 소프트웨어 개발 선언
우리 회사도 마찬가지이고 많은 회사들이 오른쪽에 있는 것보다 왼쪽에 있는 것들을 훨씬 중요하게 생각한다. 대량의 문서와 산출물이 계약으로 오가고, 개발보다는 영업이 중요하기 때문이다.
즉, 계약만 따내면 소프트웨어의 질이 어떻든 상관없고 프로젝트의 완성과 산출물(문서)이 중요하다는 뜻이다.
가장 효율적으로 최고의 만족을 제공하기
이런 환경에서 개발자들이 어떻게 효율적으로 만족을 줄 수 있을까? 그 방법은 위의 애자일 선언의 오른쪽 부분을 보면 된다.
빠르게 협력하고, 소통하며, 변화에 대응하고 문제없이 잘 작동하는 소프트웨어를 만들면 된다. 애자일 원칙에 따르면, 매우 짧은 주기로 작동하는 소프트웨어를 고객에서 제공한 뒤 피드백을 받는다. 보통 개발자와 고객은 똑같은 말을 다른 관점에서 하기 때문에 서로 생각하는 기능이 다를 때가 정말 많다. 때문에 열심히 개발했던 것을 눈물을 흘리며 롤백해야할 때도 있고, 도저히 뭘 어떻게 만들어달라는 건 지 이해하기 어려울 때도 많다. 짧은 주기로 최소한의 작동하는 소프트웨어를 제공함으로써 고객과 개발자의 생각을 맞추고 소통하여 결국에 고객이 딱 원하는 소프트웨어를 제공해줌으로써 만족을 줄 수 있다.
그러면 효율적인 것은 뭘까? 지금 트렌드로는 그게 TDD이다.
빠른 주기로 요구사항이 변경되거나 기능이 추가되면, 내가 작성한 코드도 빠르게 수정하고 기능을 추가해나가야 한다. 내가, 혹은 남이 작성한 코드를 수정하거나 확장해야하는데, 이 레거시 코드를 뭘 믿고 수정할 수 있을까? 특히, 그린필드 프로젝트가 아닌 누군가가 작성해놓은 레거시 코드에 새 기능을 추가하는 등의 작업을 해야하는 경우 매우 어렵다. 이 때, 자동화된 단위테스트가 작성되어 있지 않다면 코드를 분석하는 것도 일이지만, 분석을 했다 하더라도 해당 코드를 수정했을 때 예기치 못한 Side effect가 발생할 확률이 매우 크다. 또, 수정한 후 테스트를 해봐야하는데 소프트웨어를 실행한 후 모든 경우에 대해 수동으로 테스트를 해봐야한다. 테스트코드를 작성하는 시간과, 작성하지 않았을 때 발생하는 수동 테스트 시간 + 디버깅 시간 중 과연 무엇이 더 오래걸리고 비효율적일까?
레거시 코드에 단위 테스트를 작성하는 것은 매우 도전적인 일이다. 메서드, 클래스 간의 의존관계가 얽혀있고, 계층간의 분리도 잘 안되어있을 뿐더러 테스트하기 좋은 코드와 하기 어려운 외부 라이브러리, 외부 API 호출 등이 Service계층과 Controller 계층에 막 뒤섞여있을 수 있다. (지금 내가 맡은 프로젝트가 그렇다..🥲)
프로젝트 기한이 있기 때문에 방대한 프로젝트의 모든 로직에 테스트 코드를 작성하긴 어렵다. 수정사항이 있으면, 이미 작성되어 있는 로직에 대한 테스트 코드 혹은 수정되어야 하는 테스트코드를 먼저 작성하고, 리팩터링부터 한다. 수정 및 확장을 쉽게 받아들일 수 있는 상태로 만들어놔야 한다. 그리고 우리가 하고자 하는 수정 및 확장 해야한다.