[2025/4/22]객체지향프로그래밍 SRP, OCP

오수호·2025년 4월 21일

TIL

목록 보기
9/60

객체지향프로그래밍(ObjectOrientedPrograming - OOP)

객체지향프로그래밍은 다음과 같은 5가지 원칙을 잘 지킨 프로그래밍이다.

1. 단일 책임 원칙 (Single Reposibility Principle)

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

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

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

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

객체지향 프로그래밍에서 위의 5가지 원칙은 프로그래밍의 다형성, 캡슐화, 상속, 추상화등을 지켜주며 이를 통해 프로그램의 관리, 유지.보수, 확장등을 용이하게 만들어 준다.

그렇다면, 각각의 원칙은 무엇을 의미할까??

단일 책임 원칙 SRP

  • 단일 책임 원칙은 하나의 클래스가 하나의 책임을 맡는다는 의미이다. 하나의 책임이란 하나의 객체의 대한 기능을 의미한다. 예를들어, 플레이어라는 클래스가 있다고 하면 이런 식의 코드가 짜여질 것이다.
class Player
{	
	int attackPower;
	int defensePower;
	.
    .
    .
    public void Attack()
    {
     	Console.WriteLine("플레이어가 공격했습니다!");
    }
    public void DisplayStats()
    {
    	Console.WriteLine("플레이어의 스텟을 확인합니다!");
    }
}

위의 코드는 플레이어가 가지는 특징, 행동들을 적절하게 정의하여 수행하고 있다는 생각이 든다. 여기서 만약 게임에 상점기능을 추가한다고 해보자. 플레이어가 상점을 여는 주체니까 플레이어 클래스에게 이 상점기능을 구현해야 한다고 생각한 어떤 사람이 플레이어에게 상점 기능을 구현한 것이다.

class Player
{	...
	...
	public void OpenMarket()
    {
    	Console.WriteLine("상점이 파는 물건 출력");
        // 상점이 파는 물건은 ItemDatabase에서 가져온다!
        if(playerKeyInput == Buy)
        {
        	BuyItem();
        }
        else if(playerKeyInput == Sell)
        {
        	SellItem();
        }
        
    }
    
    public void BuyItem()
    {
    	//물건을 고르면 플레이어의 소지금을 확인하고, 차감 후 아이템을 지급하는 로직
    }
    public void SellItem()
    {
    	//플레이어 소지품의 물건을 고르면 플레이어의 소지금을 늘리고, 아이템을 삭제하는 로직
    }
}

여기서 상점이 파는 물건을 플레이어가 선택하면 플레이어의 소지골드에서 이를 차감하고, 플레이어에게 아이템을 지급하면 된다. 이렇게 봤을 때, 기능적으로는 큰 문제가 없어보인다. 실제로 이와같이 구현을 해도 Market class를 따로 두는 것과 같은 기능을 충분히 구현할 수 있다. 하지만, Market class를 따로 두지 않을 때의 문제는 다음과 같은 상황에서 발생한다.

  1. Market의 기능 확장
  2. Market의 기능을 Player가 아닌 다른 클래스나 객체가 사용할 때
  3. Market내의 알고리즘을 수정해야할 때

위와 같은 모든 상황에서 코드를 수정할 때, Player에게 Market의 기능이 구현되어있으므로 Player내의 메서드의 코드들을 수정해야한다. 이 과정에서 Player의 값을 잘못수정하여 에러가 발생할 위험이 있고, Player class에 너무나 많은 코드가 포함되어 가독성이나 유지보수가 어려워진다.

개방폐쇄원칙 OCP

개방폐쇄원칙이란 수정에선 닫혀있게(Closed) 확장은 열려있게(Opend) 프로그래밍을 해야한다는 원칙이다. 이 개방폐쇄원칙을 지키기 위해서는 어떻게 해야할까?

  • 메서드가 하나의 기능을 갖는다.
  • 메서드가 추가적인 기능을 가져야할때는, 다른 함수를 호출하여 사용한다.
  • 메서드 오버라이드와 오버로딩을 통해 다형성을 지킨다.

위와같은 요소들이 어째서 개방폐쇄원칙을 지키는데 도움이 될까?

  1. 메서드가 하나의 기능을 갖는다.

메서드가 하나의 기능을 가지면, 어떤 필요한 기능이 있을 때 이를 가져오기 편해진다.
플레이어가 움직이는 기능과 플레이어가 공격하는 기능이 모두 같은 메서드에 있으면, 플레이어를 움직이는 것만 허용하고 싶은 상황에서는 이 메서드를 사용하려면 추가적인 수정이 필요해진다.

즉, 기능을 확장하는데 메서드가 하나의 기능만을 갖는 것이 유리하다.

  1. 메서드가 추가적인 기능을 가져야할때는, 다른 함수를 호출하여 사용한다.

위와같은 이유로, 하나의 메서드에 여러가지 기능이 필요하다면 다른 메서드를 호출해서 사용하면 된다. 메서드를 최대한 잘게 나누어서 관리하면, 가독성과 유지.보수가 편리해진다. 이는 확장성에 도움을 준다.

  1. 메서드 오버라이딩과 오버로딩을 통해 다형성을 지킨다.

다양한 매개변수에 따라 일관되지만 다른 유형의 출력을 가지는 메서드들을 오버로딩하거나 자식클래스들에 따라서 비슷한 메서드를 다르게 사용하고 싶은 경우 메서드 오버라이딩을 하면, 다형성을 지킬 수 있게 된다. 다형성이란 같은 형태지만 다른 역할을 한다는 것으로, Monster라는 부모클래스를 상속받아 만들어진 Slime이나 Orc같은 몬스터들은 Attack()메서드를 오버라이딩하여, 같은 Attack()을 호출해도 다른 기능을 한다. 이는 코드를 간결하게 만드는데 큰 도움이 된다.

시간관계상 객체지향프로그래밍의 남은 3가지 원칙은 다음에 시간이 난다면 작성해보도록 하겠다.

profile
게임개발자 취준생입니다

0개의 댓글