코딩스토리

좋은 객체지향 설계의 5가지 원칙 - SOLID 본문

Spring/Spring 공부

좋은 객체지향 설계의 5가지 원칙 - SOLID

kimtaehyun98 2021. 7. 8. 15:46

SOLID란?

 

"클린 코더"로 유명한 로버트 마틴이 좋은 객체지향 설계를 하기 위한 5가지의 원칙을 제시한 것이다.

SOLID는 각각의 원칙의 앞글자를 따서 만들어졌다.

 

SOLID Principles

 

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

 

설명

 

한 클래스하나의 책임만 가져야 한다는 원칙이다.

하나의 클래스는 자신이 담당하고 있는 기능을 수행하는데 집중해야 한다. 

따라서 여러 책임을 가지고 있는 클래스가 있다면 각각 개별 클래스로 분할한다.

또는 중복되는 책임을 가지고 있다면 이를 부모 클래스(Super Class)로 정의하여 위임한다.

이를 통해 변경이 있을 때 파급효과가 적어진다(연쇄작용에서 자유롭다).

 

 

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

 

설명

 

소프트웨어는 확장에는 열려있으나 변경에는 닫혀있어야 한다.

 

예를 들어보자.

한 사람이 음식을 먹는다고 생각해보자. 

만약 음식 중 "A"란 음식은 반드시 포크로만 먹어야 하고 "B"란 음식은 반드시 젓가락으로만 먹어야 한다고 가정해보자.

그럼 이 사람은 A를 먹기 위해 포크를 사용하다가 B를 먹기 위해 젓가락을 사서 젓가락을 사용해야 할 것이다.

이는 사람, 즉 Client가 포크 사용에서 젓가락 사용으로 변경된 예시이다.

 

OCP는 포카락과 같다.

이 사람이 어떤 음식을 먹든(확장), 젓가락과 포크가 있든 없든, 포카락 하나만으로(변경) 해결 가능하다.

 

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

 

설명

 

자식 클래스는 프로그램에 정확성을 깨트리지 않으며 부모 클래스를 대체할 수 있어야 한다. 

 

쉽게 말하면 자식 클래스는 부모 클래스에서 확장된 형태여야 한다.

따라서 부모 클래스의 객체 대신 자식 클래스의 객체를 삽입해도 프로그램에 영향을 주면 안 된다.

 

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

 

설명

 

특정 Client를 위한 Interface 여러 개가 범용 Interface 한 개보다 낫다.

 

위에서 들었던 예를 생각해보자.

Client가 상속받은 interface에 포크를 사용하는 기능과 젓가락을 사용하는 기능이 있었다고 생각해보자.

근데 이 Client는 주로 젓가락만 사용한다.

이때 만약 포크를 사용하는 interface가 변경된다면 이 Client는 자신이 쓰지도 않는데 변경되어야 한다.

 

따라서 ISP를 만족하려면 젓가락을 쓰는 Client와 Interface, 포크만 쓰는 Client와 Interface로 나누어 설계하면 된다.

 

 

5. DIP : 의존관계 역전 원칙 (Dependancy Inversion Principle) 

 

설명

 

구체화에 의존하지 말고 추상화에 의존해야 한다.

 

즉 구현 클래스에 의존하지 말고 Interface에 의존하라는 의미이다.

 

예를 들어 Client는 이 음식이 포크를 쓰는지, 젓가락을 쓰는지에 집중할게 아니라 음식을 먹는 것에 집중하란 말이다.

 

# DIP 위배 코드
Food firstfood = new UseFork();
Food secondfood = new UseChopstick();

# DIP 적용 코드
Food firstfood = new Food();
Food secondfood = new Food();
// ... interface에서 first와 second가 어떤 도구를 사용하는를 결정해주면 됨

 

 

위의 5가지 원칙 중 OCP와 DIP가 중요도가 높다.

 

Spring에서는 OCP와 DIP를 지키기 위해 DI(Dependency Injection), 의존 관계 주입을 사용한다.

 

DI란 클라이언트가 어떤 구현체를 쓸지 정하는 게 아니라 우리가 클라이언트에게 어떤 구현체를 쓸지 말해주는 것이다.

 

Spring에서는 객체들을 스프링 컨테이너에 스프링 빈으로 등록하고 적재적소에 의존 관계를 만들어 줌으로써 OCP, DIP를 만족하게 한다. (@Autowired, @Component 등)

'Spring > Spring 공부' 카테고리의 다른 글

Spring 프로젝트로 Docker Image 만들기  (0) 2022.07.27
Spring 컨테이너와 Dependency Injection  (0) 2022.01.23
HttpMessageConverter  (0) 2022.01.16
REST API  (1) 2022.01.16
Comments