유니티 디자인 패턴

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

Imperor 2025. 3. 7. 13:02

SOLID 원칙은 객체지향 설계에서 지켜줘야 할 5개의 소프트웨어 개발 원칙이다.

 

SOLID 설계 원칙은 OOP의 4가지 특징(추상화, 상속, 다형성, 캡슐화)와 더불어, 객체 지향 프로그래밍의 중요한 요소이며, 여러 디자인 패턴들이 SOLID 설계 원칙에 입각하여 만들어졌기 때문에, 표준화 작업부터 아키텍처 설계에 이르기까지 다양하게 적용되는 근간이 된다.

 

객체 지향 설계의 5가지 원칙은 다음과 같다.

1. SRP(Single Responsibility Principle): 단일 책임 원칙

2. OCP(Open Closed Principle): 개방 폐쇄 원칙

3. LSP(Liskov Substitution Principle): 리스코프 치환 원칙

4. ISP(Interface Segregation Principle): 인터페이스 분리 원칙

5. DIP(Dependency Inversion Principle): 의존성 역전 원칙

 

하나씩 자세히 살펴보자.


4. ISP(Interface Segregation Principle): 인터페이스 분리 원칙

 

ISP는 어떠한 클라이언트도 자신이 사용하지 않는 메서드에 강제로 종속될 수 없다고 명시한다.

 

인터페이스의 규모가 커지지 않도록 해야 한다.

클래스와 메서드의 길이를 짧게 유지하라는 SRP(단일 책임 원칙)과 같은 맥락으로 이해할 수 있다.

그러면 유연성을 최대로 향상하며, 집중도가 높고, 컴팩트한 인터페이스를 유지할 수 있다.

 

다양한 플레이어 유닛이 있는 전략 게임(스타크래프트 같은)을 만든다고 생각하자.

각 유닛에는 체력과 속도를 비롯한 다양한 스탯이 있다.

다음과 같이 모든 유닛이 유사한 기능을 구현하도록 보장하는 인터페이스를 만들자.

public interface IUnitStats
{
    public float Health { get; set; }
    public int Defense { get; set; }
    public void Die();
    public void TakeDamage();
    public void RestoreHealth();
    public float MoveSpeed { get; set; }
    public float Acceleration { get; set; }
    public void GoForward();
    public void Reverse();
    public void TurnLeft();
    public void TurnRight();
    public int Strength { get; set; }
    public int Dexterity { get; set; }
    public int Endurance { get; set; }
}

 

부술 수 있는 통이나 상자 등 파괴 가능한 오브젝트를 만든다고 가정하자.

비록 움직이지 않는 오브젝트이지만, 체력이라는 개념은 필요하다.

또한 상자나 통에는 게임 내의 다른 유닛에 부여된 능력 중 상당수는 부여되지 않는다.

 

파괴 가능한 오브젝트에 너무 많은 메서드를 부여하는 인터페이스 한 개를 만드는 대신, 여러 개의 작은 인터페이스로 분할하자.

그러면 인터페이스를 구현하는 클래스에서 필요한 요소만 선택해 사용할 것이다.

public interface IMovable
{
    public float MoveSpeed { get; set; }
    public float Acceleration { get; set; }
    public void GoForward();
    public void Reverse();
    public void TurnLeft();
    public void TurnRight();
}
public interface IDamageable
{
    public float Health { get; set; }
    public int Defense { get; set; }
    public void Die();
    public void TakeDamage();
    public void RestoreHealth();
}
public interface IUnitStats
{
    public int Strength { get; set; }
    public int Dexterity { get; set; }
    public int Endurance { get; set; }
}

 

폭발하는 통에 IExplodable 인터페이스를 추가할 수도 있다.

public interface IExplodable
{
    public float Mass { get; set; }
    public float ExplosiveForce { get; set; }
    public float FuseDelay { get; set; }
    public void Explode();
}

 

 

클래스 하나가 둘 이상의 인터페이스를 구현할 수 있으므로 IDamagable, IMovable, IUnitStats에서 적 유닛 코드를 생성할 수 있다.

 

폭발하는 통은 다른 인터페이스의 불필요한 오버헤드 없이 IDamagable과 IExplodable을 사용할 수 있다.

public class ExplodingBarrel : MonoBehaviour, IDamageable, IExplodable
{
    //...
}
public class EnemyUnit : MonoBehaviour, IDamageable, IMovable,
IUnitStats
{
    //...
}

 

LSP(리스코프 치환)의 예시와 마찬가지로 여기에서도 상속보다 합성을 우선시한다.

인터페이스 분리 원칙은 시스템을 분리하고 간편하게 수정 및 재배포하는데 도움이 된다.

 

 

 

출처

https://unity.com/kr/resources/level-up-your-code-with-game-programming-patterns

 

게임 프로그래밍 패턴으로 코딩 스킬 업그레이드

새로운 전자책에서는 잘 알려진 디자인 패턴과 함께 실제 Unity 프로젝트에서 활용할 수 있는 실용적인 예제를 소개합니다.

unity.com