본문 바로가기
프로그래밍

SOLID 객체 지향 프로그래밍 설계 원칙

by 지나팩 2024. 4. 13.

SOLID는 객체 지향 프로그래밍과 설계에서 중요한 다섯 가지 원칙을 나타내는 약어입니다. 각 글자는 특정한 설계 원칙을 의미하며, 이 원칙들을 통해 더 유지보수가 쉽고, 확장 가능하며, 이해하기 쉬운 코드를 작성할 수 있도록 도와줍니다. 게임 개발에 있어서도 이 원칙들은 코드의 복잡성을 관리하고, 대규모 프로젝트에서 효율성을 높이는 데 기여할 수 있습니다.

 

예시는 c#

1. Single Responsibility Principle (SRP) 

단일 책임 원칙 한 클래스는 하나의 책임만 가져야 합니다. 즉, 클래스를 변경하는 이유는 오직 하나여야 합니다. 예를 들어, 게임 캐릭터의 이동 로직과 그래픽 표현을 분리하여 각각의 클래스로 관리하는 것이 이 원칙에 부합합니다.

 

예시: 게임 내의 인벤토리 시스템을 구현할 때, Inventory 클래스는 아이템을 추가하거나 제거하는 책임만을 가집니다. 사용자 인터페이스(UI) 표시나 네트워크 통신과 같은 다른 책임은 별도의 클래스(InventoryUI, NetworkManager)에서 관리합니다. 이렇게 함으로써 Inventory 클래스는 인벤토리 관리와 직접적인 관련이 없는 변경사항에 영향을 받지 않습니다.

 

2. Open/Closed Principle (OCP)

개방/폐쇄 원칙 소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장에는 열려 있어야 하지만 수정에는 닫혀 있어야 합니다. 즉, 기존의 코드를 변경하지 않고도 객체의 기능을 확장할 수 있어야 합니다. 예를 들어, 새로운 적 캐릭터나 능력을 게임에 추가할 때 기존 코드를 수정하지 않고도 쉽게 추가할 수 있어야 합니다.

 

예시: 새로운 적 유형을 추가하는 경우, 기존의 적 클래스를 수정하지 않고도 확장할 수 있어야 합니다. Enemy 클래스를 추상 기반 클래스로 설정하고, 각 적 유형(Zombie, Alien)은 Enemy를 상속받아 특정 행동을 구현합니다. 새 적 유형을 추가할 때는 단순히 Enemy 클래스를 상속받는 새 클래스를 만들면 됩니다.

3. Liskov Substitution Principle (LSP)

리스코프 치환 원칙 프로그램에서 부모 클래스의 인스턴스 대신 자식 클래스의 인스턴스를 사용할 수 있어야 합니다. 이 원칙은 상속을 사용할 때 자식 클래스가 부모 클래스의 행동을 정확히 모방하거나 확장할 수 있어야 함을 의미합니다. 예를 들어, 게임 내의 모든 적 캐릭터가 공통의 "적" 클래스로부터 파생되었다면, 모든 적은 "적" 클래스로 예상되는 행동을 수행할 수 있어야 합니다.

 

예시: 게임에서 Bird 클래스가 비행 기능을 가진 캐릭터를 위한 기본 클래스라고 가정합니다. Bird의 모든 자식 클래스(Eagle, Sparrow)는 fly() 메소드를 구현해야 하며, 이 메소드는 Bird 클래스에서 정의된 대로 정확히 작동해야 합니다. 만약 Penguin 클래스가 Bird를 상속받았지만 비행할 수 없다면, 이는 LSP를 위반하는 것입니다.

 

4. Interface Segregation Principle (ISP)

인터페이스 분리 원칙 클라이언트는 자신이 사용하지 않는 인터페이스를 구현하도록 강제되어서는 안 됩니다. 클라이언트가 필요로 하는 메서드만을 포함하는 여러 개의 구체적인 인터페이스가 더 낫습니다. 예를 들어, 비행 능력이 있는 캐릭터와 그렇지 않은 캐릭터를 위해 다른 인터페이스를 제공하여, 각 캐릭터가 필요한 기능만을 가질 수 있도록 합니다.

 

예시: 게임에 다양한 종류의 캐릭터가 있고 일부는 비행할 수 있는 능력이 있다면, 모든 캐릭터에 비행 메소드를 강제하는 대신, 비행 가능한 캐릭터만이 구현할 Flyable 인터페이스를 생성합니다. 이렇게 하면 비행 능력이 없는 캐릭터는 불필요한 메소드를 구현하지 않아도 됩니다.

5. Dependency Inversion Principle (DIP)

의존성 역전 원칙 고수준 모듈은 저수준 모듈에 의존해서는 안 되며, 둘 다 추상화에 의존해야 합니다. 즉, 세부 사항이 추상화에 의존해야 합니다. 예를 들어, 게임의 AI 로직이 특정 데이터 형식에 직접적으로 의존하기보다는, 일반적인 인터페이스를 통해 데이터에 접근하도록 설계하는 것이 좋습니다.

 

예시: 게임의 스코어링 시스템에서, ScoreManager 클래스는 점수 계산 로직을 수행하지만, 특정 데이터 저장 방식에 직접적으로 의존하지 않습니다. 대신, IDataStore 인터페이스를 통해 데이터 저장 방식과의 의존성을 역전시킵니다. 이를 통해 ScoreManager는 데이터 저장 방식이 변경되어도 영향을 받지 않으며, 다양한 데이터 저장 방식을 손쉽게 교체할 수 있습니다.

 

이 원칙들을 통해 게임 개발자는개발 과정에서 코드의 복잡성을 줄이고, 유지보수와 확장성을 개선할 수 있습니다. 이를 통해 게임의 개발 기간을 단축하고, 잠재적인 버그와 구조적 문제를 예방하여 게임의 품질을 향상시킬 수 있습니다. 각 원칙들은 프로그램의 설계와 구현 단계에서 중요한 지침으로 작용하여, 개발자들이 더 견고하고 효율적인 게임 소프트웨어를 만들도록 돕습니다. 게임 개발에서 SOLID 원칙을 적용하는 것은 큰 프로젝트에서 특히 중요하며, 코드의 질을 결정하는 중요한 요소가 될 수 있습니다. 다만 위 원칙이 절대적인 것은 아닙니다. 프로젝트나 상황에 따라 유연하게 코드를 작성하는 것이 더욱 중요하겠죠?

댓글