좋은 코드란 무엇인가
많은 프로그래머들이 좋은 코드에 대해 얘기한다. 최근 코딩 경험이 적은 한 주니어가 나에게 좋은 코드는 유지보수 비용을 낮춘다고 말했다. 반면 잘 훈련되고 경험 많은 프로그래머들로부터는 그런 확신에 찬 얘기를 듣기 어렵다. 어떤 코드가 좋은 코드인가? 요즘 유행하는 클린 코드가 좋은 코드인가? 모르겠다. ‘코드’가 뭔지는 안다. 그럼 ‘좋은’이 뭔지만 분명해지면 좋은 코드도 이해할 수 있을 것 같다.
내가 2년간 빠른 속도로 성장 중인 스타트업에 채용되었을 때 주된 책임 중 하나는 시스템 아키텍처 개선이었다. 회사의 기술팀은 기존 시스템의 설계는 변화하는 비즈니스 규모에 대응하기 어려우며, 확장가능한 아키텍처를 설계할 수 있는 인력이 필요하다고 판단했다. 이 판단이 옳다면 지금까지의 코드는 앞으로의 비즈니스에는 좋지 않은 것 같다.
프로토타이핑 코드
기존 코드는 분명 가독성이 낮고 중복이 많고 자주 오류를 발생시켰다. 대신 이 코드는 소수의 인원에 의해 빠르게 작성되어 중요한 비즈니스 타이밍에 배달되었다. 현명한 거래(trade-off)다. 난 그동안 새로운 비즈니스 실험을 하는 초기 스타트업에 타이밍이 얼마나 중요한지 배웠다. 이 타이밍이란 건 투자에도 결정적인 영향을 준다.
발생하는 프로그램 오류는 분명 나쁜 것이지만 비즈니스를 치명적으로 방해하는 수준은 아니었다. 설계는 앞서 얘기된 유지보수 비용을 높였지만 비즈니스 타이밍을 놓쳐 회사가 사라지면 유지보수성은 아무 가치 없다.
이 코드는 비즈니스를 성장시키고 매출을 만들고 투자를 이끌었다. 무엇보다 내가 회사에 채용되어 급여를 받을 수 있게 되었다. 이런 유형의 코드를 프로토타이핑 코드라고 하자.
지속가능 코드
프로토타이핑 코드의 성과를 나열했지만 언제나 바람직한 것은 아니다. 시스템 규모가 특정 수준에 이르면 코드의 낮은 가독성과 많은 중복, 잦은 오류는 전진에 필요한 비용을 증가시키고 심각한 경우 비즈니스를 멈추게 할 수도 있다.
그래서 채용된 후 나는 팀에 각종 설계 원칙을 소개하며 새 코드를 작성할 때 적용하도록 권유했다. 테스트 자동화를 이용해 오류의 재발 가능성을 줄이고 안심하고 코드 중복을 제거했다. 추가된 코드의 상당 부분은 충실히 테스트 되었기 때문에 불안감 없이 코드 파이프라인을 통해 하루에도 수차례 지속 배치되었다. 새로운 서비스는 기존 서비스와 연동되지만 항상 낮은 결합과 높은 응집을 염두하며 설계했다.
설계 목적은 분명했다. 코드 유지보수 비용을 일정 수준에서 관리하는 것이다. 이런 유형의 코드를 지속가능 코드라고 하자.
코드의 목적
프로토타이핑 코드와 지속가능 코드가 좋은지 아닌지는 절대적이지 않다. 위에서 얘기된 사례를 보면 조직의 성장 단계나 시스템 규모에 따라 달라지는 것 같다. 그런데 그 뿐일까? 난 이 회사에 입사한 후, 그러니까 회사가 수십억 투자를 유치하고 시스템도 커져가는 시점에, 많은 엔지니어링 원칙들을 지키며 할인정책 시스템을 만들었다.
하지만 시스템 통합 단계에서 근본적인 비즈니스 요구사항이 기술조직에 변질되어 전달된 것이 드러났다. 설계 뿌리부터 목적에서 어긋난 것이다. 나는 절대 좋은 코드를 썼다고 말할 수 없다. 프로젝트는 실패했다.
도구 숙련도
비즈니스 타이밍이 임박하면 지속가능한 코드는 좋지 않은가 하면 반드시 그런지도 의문이다. 최근 빠르게 런칭해야 하는 서비스 하나를 서버와 웹 클라이언트 모두 혼자 개발해야 했다. 서버는 내가 잘 아는 기술을 사용해 하루동안 프로토타이핑 코드를 작성했고 테스트는 코딩이 끝난 후 수동으로만 진행했다. 오류는 소수만 발견되어 빠르게 고쳤다.
반면 웹 프론트엔드는 기존 코드베이스 위에서 난 지금껏 공부해 본 적도 없는 React와 TypeScript를 써야 했다. 주어진 시간은 이틀이었는데 반나절 프로토타이핑 코드를 작성한 후 기한 내에 요구사항을 모두 만족시킬 수 있을지 불안감이 생겼다. 내가 도구에 익숙하지 않았기 때문이다.
그래서 난 그동안 쓴 코드를 모두 지우고 테스트 주도 개발로 다시 코딩하기 시작했다. 테스트 주도 개발을 한다는 건 단위 테스트를 쓴다는 뜻이고 단위 테스트는 정제된 모듈 설계의 도움을 크게 받는다. 결국 하루 반나절 동안 웹 클라이언트에 지속가능 코드와 80개 이상의 단위 테스트를 작성했고 내가 전달받은 모든 요구사항을 만족시켰다.
적절한 코드
좋은 코드는 맥락에 따라 달라진다. 그러니까 ‘좋은’이란 표현은 코드를 수식하기에 부족하다. 프로토타이핑에 적합한 코드, 유지보수하기 쉬운 코드, 전력효율이 높은 코드, 응답시간이 짧은 코드, 프레임 수를 유지하는 코드, GC를 덜 자극하는 코드 같은 건 있지만 그냥 좋은 코드란 존재하지 않는다.
누군가 프로토타이핑 코드는 엔지니어링 가치를 포기하고 비즈니스 가치를 선택한다고 판단할 지 모르겠다. 하지만 내 생각은 다르다. 내가 아는 모든 엔지니어링의 정의는 제한된 자원을 목적에 맞게 가장 효율적으로 사용하는 것이라고 말한다. 상황에 따라선 프로토타이핑 코드가 최선의 엔지니어링일 수 있다.
엔지니어는 다양한 도구를 준비해 적절한 곳에 쓸 줄 알아야 한다. 우린 문제를 해결하는 해커이지 진리를 탐구하는 과학자가 아니다.
Good code is dead. Long live contextual code.