Architecture

좋은 코드를 위한 5가지 핵심 원칙: SOLID부터 리팩토링까지

백엔드 유성 2024. 1. 21. 16:15

좋은 코드를 작성하는 방법에 대해 많은 이론과 원칙이 있지만, 저는 특히 다음 5가지가 중요하다고 생각합니다.

 

1. SOLID

SOLID 원칙은 효과적인 소프트웨어 설계의 핵심입니다. 이 중에서도 '단일 책임 원칙(Single Responsibility Principle, SRP)'은 특히 중요합니다. SRP는 하나의 클래스가 단 하나의 책임을 가져야 한다고 말합니다. 

 

이 원칙을 지키면 클래스 간의 복잡도가 줄어들고, 코드의 가독성과 유지보수성이 향상됩니다. 단일 책임 원칙을 통해 각 클래스의 목적이 명확해지며, 이는 전체 시스템의 이해와 확장성에 긍정적인 영향을 미칩니다.

 

2. 읽기 쉬운 코드

좋은 코드인지 확인하는 방법은 아주 간단합니다.

좋은 코드의 핵심 요소 중 하나는 바로 '읽기 쉬움'입니다. 다른 도메인의 개발자에게 해당 코드를 읽게 해보고, 그들이 얼마나 빠르고 깊이 있게 이해하는지 확인하는 것입니다.

 

읽기 쉬운 코드를 작성하기 위해 다음과 같은 규칙을 따르는 것이 좋습니다

  • 축약어 사용 자제: 코드의 명확성을 위해 축약어 사용을 최소화합니다. 일부 표준화된 축약어는 코드 컨벤션에 따라 사용할 수 있지만, 가능한 한 풀어서 쓰는 것이 이해를 돕습니다.
  • 명시적인 필드와 메서드 이름: 필드와 메서드의 이름은 그 기능과 목적을 명확하게 전달해야 합니다. 필드는 주로 명사를, 메서드는 동사를 사용하는 것이 일반적입니다.
  • 주석의 최소화: 좋은 코드는 자체적으로 명확해야 하며, 주석은 필요한 경우(복잡한 알고리즘 등)에만 제한적으로 사용하는 것이 좋습니다. 과도한 주석은 코드의 유지보수를 복잡하게 만들 수 있습니다.

"이 필드가 무엇인지 모르겠다." 라는 피드백은 "필드 이름이 너무 길다." 라는 피드백보다 안좋은 피드백입니다.

짧고 명시적으로 필드이름을 작성하되 불가피할 경우 이름이 긴 필드라도 축약하지 않고 작성하는게 좋습니다.

 

만약, 필드 이름은 축약어로만 되있고 주석은 오래되서 현재 기능과 맞지도 않는 코드를 선임도 없이 신입 개발자 혼자서 맡게 된다면 추노를 해도 이해해줘야 하지 않을까..

 

이 외에도 여러 규칙들이 있으니 확인해보시기 바랍니다. 추후에 블로그에도 쓰도록 하겠습니다.

 

3. 오버엔지니어링을 피하자

'오버엔지니어링을 피하자'는 말은 '비효율적인 코드를 작성하자'는 의미가 아닙니다. 오히려, '심각하지 않은 비효율성은 일단 넘어가자'는 관점에서 접근하는 것이 중요합니다.

간단하고 명확한 최적화는 적용해야 하지만, 코드의 작은 비효율성에 대해 과도하게 집착하며 많은 시간을 소비하는 것은 지양해야 합니다. 대신, 코드의 가독성과 유지보수성에 더 많은 집중을 하는 것이 중요합니다.

오버엔지니어링'은 종종 개발자가 코드의 성능을 지나치게 강조하며, 실제로 필요하지 않은 복잡한 설계나 최적화를 적용하는 상황을 의미합니다. 이러한 접근은 프로젝트의 진행 속도를 늦추고, 코드의 복잡성을 불필요하게 증가시킬 수 있습니다. 

 

특히, 열정이 많은 신입 개발자들이 이런 문제에 빠지기 쉽습니다. 자신의 기술적 능력을 증명하고자 하는 열망 때문에, 신입 개발자들은 종종 불필요하게 복잡한 해결책을 채택할 수 있습니다.

 

이는 단기적으로는 기술적 만족감을 줄 수 있지만, 장기적으로는 프로젝트의 효율성을 떨어뜨리고, 코드의 복잡성을 증가시키는 결과를 낳을 수 있습니다.

(아이러니 하게도,, 이런 시행착오가 있어야 신입들이 성장한다고 생각합니다..)

 

중요한 것은 기술적인 복잡성을 추구하는 것이 아니라, 프로젝트의 목표와 팀의 요구에 맞는 효율적이고 실용적인 솔루션을 찾는 것입니다. 이와 관련된 더 자세한 내용은 '리팩토링' 섹션에서 추가로 설명드리겠습니다.

 

4. private 메서드를 테스트하지 않는다

테스트 코드를 작성하면서 "어떻게 private 메서드를 테스트할까?"라는 질문이 떠오른다면, 이는 현재의 코드 구조에 잠재적인 문제가 있을 수 있다는 중요한 신호일 수 있습니다.

우선, 단일 책임 원칙(Single Responsibility Principle)이 제대로 준수되었는지 검토하는 것이 좋습니다. 이 원칙은 각 클래스나 메서드가 단 하나의 책임만을 가지도록 하는 것을 목표로 합니다. 만약 private 메서드가 여러 책임을 지니고 있다면, 리팩토링을 통해 책임을 적절히 분배할 필요가 있습니다.

좋은 설계에서는 private 메서드보다는 public 인터페이스를 통한 테스트에 더 큰 중점을 두어야 합니다. 테스트의 핵심 대상은 public 메서드 또는 API입니다. 이들은 클래스의 기능을 외부로 제공하며, 이를 통해 클래스의 정확한 기능과 동작을 검증할 수 있습니다. 반면, private 메서드는 주로 public 메서드의 내부 구현을 돕는 역할을 하며, 직접적인 테스트 대상이 되지는 않습니다.

테스트 가능한 코드 작성은 중요한 설계 과제입니다. 테스트하기 쉬운 코드는 통상적으로 더 깨끗하고, 잘 구조화된 설계를 가지고 있습니다. 이는 테스트 주도 개발(TDD) 방식이 좋은 코드를 작성하는 데 효과적인 이유입니다. TDD는 코드 작성에 앞서 어떤 메서드가 public이 될지 결정하도록 유도하며, 이를 통해 보다 명확하고 직관적인 인터페이스 설계를 가능하게 합니다.

결론적으로, 테스트 코드 작성 과정에서 private 메서드의 테스트 필요성에 직면했다면, 이는 코드의 설계를 재검토하고 개선할 좋은 기회로 삼을 수 있습니다.

 

5. 리팩토링

소프트웨어 개발에서 리팩토링은 '처음부터 완벽하게'가 아닌 '지속적으로 개선해 나가는' 과정입니다. 개발자로서 완벽을 추구하는 것은 자연스러운 일이지만, 처음부터 모든 것을 완벽하게 하려고 노력하는 것은 현실적으로 어렵고 비효율적일 수 있습니다.

기본에 충실한 초기 코드 : 좋은 개발 관행은 기본적인 기능과 구조에 초점을 맞춘 코드를 먼저 작성하는 것입니다. 이 초기 단계에서는 요구사항을 충족시키는 것이 주요 목표입니다.

리팩토링을 통한 지속적 개선: 코드가 기본적인 기능을 수행하게 되면, 이후에 리팩토링 과정을 통해 코드의 품질을 점진적으로 향상시킵니다. 이 과정에서는 코드의 가독성, 효율성, 재사용성 등을 개선하며, 필요에 따라 새로운 기능을 추가하거나 기존 기능을 최적화합니다.

리팩토링의 중요성 : 리팩토링은 단순히 코드를 '더 좋게' 만드는 것 이상의 의미를 가집니다. 이는 프로젝트의 유지보수를 용이하게 하고, 장기적인 안정성을 제공합니다. 또한, 리팩토링은 새로운 요구사항이나 기술의 변화에 더 유연하게 대응할 수 있도록 합니다.

반복적인 리팩토링 과정 : 효과적인 리팩토링은 지속적이고 반복적인 과정입니다. 소프트웨어는 항상 발전하고 변화하며, 이에 따라 코드도 계속해서 개선되어야 합니다.

결론적으로, 리팩토링은 '완벽한 시작'보다는 '지속적인 개선'에 집중하는 것이 핵심입니다. 이 과정은 코드의 품질을 높이는데 중요합니다.