Go, Vantage point
가까운 곳을 걷지 않고 서는 먼 곳을 갈 수 없다.
Github | https://github.com/overnew/
Blog | https://everenew.tistory.com/
티스토리 뷰
* 김영한님의 스프링 핵심원리 기본편 강좌를 수강하며 정리한 글입니다. *
스프링의 탄생
스프링의 명칭 자체는 자바 진영의 새로운 시작을 의미하는 것으로 문자 그대로 봄을 뜻한다.
과거 자바 진영의 표준이었던 EJB는 복잡함 때문에 많은 개발자들이 녹아내렸다...
표준이 이 모양이다 보니, 많은 개발자들이 좀 더 편리한 기능들의 자바 오픈 소스 프로젝트를 발표했고, 스프링도 이중에 하나였다.
스프링은 단 하나의 기술을 말하는 것이 아닌 여러 기술들의 생태계를 의미한다.
이중에서도 스프링 프레임 워크와 스프링 부트가 가장 중요한데, 대부분 스프링의 공부는 스프링 프레임워크를 배우는 것을 의미한다.
스프링 프레임워크의 핵심 기술은 DI 컨테이너, AOP 등이 존재하는데, 이에 대한 설명을 아래에서 진행하겠다.
스프링 부트란?
스프링도 초기에는 설정이 굉장히 복잡했지만 스프링 부트의 등장으로 스프링의 기술들을 편리하게 사용할 수 있게 되었다.
스프링 부트는 Tomcat 웹 서버를 내장하여 별도의 웹 서버를 설치하고 설정하는 번거로움이 없고, 외부 라이브러리들을 사용할 때 해당 라이브러리가 종속된 라이브러리들도 자동으로 받아오는 편의성도 갖추었다.
따라서 스프링을 사용한다면 스프링 부트는 선택지가 아닌 필수 요소로 받아지고 있고, 실무에서도 스프링 부트로 프로젝트를 시작한다고 한다. (독립적인 기술이 아니라는 것!)
스프링의 핵심은 객체 지향
스프링을 단순히 백엔드 기술 중 하나라고 생각하기 쉽지만, 스프링의 핵심은 객체 지향이다.
자바 언어의 기반이니 당연하게 생각될 수 있지만, 스프링 프레임워크는 객체 지향의 강력한 특징을 살려낼 수 있다.
여기서 로버트 마틴이 정리한 좋은 객체지향 설계의 5가지 원칙, SOLID를 살펴보자.
- SRP: 단일 책임 원칙(single responsibility principle)
- OCP: 개방-폐쇄 원칙 (Open/closed principle)
- LSP: 리스코프 치환 원칙 (Liskov substitution principle)
- ISP: 인터페이스 분리 원칙 (Interface segregation principle)
- DIP: 의존관계 역전 원칙 (Dependency inversion principle
SRP: 단일 책임 원칙(single responsibility principle)
한 클래스는 하나의 책임만을 가져야 한다는 원칙.
하지만 코드를 짜다보면 느끼겠지만 상황에 따라 달라지기 쉽다.
중요한 기준은 변경이 있을 때, 수정할 부분이 적다면 잘 지켜진 것으로 볼 수 있다.
OCP: 개방-폐쇄 원칙 (Open/closed principle)
이번 게시글에서 가장 중요한 OCP 원칙이다.
소프트웨어 요소는 확장에는 열려있지만 변경에는 닫혀 있어야 한다.
이를 이해하기 위해서 일단 자바의 객체 지향에 대해 집고 넘어가자.
객체 지향관점에서는 세상을 역할과 그 구현으로 나눈다.
예를 들어 요리사라는 역할(인터페이스)에 이를 수행하는 여러 사람(구현체)이 있을 수 있다.
손님(클라이언트)의 입장에서는 요리사가 누군지, 레시피가 어떤지 상관없이 주문한 요리가 나오면 상관이 없을 것이다.
즉, 역할과 구현을 분리하면 클라이언트는 인터페이스만 알면 되고 구현 대상의 내부 구조는 몰라도 된다.
따라서 내부 구조가 변경되거나, 그 구현대상 자체를 변경해도 영향을 받지 않는다.
이것은 객체지향의 핵심인 다형성으로 구현할 수 있다.
위의 요리사 예를 생각해보면 요리사라는 역할(인터페이스)를 구현하는 여러 요리사(구현체)가 있을 수 있다.
손님(클라이언트)의 입장에서는 어떤 요리사가 만들든 영향이 없을 것이다.
하지만 직접 Java코드로 작성을 해보면, 구현체를 변경하면 클라이언트의 코드에 변경이 필요하다.
이러한 변경은 엄밀히 말하면 OCP 원칙이 깨졌다고 볼 수 있다.
이는 DIP 원칙도 위반하게 된다.
DIP: 의존관계 역전 원칙 (Dependency inversion principle)
프로그래머는 추상화에 의존해야지, 구체화에 의존하면 안된다는 원칙으로,
여기서의 의존은 코드를 알고 사용한다는 의미로 받아들이면된다.
예를 들어 위의 Guest는 cook이 order()라는 메서드를 제공함을 알고 사용하므로, CookInterface에 의존한다.
또한 내부 코드에서 구현체 클래스까지 알고 직접 선택하고 있으므로 구현체도 의존하고 있다.
클라이언트 코드의 의존성으로 인해 구현체의 변경이 클라이언트 코드에도 영향을 주고, OCP도 동시에 위반한다.
따라서 인터페이스(추상화)에만 의존하도록 변경이 필요하다.
이처럼 다형성만으로는 OCP, DIP를 지킬 수 없다.
여기서 스프링 프레임워크가 제공하는 DI(Dependency InJection)과 컨테이너 기술로 클라이언트 코드의 변경 없이도 개발이 가능하다.
즉, 스프링은 객체지향의 장점을 극대화시킬 수 있는 기술이라는 관점을 가지고, 공부해 나가는 것이 스프링을 제대로 활용할 수 있는 방법이다.
'개발 > Spring' 카테고리의 다른 글
[Spring] 6. 스프링 컨테이너 설정 정보와 BeanDefinition (0) | 2022.06.25 |
---|---|
[Spring] 5. 스프링 빈 조회, getBean() (0) | 2022.06.25 |
[Spring] 4. 스프링 컨테이너와 스프링 빈 (0) | 2022.06.23 |
[Spring] 3. 제어의 역전(IoC)과 컨테이너 (0) | 2022.06.23 |
[Spring] 2. 구성 영역의 분리와 DI(Dependency Injection) (0) | 2022.05.30 |