CS/OOP

[OOP] SOLID 원칙 - 객체지향 설계 원칙 5가지

셰욘 2025. 1. 8. 21:49
728x90

출처 : https://didemeren.medium.com/solid-principles-in-practice-a9771a746f6c

 

 

객체지향 프로그래밍의 5가지 주요 원칙은 소프트웨어 설계의 품질을 높이고 유지보수성을 강화하기 위한 지침이다.

SRP, OCP, LSP, ISP, DIP 5가지가 있다.

 


단일 책임 원칙 (SRP, Single Responsibility Principle) 

하나의 클래스는 단 하나의 책임만 가져야 한다. (= 클래스)

 

  • 목적 : 클래스를 변경해야 하는 이유가 단 하나뿐이어야 한다.
  • 장점 : 클래스의 역할이 명확해지고 코드의 가독성과 유지보수성이 향상된다.

 

class Person {
	void cook();     //요리하기 - 요리사
	void plate();    //플레이팅 - 요리사
	void order();    //주문하기 - 손님
	void pickup();   //픽업하기 - 손님
	void eat();      //먹기    - 손님
}
class Chef {
	void cook();
}

class Customer {
	void order();
	void pickup();
	void eat();
}

 

 


개방-폐쇄 원칙 (OCP, Open/Closed Principle)

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

 

- 확장에는 열려있다 : 요구사항이 변경될 때, 새로운 동작을 추가하여 애플리케이션의 기능을 확장할 수 있다.

- 수정에는 닫혀있다 : 기존의 코드를 수정하지 않고 애플리케이션의 동작을 추가하거나 변경할 수 있다.

 

  • 목적 : 기존 코드를 수정하지 않고 새로운 기능을 추가할 수 있도록 설계
  • 장점 : 코드 변경으로 인한 버그를 최소화할 수 있다.

 

운전자는 자동차가 변경되어도 엑셀을 밟거나 브레이크를 밟는 것에 대한 영향을 받지 않는다

= 운전자가 수정에는 닫혀있다.

 

자동차는 Bus나 Truck 외에도 다른 자동차 종류로 클래스를 인터페이스를 통해서 확장할 수 있고, 운전자의 역할에는 영향을 끼치지 않는다.

= 확장에는 열려있다.

interface Car {
	void accel();
	void brake();
}

class Bus implements Car {
	void accel() { //속도 7 증가 };
	void brake() { //속도 5 감소 };
}

class Truck implements Car {
	void accel() { //속도 5 증가 };
	void brake() { //속도 3 감소 };
}

 

 


 

리스코프 치환 원칙 (LSP,  Liskov Substitution Principle)

상위 클래스 객체하위 클래스 객체로 대체할 수 있어야 한다.

 

  • 목적 : 다형성을 올바르게 구현하고 프로그램의 일관성을 유지
  • 장점 : 상속 관계에서 프로그램 동작이 깨지지 않도록 보장한다.

 

class Car {
	int speed;
	void drive() { 
		this.speed += 10;
	}
}

class Bus extends Car {
	int speed;
	int km;
	
	@Override 
	void drive() {
		// 부모 기능 그대로 수행
		this.speed += 10;
		
		// 하위 타입 기능 추가
		this.km += 1;
	}
}

 

 

 


인터페이스 분리 원칙 (ISP, Interface Segregation Principle)

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

 

  • 목적 : 인터페이스를 세분화하여 필요한 메소드만 제공
  • 장점 : 인터페이스를 작게 만들어서 구현 클래스가 불필요한 메소드를 갖지 않게 함

 

날 수 없는 동물도 있기 때문에, 동물 인터페이스를 사용하면 강아지는 날 수 없기 때문에 동물 인터페이스를 사용하지 못한다.

public interface Animal {
    void walk();
    void fly();
}

public class Dog implements Animal {
    public void walk() {
        // 강아지 걷기
    }

    public void fly() {
        // 강아지는 날 수 없음
    }
}

 

 

수정된 코드

// 걷기
public interface Walkable {
    void walk();
}

// 날기
public interface Flyable {
    void fly();
}

public class Dog implements Walkable {
    public void walk() {
        // 강아지 걷기
    }
}

public class Bird implements Walkable, Flyable {
    public void walk() {
        // 새 걷기
    }

    public void fly() {
        // 새 날기
    }
}

 

 


의존 역전 원칙 (DIP, Dependency Inversion Principle)

상위 클래스는 하위 클래스에 의존해서는 안 되며, 둘 다 추상화에 의존해야 한다.

=> 구현 클래스에 의존하지 말고, 인터페이스에 의존해라

 

  • 목적 : 구체 클래스가 아닌 추상화(인터페이스, 추상 클래스)에 의존하도록 설계
  • 장점 : 모듈 간 결합도를 낮추고 유연성을 증가시킨다.

출처 : https://minkwon4.tistory.com/281

 

왼쪽은 DIP가 적용되어 있지 않아서 자동차가 일반 타이어와 스노우 타이어에 직접적으로 의존 관계를 맺고 있다.

타이어를 인터페이스로 만들어 이 인터페이스를 통해 구현체인 일반 타이어, 스노우 타이어 등을 적절하게 가질 수 있어야 한다.

728x90