IT 이야기

[IT] 모든 소프트웨어 개발자가 알아야 할 10가지 프로그래밍 원칙

개발자 수니 2024. 1. 8. 18:01
728x90
반응형

📑 원문

10 Programming Principles Every Software Developer Should Know

원문을 읽고 한글로 정리한 글 입니다.

자세한 내용은 원문을 읽는 것을 추천드립니다 :)

 

코드 작성은 단순히 기능을 동작시키는 것뿐만이 아니라, 깨끗하고 효율적이며 유지보수가 가능한 코드를 작성하는 것입니다. 이를 위해 소프트웨어 개발자는 기본적인 프로그래밍 원칙에 익숙해져야 합니다.

 

1. DRY (Don’t’ Repeat Yourself) - 중복을 피하라

프로그램에서 코드를 중복하는 것을 피해야 하고 재사용 가능하고 모듈식인 코드를 작성해야 합니다.

코드를 중복하는 것은 유지보수 작업이 증가하며 버그가 발생할 확률이 높아지며 여러 위치에서 변경하는 것이 어려워집니다.

 

예를 들어, 여러 모양의 넓이를 계산하는 프로그램을 개발한다면
- 각 모양의 넓이를 계산하기 위해 별도의 함수를 작성하는 대신 (예: 정사각형의 넓이를 계산하는 함수, 삼각형의 넓이를 계산하는 함수 등),

DRY 원칙을 따라 필요한 매개변수를 가져와 넓이를 반환하는 단일 함수인 calculateArea 를 만들 수 있다.

2. KISS (Keep it Simple, Stupid) - 간단하게 유지하라

코드와 솔루션을 가능한 한 간단하게 유지하도록 노력해야 합니다.

코드를 단순화하면 이해하기 쉬워지며 유지보수 및 디버깅이 용이해져 오류나 문제의 가능성을 줄입니다.

 

예를 들어, 숫자 목록의 평균을 계산하는 프로그램 개발을 한다면
- 고급 수학적인 공식을 사용하거나, 불필요한 기능을 통합하여 논리를 복잡하게 만들지 않고,
간단하고 명확하게 숫자를 합한 다음 그 합을 총 개수로 나누는 이해하기 쉬운 몇 줄의 코드로 만들 수 있다.

 

3. YAGNI (You Aren’t Gonna Need It) - 필요하지 않을 것이다

코드에 불필요한 기능이나 기능을 추가하지 않도록 합니다. 다시 말해, 현재 필요하지 않거나 미래에 필요할 것으로 예상되지 않는 기능에 대해 코드를 작성하지 말아야 합니다.

이 원칙은 소프트웨어 개발에서의 단순성과 효율성을 촉진합니다. 또한 이 원칙은 깨끗하고 관리하기 쉬운 코드베이스를 유지하는 데 도움이 되며, 버그를 발견할 위험을 감소시킵니다.

4. Separation of Concerns (SoC) - Concerns의 분리

각 컴포넌트 또는 모듈이 특정한 관심사에 집중되어 있어야 합니다. 간단히 말해, 프로그램의 다른 부분이 관련 없는 작업과 얽히지 않고 한 가지 일에 중점을 둬야 한다는 것을 의미합니다.

이러한 접근은 코드의 유지보수성(애플리케이션 부분을 수정하거나 업데이트할 때 다른 부분에 영향을 미치지 않도록 만듭니다), 모듈성 및 재사용성을 향상시키는 데 도움이 됩니다. 또한 협업과 개발 효율성을 향상시킵니다.

 

예를 들어, 사용자가 회원가입하고 로그인할 수 있는 웹 애플리케이션을 개발한다면
- SoC 원칙을 따라 사용자 등록 기능과 로그인 기능을 분리할 것입니다. 이는 각 관심사를 독립적으로 처리하는 별도의 모듈이나 함수를 생성하는 것을 의미합니다. 이로써 회원가입을 담당하는 코드는 해당 작업에만 중점울 둔 채, 로그인을 담당하는 코드는 인증 및 권한 부여에 중점을 둘 수 있습니다.

5. Do The Simplest Thing That Could Possibly Work - 가능한 한 가장 간단한 방법으로 동작하도록 하라

이 원칙은 소프트웨어 개발에서 간결함의 중요성을 강조합니다. 해결책을 복잡하게 만드는 대신, 개발자는 즉각적인 요구 사항을 충족하는 가장 직관적이고 최소한의 접근 방식을 찾아야 합니다.

간단한 접근 방식은 과도한 복잡성이나 불필요한 계산 없이 원하는 결과를 달성합니다. 가장 간단한 해결책에 중점을 두는 것은 시간과 노력을 절약하는 뿐만 아니라, 결과적으로 장기적으로 이해하기 쉬우며 디버그 및 유지보수가 용이한 코드를 만들어냅니다.

6. Code For The Maintainer - 유지보수를 위해 코드를 작성하라

코드를 다른 개발자들이 쉽게 이해하고 수정하며 미래에 유지보수할 수 있도록 작성해야 합니다. 소프트웨어 개발자로서, 코드 작성 후에 코드를 작업할 다른 사람들을 고려하는 것이 중요합니다. 좋은 책은 독자를 염두에 두고 쓰여지듯이, 좋은 코드도 유지보수자를 염두에 두고 작성되어야 합니다.

이는 유지보수 및 업그레이드 중에 버그나 예상치 못한 동작이 발생할 가능성을 낮출 수 있습니다. 최종적으로, 유지보수자를 위해 코드를 작성하는 것은 소프트웨어가 안정적이며 시간이 지남에 따라 원활하게 발전할 수 있음을 보장합니다.

 

예를 들어,
- a, b 또는 x와 같은 암호화된 변수 이름 대신 코드의 목적과 기능을 명확히 설명하는 의미 있는 이름을 선택한다.
- 복잡하거나 애매한 부분을 설명하는 주석을 추가한다.
- 복잡한 작업을 작은 관리 가능한 함수로 분할한다.

7. Avoid Premature Optimization - 이른 최적화 피하기

성능 최적화에 집중하기 전에 깨끗하고 기능적인 코드 작성을 우선시해야 합니다. 이른 최적화란 꼭 필요하지 않은 코드에 지나치게 많은 시간과 노력을 들여 최적화하는 것을 말합니다.

코드가 기능적이며 요구사항을 충족하는 경우, 실제 사용 패턴이나 성능 측정에 기초하여 성능을 분석하고 필요한 경우 최적화할 수 있습니다. 이렇게 하면 시간과 노력이 현명하게 사용되며 개발 초기 단계에서 과도한 복잡성이 피해집니다. 이러한 방식으로 최적화를 진행하면 코드의 성능을 향상시키면서도 코드의 가독성과 유지보수성을 유지할 수 있습니다.

8. Boy Scout Rule - 코드를 남길 때보다 더 나은 상태로

이는 소프트웨어 개발자에게 코드베이스를 개선한 상태로 남겨야 한다는 코딩 원칙입니다. 작업할 때마다 작고 점진적인 변경을 통해 코드의 품질을 지속적으로 향상시키는 아이디어를 장려합니다. 마치 보이 스카우트가 캠프장을 떠날 때보다 깨끗하게 남기는 것처럼, 개발자는 변경 후에 코드베이스를 더 정리되고 가독성이 높아지며 유지보수가 더 쉬운 상태로 유지하도록 노력해야 합니다.

보이 스카우트 규칙을 적용하면 단순히 즉시 문제를 해결하는 것뿐만 아니라 미래에 해당 코드를 작업할 개발자들을 위해 코드베이스를 개선할 수 있습니다.

 

예를 들어, 프로젝트에서 작업 중에 이해하기 어려운 부분이나 더 효율적으로 작성될 수 잇는 코드 부분을 발견한다면
- 필요한 변경만 수행하고 넘어가지 않고, 코드를 개성하는 데 조금 더 시간을 투자한다
- 변수 이름을 더 명확하게 변경하거나, 복잡한 로직을 단순화 하거나, 코드를 리팩터링하여 모범 사례를 따르도록 하는 등의 작업

9. Law of Demeter - 오직 자신의 친구에게만 말하라

디미터의 법칙은 개발자가 코드를 더 모듈화하고 다른 구성 요소의 내부 세부 정보에 덜 의존하는 방식으로 작성할 수 있도록 도와주는 지침입니다. 이 원칙의 주요 아이디어는 소프트웨어 시스템의 다양한 부분 간의 결합도를 최소화하는 것입니다.

간단히 말하면, 이 원칙은 모듈이 다른 모듈의 내부 구조에 대한 제한된 지식만 가지고 있어야 하며, 오직 직접적인 이웃 모듈들과만 상호 작용해야 한다는 것을 제안합니다.

 

예를 들어, 다양한 속성과 동작을 갖춘 Person이라는 객체가 있다고 가정. Person의 주소 속성에 접근하려면
- person.address.street 처럼 직접 접근하는 대신, person 객체 자체에 제공하는 person.getStreet()와 같은 메서드를 사용한다.
- 이는 Person 객체가 자체 주소의 세부 정보를 캡슐화하고 다른 구성 요소들이 이와 상호 작용하기 위한 높은 수준의 인터페이스를 노출시킨다.

 

디미터의 법칙을 따르면 코드는 더 다재다능하고 유지보수가 쉬워집니다. 만약 Person 객체나 그 주소의 내부 구조가 변경된다면, 주소가 직접적으로 접근되는 코드 전체를 수정하는 대신 Person 객체 내의 메서드만 업데이트하면 됩니다. 이 원칙은 느슨한 결합을 촉진하고 의존성을 감소시키며 소프트웨어 시스템의 전체적인 모듈성을 향상시킵니다.

10. SOLID Principles 

SOLID 원칙은 소프트웨어 개발자가 유지보수 가능하고 유연한 코드를 작성하는 데 도움이 되는 다섯 가지 디자인 원칙입니다. 이러한 원칙은 모듈성, 재사용성, 그리고 간편한 테스트를 촉진하여 결국에는 품질 높은 소프트웨어를 만들 수 있게 도와줍니다. 초기에 약간의 추가 노력과 계획이 필요할 수 있지만 장기적인 이점으로 인해 이러한 원칙을 소프트웨어 개발 과정에서 따르는 것은 가치 있는 지침입니다

Single Responsibility Principle (SRP) - 단일 책임 원칙

단일 책임 원칙 원칙은 클래스 또는 모듈이 변경되어야 하는 이유가 하나뿐이어야 하며, 즉, 하나의 책임만 가져야 한다는 것을 명시합니다.

단일 목적에 중점을 둔 클래스는 이해하기 쉽고 테스트하기 쉽고 적응하기 쉽습니다.

 

예를 들어, EmailSender라는 클래스를 고려한다면, 이 클래스는 이메일을 보내는 책임을 가져야 하며, 보고서 생성이나 데이터 파싱과 같은 다른 관련 없는 작업을 처리하면 안 됩니다.

SRP를 준수함으로써 코드베이스를 더 유지보수 가능하고 모듈화된 상태로 유지할 수 있습니다.

Open/Closed Principle (OCP) - 개방/폐쇄 원칙

개방/폐쇄 원칙은 소프트웨어 엔터티(클래스, 모듈, 함수 등)는 확장을 위해 열려 있어야 하지만 수정을 위해 폐쇄되어야 한다는 원칙을 강조합니다. 이는 기존 코드를 수정하지 않고도 새로운 기능이나 동작을 추가할 수 있어야 한다는 것을 의미합니다. (상속이나 인터페이스를 사용)

 

예를 들어, 다양한 하위 클래스인 Rectangle과 Circle이 있는 Shape 클래스가 있다고 가정해 봅시다. 새로운 도형을 추가하려면 기존 Shape 클래스를 수정하지 않고 새로운 하위 클래스를 생성할 수 있습니다.

이 원칙은 코드의 재사용성을 촉진하고 이미 작동 중인 코드에 버그를 도입할 위험을 줄입니다.

Liskov Substitution Principle (LSP) - 리스코프 치환 원칙

리스코프 치환 원칙은 슈퍼클래스의 객체는 그 하위 클래스의 객체로 교체할 수 있어야 하며, 프로그램의 정확성에 영향을 미치지 않아야 한다는 원칙입니다. 간단히 말하면, 어떤 클래스의 인스턴스는 부모 클래스의 자리에 사용될 수 있어야 하며 예상치 못한 동작을 일으키지 않아야 합니다.

 

예를 들어, Animal이라는 기본 클래스가 있고 makeSound() 메서드가 있는 경우, Cat과 Dog 같은 하위 클래스는 Animal 클래스를 대체할 수 있어야 하며 여전히 예상된 동작을 생성하면서 오류나 불일치를 발생시키지 않아야 합니다.

Interface Segregation Principle (ISP) - 인터페이스 분리 원칙

인터페이스 분리 원칙은 클라이언트가 사용하지 않는 인터페이스에 의존하도록 강제되어서는 안 된다고 조언합니다. 이는 큰 단일 인터페이스 대신 클라이언트의 필요에 맞게 특정 인터페이스를 만들도록 장려합니다. 이로써 클래스는 자신에게 관련이 없는 메서드를 구현할 필요가 없어집니다.

 

예를 들어, print(), scan(), fax() 같은 메서드를 가진 Printer라는 인터페이스가 있다고 가정해 봅시다. 단일 인터페이스 대신 Printable, Scannable, Faxable과 같은 작은 인터페이스로 나누는 것이 더 좋습니다.

이렇게 하면 클래스는 필요한 인터페이스만 구현할 수 있어 코드베이스를 더 깔끔하고 집중된 상태로 유지할 수 있습니다.

Dependency Inversion Principle (DIP) - 의존성 역전 원칙

의존성 역전 원칙은 고수준 모듈이 저수준 모듈에 의존해서는 안 되며, 양쪽 모두 추상화에 의존해야 한다는 것을 제안합니다. 이는 느슨한 결합을 촉진하고 수정 및 테스트가 더 쉽게 이루어지도록 합니다. 실제로 이는 클래스가 구체적인 구현이 아니라 인터페이스나 추상 클래스에 의존하도록 하는 것을 의미합니다.

 

예를 들어, 파일에 로그를 기록해야 하는 Logger라는 클래스가 있다고 가정해 봅시다. 특정 파일 시스템 구현에 직접 의존하는 대신,  여러 구현을 가질 수 있는 FileSystem(LocalFileSystem, CloudFileSystem)과 같은 인터페이스에 의존하도록 해야 합니다. 이렇게 하면 Logger 클래스를 수정하지 않고 구현을 전환할 수 있습니다.

 

 

 

728x90
반응형