[파이썬] SOLID 원칙과 객체지향 프로그래밍

SOLID 원칙(SOLID principles)은 객체지향 프로그래밍(OOP)의 설계 원칙들을 나타내는 문구입니다. 이 원칙들은 소프트웨어를 더욱 견고하고 유지보수하기 쉽게 만들어줍니다. 이번 블로그 포스트에서는 SOLID 원칙에 대해 알아보고, Python에서 객체지향 프로그래밍을 할 때 SOLID 원칙을 어떻게 적용할 수 있는지 알아보겠습니다.

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

단일 책임 원칙은 한 클래스는 하나의 책임만을 가져야 한다는 원칙입니다. 만약 한 클래스가 여러 개의 책임을 가지고 있다면, 클래스를 변경해야 할 이유가 더 많아지게 됩니다. 이는 코드를 유지보수하기 어렵게 만들며, 기능의 수정에도 불필요한 영향을 미칠 수 있습니다.

Python에서는 단일 책임 원칙을 지키기 위해 클래스를 작게 나눠주는 것이 좋습니다. 예를 들어, 데이터베이스 연결과 데이터 조회를 담당하는 클래스와 데이터 처리를 담당하는 클래스를 분리하는 것이 좋은 예입니다.

class DatabaseConnector:
    def connect(self, host, port, username, password):
        pass

    def disconnect(self):
        pass

    def query(self, query):
        pass

class DataProcessor:
    def process(self, data):
        pass

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

개방-폐쇄 원칙은 기존의 코드를 수정하지 않고 확장할 수 있어야 한다는 원칙입니다. 이는 코드 재사용성과 유연성을 높여줍니다. 만약 새로운 기능을 추가해야 할 때, 기존의 코드를 수정하지 않고도 새로운 클래스나 모듈을 추가함으로써 확장할 수 있습니다.

Python에서는 상속(Inheritance), 다형성(Polymorphism), 인터페이스(Interface) 등을 이용하여 개방-폐쇄 원칙을 지킬 수 있습니다. 이를 통해 기존의 코드를 변경하지 않고도 새로운 동작을 추가할 수 있습니다.

class Shape:
    def area(self):
        pass

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius * self.radius

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

리스코프 치환 원칙은 자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 한다는 원칙입니다. 즉, 기존의 클래스를 상속받아 새로운 클래스를 만들었을 때, 기존의 클래스의 기능을 고려하지 않고 새로운 동작만을 추가하여 개발자에게 혼동을 주지 않아야 합니다.

Python에서는 상속 관계를 구성할 때, 자식 클래스는 최소한의 수정으로도 부모 클래스의 기능을 사용할 수 있도록 해야 합니다. 이를 통해 코드의 확장성과 유지보수성을 높일 수 있습니다.

class Animal:
    def move(self):
        pass

class Dog(Animal):
    def move(self):
        return "Walking"

class Bird(Animal):
    def move(self):
        return "Flying"

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

인터페이스 분리 원칙은 클라이언트가 자신이 사용하지 않는 메서드에 의존하도록 강요하지 말아야 한다는 원칙입니다. 즉, 필요한 기능만을 제공하는 인터페이스를 만들어야 합니다. 이는 클라이언트와 구현 사이의 결합도를 낮추고, 의존성을 줄이는데 도움을 줍니다.

Python에서는 필요한 기능에 맞게 인터페이스를 분리하여 사용해야 합니다. 이를 통해 필요하지 않은 메서드에 의존하지 않고, 코드의 유연성과 가독성을 높일 수 있습니다.

class Printer:
    def print(self, document):
        pass

class Scanner:
    def scan(self, document):
        pass

class FaxMachine:
    def fax(self, document):
        pass

class MultifunctionDevice(Printer, Scanner, FaxMachine):
    pass

D - 의존관계 역전 원칙 (Dependency Inversion Principle)

의존관계 역전 원칙은 추상화에 의존해야지 구체화에 의존해선 안된다는 원칙입니다. 즉, 인터페이스나 추상 클래스에 의존하는 것이 구체적인 클래스에 의존하는 것보다 더 유연하고 확장 가능한 코드를 작성할 수 있습니다.

Python에서는 인터페이스나 추상화된 클래스를 사용하여 의존성을 주입하는 방식으로 의존관계 역전 원칙을 적용할 수 있습니다. 이를 통해 객체 간의 결함도를 낮추고, 코드의 재사용성을 높일 수 있습니다.

from abc import ABC, abstractmethod

class Database(ABC):
    @abstractmethod
    def read(self):
        pass

class SQLDatabase(Database):
    def read(self):
        return "Reading data from SQL database"

class MongoDB(Database):
    def read(self):
        return "Reading data from MongoDB"

SOLID 원칙은 객체지향 프로그래밍에서 중요한 원칙들을 정의하고 있습니다. Python에서도 SOLID 원칙을 지키면서 코드를 작성하는 것은 좋은 소프트웨어의 품질과 유지보수성을 높이는 데 도움이 됩니다. SOLID 원칙에 대한 이해를 바탕으로 안정적이고 확장 가능한 Python 코드를 작성해보세요.

참고 자료