좋은 코드를 만드는 이유, 좋은 코드를 만드는 방법

주싱·2023년 2월 28일
1

더 나은 코드

목록 보기
9/14
post-custom-banner

1. 코드를 만드는 이유

개발자가 코드를 작성하는 기본적인 이유는 어떤 기능을 구현한 제품을 만들기 위해서입니다. 그런데 종종 우리는 좋은 코드를 만들어야 한다는 말을 듣습니다. 기능을 똑같이 구현하는데 좋은 코드를 만들어야 하는 이유는 무엇일까요? 그리고 좋은 코드는 어떻게 만드는 걸까요? 컴퓨터 공학과를 나와서 현업에서 소프트웨어를 개발한지 몇 년의 시간이 흘렀습니다. 여러 경험과 배움이 있었고, 여러 사람들의 생각과 태도도 접했습니다. 문득 지금 이 순간에 “좋은 코드를 만드는 이유, 좋은 코드를 만드는 방법”에 대해 제 안에 있는 것들을 정리하고 싶은 생각이 들었습니다. 앞으로 흐트러지는 순간이 올 때 꺼내서 볼 수 있으면 좋을 것 같습니다. 그리고 훗날 보면 달라진 생각이 있을지 아니면 더 분명해 졌을지 기대도 됩니다.

2. 좋은 코드를 만드는 이유

개발자가 통제할 수 없는 것

코드는 개발자가 통제할 수 있는 영역과 통제 할 수 없는 영역으로 나눌 수 있습니다. 구현 기술, 코드 구조 등은 개발자가 선택하고 통제할 수 있습니다. 그러나 프로그램 외부에 있는 사용자의 요구, 정책의 변화 등은 통제하기 어렵습니다. 기술이나 코드의 구조는 개발팀에서 필요에 따라 바꿀 수도 있고, 시간이 없으면 나중에 하기로 부채로 남겨두기도 합니다. 그러나 사용자 요구나 정책의 변화는 그렇지 않습니다. 변화를 따라가지 못하면 프로그램 자체가 필요 없어 지기도 합니다. 예측하고 통제하기 어려운 이 변화는 개발하는 도중에, 심지어 개발을 시작하기도 전에 이러저리 바뀝니다. 그래서 코드는 변화에 빠르게 대응할 수 있어야 합니다.

좋은 코드의 최종 목표

문득 우리가 좋은 코드를 만들기 위해 노력하는 궁극적인 이유가 무엇인지 생각해 봅니다. 개인적으로 이 예측하고 통제하기 힘든 비지니스 영역의 빠른 변화에 코드 역시 빠르게 대응할 수 있는 기술적인 토대를 마련하기 위함이란 생각이 듭니다. 그래서 비지니스 목표를 이루고, 비지니스를 통해 사람들에게 유익한 도움을 주기 위함이라고 할 수 있겠습니다.

변화의 두 단계

잠시 새로운 비지니스 요구사항을 구현하기 위해 코드를 수정하는 단계에 대해 생각해 봅니다. 이 일은 크게 두 가지로 나눌 수 있습니다. 하나는 기존의 코드(우리 서비스 코드 또는 프레임워크 인터페이스 등)를 이해하는 일이고 다른 하나는 기존 코드 위에 새로운 코드를 추가하는 일입니다. 대게 새로운 코드를 추가하는 일에만 포커스를 맞추곤 하지만 기존 코드의 구조나 흐름을 제대로 이해하지 못하면 기존 코드와 함께 정상 동작하는 새 코드를 작성할 수 없습니다. 더러는 새로 추가한 코드가 기존 코드의 동작을 깨는 일이 발생하기도 합니다. 그래서 기존 코드를 읽고 이해하는 일 그리고 새 코드를 추가하는 일 모두 쉽고, 빠르게, 안정적으로 할 수 있도록 코드 베이스를 유지하는 것이 중요합니다. 그런면에서 우리가 앞서 말한 비지니스의 변화에 빠르게 대응할 수 있는 코드란 사실 읽고 이해하기 쉬운 코드이고, 또다른 면에서는 새로운 코드를 추가하기 좋은 코드라고 다시 표현할 수 있겠습니다.

3. 좋은 코드를 만드는 방법

다음에서 설명하는 좋은 코드를 만들기 위한 여러 방법들은 위에서 정리한 것 처럼 비지니스의 빠른 변화에 코드 역시 기민하게 대응하기 위해서 읽고 이해하기 쉬운 코드를 만들고, 또한 새로운 코드를 추가하기 쉽게 만드는 방법이라고 설명할 수 있습니다. 깊이 있게 내용을 다루지는 않고 간단한 포인트들만 정리해봅니다. 조금 더 자세한 내용이 필요한 분이 있다면 다음의 책들을 추천하고 싶습니다.

이름 짓기

코드는 컴퓨터에게 일을 시키는 단어와 문장들로 구성됩니다. 일을 시키는 사람(프로그래머)이 있고 일을 하는 대상(컴퓨터)이 있습니다. 여기서 일을 시키는 사람의 의도를 파악하는 것이 코드를 읽고 이해하는 행위입니다. 누군가 컴퓨터에게 시킨 일이 무엇인지 바르게 이해하기 위해서는 단어와 문장에 적절한 이름이 붙어 있어야 합니다. 실제로 “요리”를 하라는 명령을 하는데, “일”을 하라는 이름을 붙여둔다면 글의 앞뒤를 살핀 후에야 여기서의 “일”이 “요리” 였음을 알게 될 것입니다. 의도를 분명하게 표현하는 이름 짓기는 기본적으로 중요합니다.

제목 붙이기

한 단어 한 문장이 이해된다면 이제 좀 더 큰 문맥에서 어떤 일을 하고 있는지 이해할 수 있어야 합니다. 우리가 개요가 없는 요리책(우리가 접하는 많은 프로젝트 소스코드에는 개요 문서가 없습니다)에서 파스타 레시피를 찾는다고 상상해 보겠습니다. 우선 파스타 레시피가 어디에 있는지 책에서 찾기 시작하는데 책의 한 부분에 갑자기 버스를 타기 위한 상세한 방법이 쭉 나옵니다. 요리책에 갑자기 버스를 타는 방법이 왜 나오는 건지 의아한데 책을 모두 읽은 후에야 그 부분은 우리 동네에서 파스타 재료를 사기 위해 OO 마트에 가는 방법을 설명하는 글이었음을 이해하게 됩니다. 만약에 챕터 제목에 “재료 준비하기”라고 쓰고, “첫째. 마트 가기” 라는 제목을 달아두었다면 왜 그런 일을 하는지 이해하기 쉬웠을 것입니다. 코드도 비슷합니다. 어떤 클래스가 어떤 일을 하는지, 그 클래스 안에 함수는 어떤 일을 하는지 큰 제목을 문맥 안에서 잘 붙여두면 코드의 전체적인 의도와 흐름을 이해하기 쉽습니다.

관련 있는 것은 모으고

코드를 작성하며 좋은 함수 이름, 좋은 클래스 이름을 고민해 본 사람이라면 공감할 것입니다. 우리는 종종 함수가 무엇을 하는지, 클래스가 무엇을 하는지 설명하기 곤란한 경험을 합니다. 이런 경우 내 어휘력이 부족한가를 돌아볼 필요도 있지만 대게는 그보다 함수 또는 클래스가 하나의 주제로 모여질 수 없는 연관성이 적은 여러 일을 하고 있기 때문인 경우가 많습니다. 파스타 만들기를 설명하는 글을 쓰다가, 갑자기 오늘 아침 지하철에서 있었던 에피소드가 생각나 적기 시작한다면 글의 제목이 뭐가 되어야 할까요? “파스타를 만드는 방법과 함께 생각 난 오늘 아침 지하철 에피소드” 같은 희안하고 길다른 제목 말고는 붙일 이름이 없어질 것입니다. 우리는 그래서 하나의 주제로 모여질 수 있는 관련 있는 코드들은 하나의 함수, 클래스 안에 모아둘 필요가 있습니다. 이런 코드를 응집도가 높다고 표현합니다.

관련 없는 것은 분리한다

앞에서 설명한 응집도가 높은 코드는 자연스레 낮은 결합도를 가진 코드를 만듭니다. 겹합도라는 것은 응집도와는 반대되는 것으로 연관성이 적은 코드는 서로 영향을 받지 않도록 독립적으로 존재하게 하는 겁니다. 연관성이 적다는 것을 또 다른 표현으로 변경되는 이유가 다르다고 표현하기도 합니다. 변경의 이유가 같은 코드가 모여있으면 코드를 변경하기 쉽습니다. 변경해야 할 때 적은 부분만 수정하면 되니까 작업을 빠르게 할 수 있습니다. 변경의 이유가 다른 코드가 분리되어 있으니 내가 수정하려는 영역 이외의 코드는 영향을 받지 않는다고 믿고 보다 안정적으로 작업을 할 수 있습니다.

도메인의 변경에 대한 이해

앞에서 언급한 응집도와 결합도를 다시 정리한다면 함께 변경되는 코드는 모으고, 다르게 변경되는 코드는 분리한다고 표현 할 수 있습니다. 우리는 여기서 응집도와 결합도의 근간이 되는 변경이라는 것 자체에 대한 이해가 필요합니다. 무엇이 바뀌는 것이고 무엇은 쉽게 바뀌지 않는 것인지 이해해야 좋은 코드를 만들 수 있습니다. 그런데 변경은 두 영역에서 일어납니다. 하나는 프로그램의 도메인 영역에서 일어나고, 나머지 하나는 기술 영역에서 일어납니다. 프로그램의 도메인은 우리 프로그램의 목표가 되는 사용자가 일하는 분야, 일하는 방법 그리고 사용자의 불편과 요구 등과 관련된 것입니다. 도메인이 변경되면 프로그램은 필연적으로 함께 변경됩니다. 도메인에 대해 잘 이해하면 앞으로 무엇이 바뀔 수 있을지 힌트를 얻게 됩니다. 그리고 그것을 코드에 반영해서 어떤 것들은 모아 두고, 어떤 것들은 분리할 수 있습니다.

기술의 변경에 대한 이해

변화는 사실 사용자가 있기 때문에 일어납니다. (사용자가 없다면 버그도 변경 요구도 없습니다) 그런데 도메인 영역 외에 기술 영역에도 사용자가 있습니다. 바로 작성한 코드를 호출하고, 유지보수하며, 읽게 될 개발자 동료들과 나 자신이 이에 해당됩니다. 어떤 기술은 더 쉽고, 효율적이며, 안정적인 기술로 대체될 수 있습니다. 그래서 어떤 개발자들은 나중에 바꾸고 싶은 기술 영역이 있으면 그 영역을 가능하면 모아두고 다른 것과 분리해 두려고 노력합니다. 지금 바빠서 조금 부족하게 작성한 코드도 있다면 그 코드 영역도 추후에 리팩토링할 수 있도록 잘 분리해 둡니다. 완벽하지는 않아도 그러려고 노력합니다. 우리가 이처럼 기술 영역의 변경 가능성을 염두에 둔다면 이를 코드에 반영할 수 있습니다.

DRY (Don’t Repeat Yourself)

그리고 중복에 대한 내용입니다. 중복은 코드를 이해하는 것도, 변경하는 것도 어렵고 지루하게 만듭니다. 같은 내용이 여러번 반복해서 나오면 매번 그것을 이해하기 위해 코드를 읽어야 합니다. 그러나 하나의 공통 코드를 참조하면 한 번 이해한 코드의 문맥을 그대로 활용할 수 있습니다. 변경은 더 어렵습니다. 비슷한 하나의 코드 조각이 N번 중복 개발되었고 그 코드를 수정해야 한다고 생각해 봅시다. 하나의 공통 모듈이 있다면 한 군데를 수정하고 하나의 영향성을 검토하고 참조하는 모든 사용자 코드는 그 모듈을 믿고 사용하면 됩니다. 반면에 N번 반복되어 있다면 N번을 수정하고 N군데의 변경 영향성을 검토해야 합니다. 테스트에 대한 내용까지 함께 생각한다면 수정 작업의 양과 노력이 기하급수적으로 늘어나고 불안함 역시 커집니다.

주석달기

지금까지 좋은 코드를 만드는 방법을 설명했지만 코드만으로 부족한 것이 있습니다. 우리에게 좋은 주석을 달 책임이 분명히 있습니다. 기준은 분명합니다. 앞서 설명한 좋은 코드를 만드는 노력 없이 모든 것을 주석으로 설명하려는 노력은 피해야 합니다. 그러나 아무리 좋은 코드를 만들지라도 잘 정리된 사람의 언어 한 줄 보다는 이해하기 어렵습니다. 종종 코드보다 이해하기 어려운 핵심이 없는 주석을 달거나, 코드에 있는 내용을 그대로 기계적으로 기록한 주석 때문에 주석 자체가 불필요하다는 논지의 의견도 있지만 사람이 가장 잘 이해할 수 있는 것은 사람의 언어인 것은 확실합니다. 개인적인 원칙은 코드가 무엇을 하는지 코드 스스로 설명하게 하고, 주석에는 무엇에 대한 요약과 왜 이것을 하는지 설명하는 일이 필요한 것 같습니다.

기술적인 뒷받침

지금까지 소프트한 원리에 대한 내용을 설명했다면 이제 그것을 실제로 구현하는 기술에 대한 내용을 잠시 언급하려 합니다. 좋은 코드를 만들기 위해서는 기본적으로 프로그래밍 언어를 능숙하게 구사하는 능력이 필요합니다. 글을 잘 쓰는 원리를 잘 이해하고 있더라도 한글이든 영어든 언어를 잘 구사하지 못한다면 쓸모가 없습니다. 또한 여러 프레임워크들의 서비스를 잘 이해하고 활용할 수 있는 능력도 필요합니다. 좋은 프레임워크들은 함께 변경되는 같은 주제의 코드들을 잘 분리해서 독립적으로 구현해서 제공합니다. 프레임워크를 잘 활용하면 적은 비용으로 높은 응집성과 낮은 결합도를 얻을 수 있습니다. 뿐만 아니라 내가 중복해서 구현하지 않도록 나 대신 코드를 작성해 주고, 많은 경우 나보다 더 경험이 많은 개발자들이 만든 좋은 네이밍과 구조로 서비스가 제공됩니다. 공부할 것이 많다는 생각이 잠시 듭니다. 그러나 그리 거대한 산은 아닙니다. 조금씩 꾸준히 하다보면 모두 할 수 있다고 생각합니다.

4. 마치며

지금까지 제 안에 있는 좋은 코드를 만드는 이유, 좋은 코드를 만드는 방법에 대해 정리해 보았습니다. 이제 사용자를 만나고, 제품을 만들며 더 느껴볼 차례란 생각이 듭니다. 변화에 기민한 제품을 만들고 사람들에게 유익한 서비스를 제공하는 일을 많이 하고 싶습니다. 감사합니다.

profile
소프트웨어 엔지니어, 일상
post-custom-banner

0개의 댓글