본문 바로가기

Spring

[spring] SOLID 원칙

 최근 스프링을 공부하면서 SOLID 원칙(객체지향 5대원칙)이라는 단어를 들어보았다. 강의에서 말하는 내용을

듣기만 해서는 이해가 쉽게 가지않고 잊어버리지 않게 위해서 다시 정리하면서 포스팅을 할려고 한다.

 

객체지향 5대 원칙(SOLID원칙)이란

 SRP(단일 책임 원칙), OCP(개방-폐쇄 원칙), LSP(리스코프 치환 원칙), DIP(의존 역전 원칙), ISP(인터페이스 분리 원칙)을 말하며, 앞자를 따서 SOILD 원칙이라고 부른다. 프로그래머가 시간이 지나도 유지 보수와 확장이 쉬운 소프트웨어를 만드는데 이 원칙들을 적용할 수 있다.

 

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

"소프트웨어의 설계 부품(클래스, 함수 등)은 단 하나의 책임만을 가져야 한다."

여기서 책임이란, '기능'정도의 의미로 해석하면 된다.

 

이는 SRP를 잘 지켰다면 새로운 요구사항및 변경사항에 유연하게 대처할수있음을 의미한다. 즉 한 클래스가 수행할수있는 기능(책임)이 적어진다면 클래스 내부끼리의 강한결합을 미연에 방지할수있고 이는 유지보수에 비용의 증가를 막을수있다. 그러므로 책임을 분리시킬필요가 있다.

 

2. Open-Closed Principle (개방-패쇄 원칙), OCP
"기존의 코드를 변경하지 않고(Closed) 기능을 수정하거나 추가할 수 있도록(Open) 설계해야 한다."

이는 무슨말이냐 하면, 프로그램을 유지 보수하면서 코드를 변경하지않고 확장은 가능하게 해야한다.

 

즉 기존의 주요 로직이 작동하는 클래스는 그래도 두되 주요 로직이 동작하는 클래스에서 객체를 할당(new)하는 코드를 임의의 클래스(ex. AppConfig)에서 할당하여 건네준다. 그렇게 한다면 이는 주요 로직이 동작하는 클래스는 가만히 두고(변경하지않고) 객체를 변경(기능을 확장)할수있다.

 

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

"자식 클래스는 부모클래스에서 가능한 행위를 수행할 수 있어야 한다."

부모 클래스와 자식 클래스 사이의 행위에는 일관성이 있어야 한다는 원칙

 

리스코프 치환 원칙은 MIT 컴퓨터 사이언스 교수인 리스코프가 제안한 설계 원칙이다. 이는 객체 지향 프로그래밍에서 부모 클래스의 인스턴스 대신 자식 클래스의 인스터스를 사용해도 문제가 없어야 한다는 것을 의미한다.
간단하게 오버라이딩정도로 생각하면 될듯하다.

 

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

"의존 관계를 맺을 때, 변화하기 쉬운것 보단 변화하기 어려운 것에 의존해야 한다는 원칙이다."

 

이는 말이 어려운데 쉽게 설명하면 클래스를 작성할떄 DIP를 준수할려면 추상화(인터페이스)에 의존하고 구체화에 의존하면 안된다는 말이다. 이는 위의 OCP와도 연관이 있는데 객체를 생성할때, 구체적인 클래스를 통해 생성하는것이 아닌 인터페이로만 생성을 해야하는것이다. 그렇다면 객체는 어떡게 생성하냐는 의구심이 든다. 이는 의존성 주입. 이라는 기술로 해결을 할수있다. 말이 어렵지 쉽게 설명을 하자면 생성자를 통해 생성을 한다는 것이다. 그렇다면 주요 로직을 구성하는 클래스에는 구체화역할을 담당하는 클래스만 있을것이고 직접적으로 구체화를 수행하는 코드는 없을것이다. 그렇다면 이는 DIP를 만족한다고 볼수있겠다.

한줄로 요약하자면 기존클래스에는 다른 객체를 생성하는 기능(역할)과 주요 로직을 구성하는 기능(역할)이 있었다면 이것을 객체를 생성하는 기능(역할)만을 담당하는 임의의 클래스를 따로 작성을 하여 그 클래스에 전부 일임 하는것이다.

 

5. Interface Segregation Principle (인터페이스 분리 원칙), ISP
"한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다. 하나의 일반적인 인터페이스보다는, 여러 개의 구체적인 인터페이스가 낫다."

이는 앞서말한 SRP와도 어느정도 맥락을 같이하는 말인데. 예를 들면 "자동차"라는 인터페이스와 "운전자"라는 인터페이가 있다면 "자동차"를 구체화하는 클래스에서 "운전자"라는 인터페이스를 구현할 필요가 없다는 것이다. 만일 하나의 클래스에 사용하지않는 인터페이스를 구현해놓는다면 이는 시스템 내부 의존성을 악화시켜 리팩토링, 수정, 배포를 쉽게 할수 없게 된다.

 

스프링을 공부하면 따로 정리가 필요할듯 하여 포스팅을 한다. 아직은 공부가 많이 부족한듯하다. 나중에는 위의 5가지원칙을 당연하게 생각하여 자연스럽게 구현할수있는 수준까지 왔으면 좋겠다.