컴퓨터 사이언스/소프트웨어 개발 방법론

[SOLID] 유지보수성과 확장성을 높이는 객체지향 설계 원칙

Dachaes 2025. 4. 26. 18:39
728x90
반응형
728x90

객체지향 설계 원칙(SOLID) 

객체지향 프로그래밍(OOP)은 단순히 클래스를 사용하는 것만으로 끝나지 않습니다. 진짜 중요한 것은 "좋은 객체지향 설계"를 통해 소프트웨어를 유지보수하기 쉽고, 확장 가능하게 만드는 것입니다. 이를 위해 꼭 알아야 할 설계 원칙이 바로 SOLID입니다.

이번 글에서는 SOLID가 무엇인지, 각 원칙을 하나하나 쉽고 깊게 살펴보겠습니다.

 


1.  SOLID란 무엇인가?

SOLID는 객체지향 프로그래밍에서 '좋은 설계'를 만들기 위해 제시된 5가지 핵심 원칙의 앞글자를 모은 약어입니다. 로버트 C. 마틴(Robert C. Martin), 일명 "아저씨(Uncle Bob)"가 제안했습니다.

  • S : Single Responsibility Principle (단일 책임 원칙)
  • O : Open/Closed Principle (개방-폐쇄 원칙)
  • L : Liskov Substitution Principle (리스코프 치환 원칙)
  • I : Interface Segregation Principle (인터페이스 분리 원칙)
  • D : Dependency Inversion Principle (의존 역전 원칙)

이 원칙들은 유연하고, 확장 가능하며, 유지보수하기 좋은 소프트웨어를 만들기 위한 기본 철학입니다.

 


2.  SOLID 5대 원칙 자세히 알아보기

a.  단일 책임 원칙 (SRP)

"클래스는 하나의 책임만 가져야 한다."

  • 하나의 클래스는 오직 하나의 기능만을 담당해야 합니다.
  • 여러 책임을 가진 클래스는 변경의 이유가 여러 개가 되어, 유지보수가 어려워집니다.

예시 코드 (Python)

# Bad Example: 여러 책임을 가진 클래스
class Report:
    def generate_report(self):
        pass
    def save_to_file(self):
        pass

# Good Example: 책임을 분리
class ReportGenerator:
    def generate(self):
        pass

class FileSaver:
    def save(self, report):
        pass

b.  개방-폐쇄 원칙 (OCP)

"확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 한다."

  • 새로운 기능 추가는 기존 코드를 수정하지 않고 확장으로 해결해야 합니다.
  • 변경이 잦으면 기존 기능이 깨질 위험이 높아집니다.

예시 코드 (Python)

# 확장 가능한 형태로 구성
class Shape:
    def area(self):
        pass

class Rectangle(Shape):
    def area(self):
        return self.width * self.height

class Circle(Shape):
    def area(self):
        return 3.14 * self.radius * self.radius
  • 새로운 도형이 추가되더라도 Shape 인터페이스만 지키면 기존 코드를 건드릴 필요가 없습니다.

c.  리스코프 치환 원칙 (LSP)

"서브타입은 언제나 기반 타입으로 교체할 수 있어야 한다."

  • 부모 클래스 객체를 사용하는 곳에 자식 클래스 객체를 대신 넣어도 프로그램이 정상 동작해야 합니다.

예시 코드 (Python)

class Bird:
    def fly(self):
        pass

class Sparrow(Bird):
    def fly(self):
        print("Sparrow flies!")

class Ostrich(Bird):
    def fly(self):
        raise Exception("Ostrich can't fly!")  # ❌ 위반 사례
  • 날지 못하는 Ostrich를 Bird로 다루면 문제가 발생합니다. 설계를 다시 해야 합니다.
  • 예: Flyable 인터페이스 분리

d.  인터페이스 분리 원칙 (ISP)

"클라이언트는 자신이 사용하지 않는 인터페이스에 의존하면 안 된다."

  • 하나의 거대한 인터페이스를 여러 개의 구체적인 인터페이스로 나누어야 합니다.

예시 코드 (Python)

# 나쁜 예
class Worker:
    def work(self):
        pass
    def eat(self):
        pass

# 좋은 예 - 인터페이스 분리
class Workable:
    def work(self):
        pass

class Eatable:
    def eat(self):
        pass
  • 로봇은 일만 하고 식사는 필요 없을 수도 있잖아요? 이렇게 필요한 것만 구현하게 합니다.

e.  의존 역전 원칙 (DIP)

"고수준 모듈은 저수준 모듈에 의존해서는 안 된다. 둘 다 추상화에 의존해야 한다."

  • 구체적 구현이 아닌 추상화(인터페이스, 추상 클래스 등)에 의존해야 합니다.

예시 코드 (Python)

# DIP 위반 예
class Keyboard:
    pass

class Computer:
    def __init__(self):
        self.keyboard = Keyboard()

# DIP 준수 예
class IKeyboard:
    def input(self):
        pass

class Keyboard(IKeyboard):
    def input(self):
        return "typing..."

class Computer:
    def __init__(self, keyboard: IKeyboard):
        self.keyboard = keyboard
  • Computer 는 이제 IKeyboard 라는 추상화에만 의존하여 유연성이 높아집니다.

 


3.  SOLID 원칙을 지키면 좋은 점

  • 코드 재사용성 증가
  • 유지보수 비용 감소
  • 버그 발생 가능성 감소
  • 팀 간 협업 시 명확한 규칙 제공
  • 대규모 시스템 확장 시 안정성 확보

 


4.  마무리

SOLID는 객체지향 프로그래밍을 넘어 현대 소프트웨어 설계의 기본 원칙으로 자리 잡았습니다. 각 원칙은 독립적으로도 중요하지만, 서로 조합될 때 훨씬 더 강력한 효과를 발휘합니다. 좋은 설계는 우연히 만들어지는 것이 아니라, SOLID 같은 원칙을 체계적으로 적용하려는 노력에서 나옵니다. 초반에는 약간 번거로울 수 있지만, 프로젝트 규모가 커질수록 SOLID의 중요성은 빛을 발합니다.

함께 보면 좋은 자료

외부 사이트 :

 


반응형

 

728x90
반응형