좋은 설계란 시스템에 새롤운 요구사항이나 변경사항이 있을 때, 영향을 받는 범위가 적은 구조를 말한다.
SOLID 객체 지향 원칙을 적용하면 코드를 확장하고 유지 보수 관리
하기가 더 쉬워지며, 불필요한 복잡성을 제거
해 리팩토링에 소요되는 시간을 줄임으로써 프로젝트의 개발의 생산성을 높일 수 있다.
SOLID는 특정 프로그래밍 언어 혹은 프레임워크를 위해 만든 원칙이 아니다.
SOLID 원칙이란 객체지향 설계에서 지켜줘야 할 5개의 소프트웨어 개발 원칙을 말한다.
- SRP (Single Responsibility Principle): 단일 책임 원칙
- OCP (Open Closed Principle): 개방 폐쇄 원칙
- LSP (Listov Substitution Principle): 리스코프 치환 원칙
- ISP (Interface Segregation Principle): 인터페이스 분리 원칙
- DIP (Dependency Inversion Principle): 의존 역전 원칙
단일 책임 원칙 - SRP (Single Responsibility Principle)
- 클래스 (객체)는 단 하나의 책임만 가져야 한다는 원칙
- 여기서 ‘책임’ 이라는 의미는 하나의 ‘기능 담당’으로 보면 된다.
- 즉, 하나의 클래스는 하나의 기능을 담당하여 하나의 책임을 수행하는데 집중되도록 클래스를 따로따로 여러개 설계하라는 원칙이다.
- 하나의 클래스에 기능(책임)이 여러개 있다면 기능 변경(수정)이 일어났을 때 수정해야할 코드가 많아진다. A를 고쳤더니 B를 수정해야하고 또 C를 수정해야하고, C를 수정했더니 다시 A로 돌아가서 수정해야하는, 책임이 순환되는 형태가 되어버린다. 따라서 SRP 원칙을 따름으로써 한 책임의 변경으로부터 다른 책임의 변경으로의 연쇄작용을 극복할 수 있게 된다.
- SRP의 목적은 프로그램의 유지보수성을 높이기 위한 설계 기법이다.
- 하나의 클래스로 너무 많은 일을 하지말고 딱 한 가지 책임만 수행하면 된다.
개방 폐쇄 원칙 - OCP (Open Closed Principle)
- OCP 원칙은 클래스는 확장에 열려있어야 하며, 수정에는 닫혀있어야 한다를 뜻함.
- 기능 추가 요청이 오면 클래스를 확장을 통해 손쉽게 구현하면서, 확장에 따른 클래스 수정은 최소화하도록 프로그램을 작성해야하는 설계 기법.
- “확장에 열려있다.” - 새로운 변경 사항이 발생했을 때 유연하게 코드를 추가함으로써 애플리케이션의 기능을 확장할 수 있음.
- “변경에 닫혀있다.” - 새로운 변경 사항이 발생했을 때 객체를 직접적으로 수정을 제한함.
- 추상화 사용을 통한 관계 구축을 권장
- 다형성과 확장을 가능하게 하는 객체지향의 장점을 극대화하는 기본적인 설계 원칙
리스코프 치환 원칙 - LSP (Liskov Substitution Principle)
- LSP 원칙은 서브 타입은 언제나 기반 타입으로 교체할 수 있어야 한다는 원칙이다.
- LSP는 다형성 원리를 이용하기 위한 원칙 개념으로 보면 된다.
- 다형성의 특징을 이용하기 위해 상위 클래스 타입으로 객체를 선언하여 하위 클래스의 인스턴스를 받으면, 업캐스팅된 상태에서 부모의 메서드를 사용해도 동작이 의도대로 흘러가야 하는 것을 의미하는 것.
- LSP 원칙은 부모 메서드의 오버라이딩을 살펴보며 해야한다. 부모 클래스와 동일한 수준의 선행 조건을 기대하고 사용하는 프로그램 코드에서 예상치 못한 문제를 일으킬 수 있다.
- ex. JAVA - Collection 인터페이스
- Collection 타입의 객체에서 자료형을 LinkedList에서 HashSet으로 바꿔도
add()
메서드를 실행하는데 있어 원래 의도대로 작동된다. - 즉, 다형성 이용을 위해 부모 타입으로 메서드를 실행해도 의도대로 실행되도록 구성을 해줘야하는 원칙이다.
- Collection 타입의 객체에서 자료형을 LinkedList에서 HashSet으로 바꿔도
public void myData() {
// Collection 인터페이스 타입으로 변수 선언
Collection data = new LinkedList();
data = new HashSet(); // 중간에 전혀 다른 자료형 클래스를 할당해도 호환됨
modify(data); // 메소드 실행
}
public void modify(Collection data){
list.add(1); // 인터페이스 구현 구조가 잘 잡혀있기 때문에 add 메소드 동작이 각기 자료형에 맞게 보장됨
// ...
}
인터페이스 분리 원칙 - ISP (Interface Segregation Principle)
- ISP 원칙은 인터페이스를 각각 사용에 맞게끔 잘게 분리해야한다는 설계 원칙이다.
- SRP 원칙 → 클래스의 단일 책임 강조, ISP 원칙 → 인터페이스의 단일 책임을 강조
- SRP 원칙의 목표는 클래스 분리를 통해 이루어진다면, ISP 원칙은 인터페이스 분리를 통해 설계하는 원칙이다.
- ISP 원칙은 인터페이스를 사용하는 클라이언트를 기준으로 분리함으로써, 클라이언트의 목적과 용도에 적합한 인터페이스 만을 제공하는 것이 목표이다.
- 주의해야할 점은 한 번 인터페이스를 분리하여 구성해놓고 나중에 수정사항이 생겨서 또 인터페이스들을 분리하는 행위를 하면 안 된다.
- 인터페이스는 한 번 구성하였으면 웬만해선 변하면 안되는 정책 개념
- 인터페이스는 제약없이 자유롭게 다중 상속이 가능하기 때문에 분리할 수 있으면 분리하여 각 클래스 용도에 맞게 implements 하라는 설계 원칙.
의존 역전 원칙 - DIP (Dependency Inversion Principle)
- DIP 원칙은 어떤 Class를 참조해서 사용해야하는 상황이 생긴다면 그 Class를 직접 참조하는 것이 아니라 그 대상의 상위 요소 (추상 클래스 or 인터페이스)로 참조하라는 원칙이다.
- 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻이다.
- 의존 관계를 맺을 때 변화하기 쉬운 것 또는 자주 변화하는 것보다는 변화하기 어려운 것 거의 변화가 없는 것에 의존하라는 것이다.
- 의존 역전 원칙의 지향점은 각 클래스간의 결합도를 낮추는 것이다.
참고자료
'공부' 카테고리의 다른 글
[Spring] 순환참조문제 (0) | 2025.04.04 |
---|---|
[Spring] spring의 의존성 주입 방법 4가지 (0) | 2025.04.04 |
[Spring] POJO란? Hibernate와 Spring이 왜 POJO 친화적인가 (0) | 2025.04.03 |
[DDD] Aggregate란? (0) | 2025.04.01 |
[JPA] JPA의 N + 1 문제 정리 (0) | 2025.03.27 |