좋은 코드?
본론으로 들어가기 앞서서, 좋은 코드란 무엇일까요?
여러 가지 기준 중에서도 가장 중요한 것은 수정하기 쉬워야 한다는 것입니다. 코드는 필연적으로 계속해서 수정됩니다. 새로운 기능을 추가하든 버그를 잡든 코드는 수정되어야 하고, 수정되지 않는 코드는 죽은 코드가 됩니다.
코드가 이해하기 쉽고 안전해야 수정하기도 쉽습니다. 이해하기 어렵고 건드릴 때마다 버그가 생겨나는 코드는 당연히 수정하기 어렵겠죠. 따라서 간단명료하고, 의도를 명확하게 표현하면서 안전 장치도 되어있는 코드를 작성하기 위해 노력해야합니다.
말로는 쉬운데, 어떻게 해야 그렇게 좋은 코드를 작성할 수 있을까요? 그래서 준비했습니다.
1. 테스트 코드에 의지해라
테스트 코드는 소프트웨어 개발에 있어 가장 이로운 것이라고 해도 과언이 아닙니다. 테스트 코드는 존재만으로 좋은 코드와 버그 없는 안전한 세상을 불러옵니다. 따라서 우리는 테스트 코드를 종교처럼 믿고 의지해야합니다.
의도한 동작을 모두 테스트 코드로 표현하세요. 테스트 코드가 그 자체로 기능 명세서가 되어야합니다. 이런 과정이 쉽지는 않을겁니다. 하지만 이런 과정에서 자연스럽게 코드는 좋은 형태를 띄게 됩니다. 왜냐하면, 의도한 동작을 테스트 코드로 표현하려면 작성한 코드의 사용자가 되어야 하기 때문입니다. 내가 내 코드를 사용해봄으로써, 부족하거나 잘못된 부분을 쉽게 찾을 수 있습니다. 원래대로라면 다른 사람이나 미래의 자신이 “코드를 왜 이렇게 짠거야?”하고 발견했을 부분들을 미리 보완할 수 있는 것이죠.
또 이렇게 만들어놓은 테스트 코드들을 코드가 수정될 때마다 실행해봄으로써, 안전 점검이 가능해집니다. 코드를 수정했는데 테스트를 통과한다면 문제가 없는 것이고, 통과하지 못한다면 문제가 있다는 것이 보장되기 때문입니다. 이건 정말 엄청난 이점입니다. 코드를 수정했을 때 생겨날 문제, 즉 사이드 이펙트에 대한 걱정 없이 코드를 마음껏 수정할 수 있게 되기 때문입니다.
이러한 이점들 때문에 거의 모든 현대 프로그래밍 언어가 테스트 코드 프레임워크를 지원합니다. 사용해 본 적이 없다면 꼭 사용해보세요. 테스트 주도 개발(TDD)이나 테스트 방법론에 대한 글을 읽어보는 것도 좋습니다.
2. 사용하는 언어의 철학을 이해해라
혹시라도 사용하는 언어의 문법을 익히는 데서 그쳤다면, 한 발짝 더 나아갈 때입니다.
현대에는 정말 많은 프로그래밍 언어가 존재하고, 또 새로 생겨나고 있습니다. 그 많은 언어들이 각자 특유의 탄생배경과 철학을 가지고 있는데요. 공식 웹페이지나 서적에서 찾아보거나 ‘Python philosophy’ 같은 검색어로 검색해볼 수 있습니다.
자신이 사용하는 언어의 철학을 이해하고 코드를 작성해야 장점을 극대화 할 수 있고, 코드 전체를 관통하는 흐름이 통일되면서 이해하기 쉬운 코드가 됩니다. 파이썬을 사용하는 프로젝트에서 어떤 사람은 코드를 C언어처럼 작성하고, 어떤 사람은 자바처럼 작성한다면 혼란스러운 코드가 되겠죠.
3. 사전 설계를 최소화해라
협업을 위한 API 설계나 컴포넌트 분배가 꼭 필요한 경우가 아니라면, 코드를 작성하기 전의 설계는 하지 않는 것이 좋습니다. 하더라도, 테스트 코드를 위한 인터페이스 구상 정도로 최소화 하는 것이 좋습니다.
사전 설계를 통해 이점을 얻기보다 불필요한 코드나 레이어를 만드는 경우가 더 많기 때문입니다. 유명한 예로, 디자인 패턴을 학습한 직후에 오히려 장황하고 복잡한 코드를 작성하는 케이스가 있죠.
군더더기 없이 간단명료한 코드를 작성하려면, 우선 동작하는 코드 덩어리를 만들고 리팩토링하는 과정을 반복하는 것이 좋습니다. 이 과정에 익숙하지 않다면, 극단적으로 메인 함수에 모든 코드를 작성하면서 함수, 클래스, 상속 계층 등을 나누는 것으로 시작해 연습해보세요. 익숙해지면 몇 가지 단계를 생략하면서도 간단명료한 코드를 작성할 수 있게됩니다.
리팩토링이라는 용어를 처음 듣거나 익숙하지 않다면, 마틴 파울러의 “Refactoring”을 꼭 읽어보세요.
4. 섣부른 최적화, 하지 마라
맹목적인 어리석음(blind stupidity)을 비롯한 다른 어떤 이유보다도, 효율성이라는 이름으로 저질러지는 죄악이 더 많다(효율성을 반드시 성취하는 것도 아니면서 말이다)
윌리엄 울프(William A. Wulf)
작은 효율성(small efficiency)에 대해서는, 말하자면 97% 정도에 대해서는, 잊어버려라. 섣부른 최적화(premature optimization)는 모든 악의 근원이다.
도널드 커누스(Donald E. Knuth)
최적화를 할 때는 아래의 두 규칙을 따르라 규칙 1 : 하지마라 규칙 2 : (전문가들만 따를 것) 아직은 하지마라 – 완벽히 명료한, 최적화되지 않은 해답을 얻을 때 까지는.
M. A. 잭슨(M. A. Jackson)
빠르게 동작하지만 이해하기 어려운 코드를 작성하지 마세요. 이해하기 쉬운 코드를 작성하는 것이 먼저입니다. 최적화는 정말로 필요할 때까지 최대한 미루세요. 배열 대신 트리 구조를 사용하는 것이 더 빠를지라도, 코드를 복잡하게 만든다면 그냥 배열을 사용하세요. 우선 동작하는 간단한 코드를 만들고, 필요한 성능을 충족하는지 테스트해본 뒤에 최적화를 하더라도 늦지 않습니다. 어차피 이해하기 쉬운 코드는 수정하기도 쉬우니까요.
5. 멀티스레딩을 멀리해라
3번 조언의 연장선상에서, 멀티스레딩을 멀리하세요. 멀티스레딩은 모든 문제를 해결해주는 은탄환으로 보일 수도 있지만, 실상은 정반대로 모든 악의 근원에 가깝습니다. 따라서 꼭 필요한 경우가 아니라면 사용하지 않는 것이 좋습니다. 스레드가 하나에서 여러 개로 늘어나는 순간 코드의 복잡도가 올라가고, 여러 가지 위험에 노출되고, 테스트하기도 까다로워지기 때문입니다.
하지만 현실적으로는 멀티스레딩이 꼭 필요한 경우가 아주 많습니다. 따라서 멀티스레드 환경에서 일어날 수 있는 문제들과 해결 방법에 대해서 알아두는 것이 좋습니다. 함수형 언어들에 대해 공부해보는 것도 좋은 아이디어입니다.
FYI) 성능을 위해서 멀티스레딩을 사용하는 경우, 실제로 성능은 좋아지지 않으면서 다른 문제들만 불러오는 경우도 있습니다. 거짓 공유(False sharing) 문제가 그 예인데, 다른 블로그 글에서도 다루고 있어 설명은 생략합니다.
6. 겉모습도 예쁜게 좋다
코드의 아름답고 효율적인 구조도 중요하지만, 겉모습도 예쁜게 좋습니다. 당연한 것처럼 들리지만 꽤 중요한 부분입니다.
가독성을 위해서는 일관성있는 스타일을 유지하는 것이 좋습니다. 들여쓰기, 가로 길이, 함수당 줄 수, 변수, 함수, 클래스 등의 이름 규칙, 조건식 표시 등 사소해보이는 부분들도 일관성있게 작성해야 보기에도 좋고, 실제로 코드를 읽는데 큰 도움이 됩니다. 유명한 예로 구글에서는 여러 프로그래밍 언어의 스타일 가이드를 제시하고 있습니다.
7. 다른 사람들의 코드를 많이 읽어라
책을 읽는 것처럼, 코드도 많이 읽으면 읽을 수록 좋습니다. 코드는 작성할 때보다 읽을 때 배우는 것이 더 많기 때문입니다.
우리에게는 양질의 코드를 읽어볼 기회가 많습니다. 풍부한 오픈소스 프로젝트들 덕분인데요. 개발자라면 다들 아시는Github이나 아파치 재단 등 인터넷에서 여러가지 오픈소스 프로젝트들을 찾아볼 수 있습니다. 물론 오픈소스 프로젝트라고 해서 모두 좋은 코드는 아닐 수 있습니다. 그렇기 때문에 다양한 프로젝트의 코드를 읽어보는 것이 좋습니다. 그러다보면 자연스럽게 어떤 코드가 좋은 코드인지, 어떤 코드가 좋지 못한 코드인지 안목을 기를 수 있습니다.
마치며
개발자라면 항상 좋은 코드를 작성하기 위해 항상 노력하고 고민해야한다고 생각합니다. 위의 7가지 이외에도 좋은 코드를 위해 신경쓸 점은 수없이 많겠죠. 가장 중요한 것은 자만하지 않고 겸손하게 자신의 코드를 돌아보는 자세가 아닐까 싶습니다. 개발자들간의 소통과 코드리뷰 문화도 중요한 역할을 하고 있다고 보구요.
글의 내용에서 동의하거나 동의하지 못하는 부분이 있다면 댓글 남겨주시면 좋을 것 같습니다. 부족한 글 읽어주셔서 감사합니다! 😄
잘보고있습니다. 감사합니다.