
1️⃣ SOLID 란?
SOLID 는 Robert C. Martin 이 2000년대 초반 명명한 객체 지향 프로그래밍 및 설계의 5가지 기본 원칙을 Michael C.Feathers 가 소개한 것이다. 이는 객체 지향 프로그래밍에서 중요한 원칙으로 자리잡았으며, 프로그래머가 소스 코드를 읽기 쉽고 확장하기 쉽게 될 때까지 소스 코드를 리팩터링하여 코드 냄새를 제거하기 위해 적용할 수 있는 지침이다.
'SOLID' 라는 이름은 5가지 원칙인 SRP, OCP, LSP, ISP, DIP 의 각 첫 글자를 따서 지어졌다.
즉, SOLID 는 좋은 객체 지향 프로그램을 설계하도록 하는 원칙인 것이다.
각 원칙은 다음과 같다.
- SRP (Single Responsibility Principle) : 단일 책임 원칙
- OCP (Open/Closed Principle) : 개방-폐쇄 원칙
- LSP (Liskov Substitution Principle) : 리스코프 치환 원칙
- ISP (Interface Segregation Principle) : 인터페이스 분리 원칙
- DIP (Dependency Inversion Principle) : 의존관계 역전 원칙
2️⃣ SOLID 의 각 원칙
1. SRP (Single Responsibility Principle) : 단일 책임 원칙
객체 지향 프로그래밍에서 클래스(class) 는 특정 객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀이다.
여기엔 객체를 정의하기 위한 메소드와 변수로 구성된다.
예를 들어 붕어빵 기계라는 클래스가 있다고 하자.
이 기계라는 클래스를 통해 팥 붕어빵, 슈크림 붕어빵 등 다양한 객체를 찍어낼 수 있다.
SRP 는 말 그대로 한 클래스는 하나의 책임만 가져야 한다는 원칙이다.
만약 한 클래스가 여러 책임을 가진다면, 변경이 있을 때 파급 효과가 클 것이다.
붕어빵 기계가 모양을 잡는 틀의 역할을 하는 것 뿐만 아니라 맛도 좌우한다면, 기계를 바꿨을 때 영향을 미치는 부분이 많이 생길 수 밖에 없다는 것이다.
따라서 프로그램상 변경이 있을 때, 다른 부분에 영향을 덜 미친다면 SRP 를 잘 따른 것이라 할 수 있다.
2. OCP (Open/Closed Principle) : 개방-폐쇄 원칙
OCP 는 소프트웨어 요소가 확장에는 개방적이나 변경에는 폐쇄적이어야 한다는 원칙이다.
이 말을 쉽게 이해하기 위해선 객체 지향 프로그래밍의 '다형성' 을 다시 볼 필요가 있다.
우리가 객체 지향을 실생활에 비유할 때, 객체는 부품이고 부품들을 연결, 조립하여 프로그램을 완성한다고 한다.
따라서 우리는 다형성을 활용해 필요한 객체를 빼거나 갈아 끼울 수 있는 것이다.
그런데 어떻게 하면 확장은 개방적이나 변경은 폐쇄적일 수 있을까?
역시 다형성을 활용하면 가능하다. 인터페이스로 역할을 정의하고 구체 클래스를 통해 구현을 정의하면 된다.
이는 역할과 구현의 역할이 명확히 구분되어야함을 보여준다.
그러나 다형성만 사용해서는 OCP 를 지킬 수 없는 경우도 존재한다. 이후에 다시 살펴보겠다.
3. LSP (Liskov Substitution Principle) : 리스코프 치환 원칙
LSP 란 객체는 프로그램의 정확성을 잃지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다는 원칙이다.
즉, 다형성에서 하위 클래스들은 상위 클래스의 규칙을 다 지켜야 한다는 것이다.
만약 'food' 라는 인터페이스가 있고, 이를 구현한 구현체인 'apple' 이라는 클래스가 있다고 하자.
food 인터페이스는 먹을 수 있다는 규칙이 있고, 하위 클래스인 apple 역시 먹을 수 있다는 기능이 있다.
그러나 'poison' 이라는 하위 클래스는 먹을 있다는 기능이 없고, 이는 LSP 를 위반한 것이다.
이처럼 인터페이스를 구현한 구현체를 사용하려면, 인터페이스에서 정한 규칙을 지켜야 한다.
이를 통해 프로그램상 오류를 줄일 수 있고, 엉뚱한 기능을 넣는 등 여러 문제를 방지할 수 있다.
4. ISP (Interface Segregation Principle) : 인터페이스 분리 원칙
말 그대로 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다는 뜻이다.
만약 하나의 인터페이스가 여러 종류의 클라이언트를 위해 존재한다면, 클라이언트의 변경시 많은 혼란이 생길 수 있다.
빨주노초파남보는 색깔, 도레미파솔라시는 계이름, 가나다라마바사는 한글 과 같이 분류하는 것처럼 말이다.
이렇게 하면 각 인터페이스는 역할이 명확해지고, 대체 가능성이 높아진다.
5. DIP (Dependency Inversion Principle) : 의존관계 역전 원칙
어떻게 보면 Spring 에서 지켜야 하는 핵심 원칙이라고도 볼 수 있다.
우선 객체 지향에서 의존관계를 알기 위해선 '의존성(dependency)' 라는 용어를 알아야 한다.
프로그램을 작성하다보면 수많은 패키지, 클래스, 함수 등이 복잡하게 얽혀있다.
만약 A 라는 코드가 바뀔 때, B 라는 코드의 결과까지 영향을 미친다면, 이는 의존성이 있다고 표현한다.
그 종류는 다양한데 클래스간 의존성, 패키지간 의존성 등이 있다.
쉽게 말해 변경이 생겼을 때, 결과에 영향을 미치는 것들의 관계를 의존관계라고 한다.
따라서 우리는 변경시 번거로움을 최소화하기 위해 추상화에 의존하고, 구체화에는 의존하면 안된다.
즉 앞서 말했던 역할과 구현 중 역할에 의존하게 해야 한다는 것이다.
인터페이스에 의존한다면 구체 클래스가 어떤 것이라도 유연하게 변경이 가능하다.
3️⃣ 배운 점
좋은 객체 지향 프로그램이 무엇인지 살펴보며 아무 생각 없이 코드를 작성하면 안되겠다는 생각이 들었다.
체계적으로 코드를 작성함으로써 변경과 확장에 용이하도록 설계하는 것이 얼마나 중요한 일인지 알게 되었다.
기존 Java 코드로만 OCP, DIP 등의 원칙을 지키며 개발을 해보니 어려워 탄생한 것이 Spring 이라고 한다.
물론 나는 Spring 의 좋은 기능들을 사용하겠지만, 그 전에 순수 Java 코드로도 여러 예제를 공부해볼 생각이다.
이후에는 정말 중요한 개념인 DI, IOC 등에 대해 공부해야겠다.
출처 : 김영한 - 스프링 핵심 원리(기본편), Spring 공식 사이트, 위키백과

1️⃣ SOLID 란?
SOLID 는 Robert C. Martin 이 2000년대 초반 명명한 객체 지향 프로그래밍 및 설계의 5가지 기본 원칙을 Michael C.Feathers 가 소개한 것이다. 이는 객체 지향 프로그래밍에서 중요한 원칙으로 자리잡았으며, 프로그래머가 소스 코드를 읽기 쉽고 확장하기 쉽게 될 때까지 소스 코드를 리팩터링하여 코드 냄새를 제거하기 위해 적용할 수 있는 지침이다.
'SOLID' 라는 이름은 5가지 원칙인 SRP, OCP, LSP, ISP, DIP 의 각 첫 글자를 따서 지어졌다.
즉, SOLID 는 좋은 객체 지향 프로그램을 설계하도록 하는 원칙인 것이다.
각 원칙은 다음과 같다.
- SRP (Single Responsibility Principle) : 단일 책임 원칙
- OCP (Open/Closed Principle) : 개방-폐쇄 원칙
- LSP (Liskov Substitution Principle) : 리스코프 치환 원칙
- ISP (Interface Segregation Principle) : 인터페이스 분리 원칙
- DIP (Dependency Inversion Principle) : 의존관계 역전 원칙
2️⃣ SOLID 의 각 원칙
1. SRP (Single Responsibility Principle) : 단일 책임 원칙
객체 지향 프로그래밍에서 클래스(class) 는 특정 객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀이다.
여기엔 객체를 정의하기 위한 메소드와 변수로 구성된다.
예를 들어 붕어빵 기계라는 클래스가 있다고 하자.
이 기계라는 클래스를 통해 팥 붕어빵, 슈크림 붕어빵 등 다양한 객체를 찍어낼 수 있다.
SRP 는 말 그대로 한 클래스는 하나의 책임만 가져야 한다는 원칙이다.
만약 한 클래스가 여러 책임을 가진다면, 변경이 있을 때 파급 효과가 클 것이다.
붕어빵 기계가 모양을 잡는 틀의 역할을 하는 것 뿐만 아니라 맛도 좌우한다면, 기계를 바꿨을 때 영향을 미치는 부분이 많이 생길 수 밖에 없다는 것이다.
따라서 프로그램상 변경이 있을 때, 다른 부분에 영향을 덜 미친다면 SRP 를 잘 따른 것이라 할 수 있다.
2. OCP (Open/Closed Principle) : 개방-폐쇄 원칙
OCP 는 소프트웨어 요소가 확장에는 개방적이나 변경에는 폐쇄적이어야 한다는 원칙이다.
이 말을 쉽게 이해하기 위해선 객체 지향 프로그래밍의 '다형성' 을 다시 볼 필요가 있다.
우리가 객체 지향을 실생활에 비유할 때, 객체는 부품이고 부품들을 연결, 조립하여 프로그램을 완성한다고 한다.
따라서 우리는 다형성을 활용해 필요한 객체를 빼거나 갈아 끼울 수 있는 것이다.
그런데 어떻게 하면 확장은 개방적이나 변경은 폐쇄적일 수 있을까?
역시 다형성을 활용하면 가능하다. 인터페이스로 역할을 정의하고 구체 클래스를 통해 구현을 정의하면 된다.
이는 역할과 구현의 역할이 명확히 구분되어야함을 보여준다.
그러나 다형성만 사용해서는 OCP 를 지킬 수 없는 경우도 존재한다. 이후에 다시 살펴보겠다.
3. LSP (Liskov Substitution Principle) : 리스코프 치환 원칙
LSP 란 객체는 프로그램의 정확성을 잃지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다는 원칙이다.
즉, 다형성에서 하위 클래스들은 상위 클래스의 규칙을 다 지켜야 한다는 것이다.
만약 'food' 라는 인터페이스가 있고, 이를 구현한 구현체인 'apple' 이라는 클래스가 있다고 하자.
food 인터페이스는 먹을 수 있다는 규칙이 있고, 하위 클래스인 apple 역시 먹을 수 있다는 기능이 있다.
그러나 'poison' 이라는 하위 클래스는 먹을 있다는 기능이 없고, 이는 LSP 를 위반한 것이다.
이처럼 인터페이스를 구현한 구현체를 사용하려면, 인터페이스에서 정한 규칙을 지켜야 한다.
이를 통해 프로그램상 오류를 줄일 수 있고, 엉뚱한 기능을 넣는 등 여러 문제를 방지할 수 있다.
4. ISP (Interface Segregation Principle) : 인터페이스 분리 원칙
말 그대로 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다는 뜻이다.
만약 하나의 인터페이스가 여러 종류의 클라이언트를 위해 존재한다면, 클라이언트의 변경시 많은 혼란이 생길 수 있다.
빨주노초파남보는 색깔, 도레미파솔라시는 계이름, 가나다라마바사는 한글 과 같이 분류하는 것처럼 말이다.
이렇게 하면 각 인터페이스는 역할이 명확해지고, 대체 가능성이 높아진다.
5. DIP (Dependency Inversion Principle) : 의존관계 역전 원칙
어떻게 보면 Spring 에서 지켜야 하는 핵심 원칙이라고도 볼 수 있다.
우선 객체 지향에서 의존관계를 알기 위해선 '의존성(dependency)' 라는 용어를 알아야 한다.
프로그램을 작성하다보면 수많은 패키지, 클래스, 함수 등이 복잡하게 얽혀있다.
만약 A 라는 코드가 바뀔 때, B 라는 코드의 결과까지 영향을 미친다면, 이는 의존성이 있다고 표현한다.
그 종류는 다양한데 클래스간 의존성, 패키지간 의존성 등이 있다.
쉽게 말해 변경이 생겼을 때, 결과에 영향을 미치는 것들의 관계를 의존관계라고 한다.
따라서 우리는 변경시 번거로움을 최소화하기 위해 추상화에 의존하고, 구체화에는 의존하면 안된다.
즉 앞서 말했던 역할과 구현 중 역할에 의존하게 해야 한다는 것이다.
인터페이스에 의존한다면 구체 클래스가 어떤 것이라도 유연하게 변경이 가능하다.
3️⃣ 배운 점
좋은 객체 지향 프로그램이 무엇인지 살펴보며 아무 생각 없이 코드를 작성하면 안되겠다는 생각이 들었다.
체계적으로 코드를 작성함으로써 변경과 확장에 용이하도록 설계하는 것이 얼마나 중요한 일인지 알게 되었다.
기존 Java 코드로만 OCP, DIP 등의 원칙을 지키며 개발을 해보니 어려워 탄생한 것이 Spring 이라고 한다.
물론 나는 Spring 의 좋은 기능들을 사용하겠지만, 그 전에 순수 Java 코드로도 여러 예제를 공부해볼 생각이다.
이후에는 정말 중요한 개념인 DI, IOC 등에 대해 공부해야겠다.
출처 : 김영한 - 스프링 핵심 원리(기본편), Spring 공식 사이트, 위키백과