본문 바로가기
Study/Java Spring Boot

[Spring] 핵심 원리 10 강의를 마치며

인프런에서 Spring Intro 강의를 거쳐,

Spring Core Basic 강좌를 듣고 정리하고 학습하는 과정을 마쳤다.

그동안 배운 9가지 주제를 정리하며 회고하는 글을 작성해보려 한다.

1. 객체지향 설계와 스프링(SOLID)

스프링의 탄생 배경부터 설명을 해주셨다.

Enterprise Java Beans (EJB)가 발전하면서 의존적이러 난해한 생태계를

다시 POJO (순수 과거 자바 오브젝트로 돌아가자) 는 말들로

로드 존슨과 개빈 킹이 Java의 겨울을 끝내고 Spring과 JPA를 만든다.

 

다양한 기는중에서도 스프링 부트의 핵심은 결국

객체 지향적 설계를 가능케 하는 기술들이였다.

 

이와 더불어 배운 클린코드의 저서 로버트 마틴이 제시한 OOP에 좋은 설계를 위한 5가지 SOLID 원칙.

  1. SRP (단일 책임 원칙)
  2. OCP (개방 폐쇄 원칙)
  3. LSP (리스코프 치환원칙)
  4. ISP (인터페이스 분리 원칙)
  5. DIP (의존관계 역전원칙)

배우면서 이제서야 이 원칙을 알게된 내가 부끄럽기도 하고,

코드를 작성할 때,  상시 역할과 책임을 구분하여 생각하고 설계하도록 마음속에 새기게 되었다.

이 강의에 핵심은 1장이였다고 생각한다.

 

왜 스프링을 쓰는지, 왜 DI를 해야하고, 싱글톤을 보장해주어야 하는지에 대한 모든 답은 1장이였다.

 

2, 3. 회원 도메인 개발과 테스트

Java 11, Gradle 기반의 프로젝트 코드를 짜보면서,

기본 프로젝트의 실행과 테스트의 작성법을 배웠다.

 

코드는 mvc 패턴이 아닌,

단순 서비스 부분으로만 작성하면서

수행 테스트를 하면서 진행 되었고,

 

예제 코드를 통해, 객체 지향적이지 못한 코드와 DIP, OCP 원칙 위배에 대해서 상세히 설명해주셨다.

 

우리가 에자일 소프트웨어 개발 내용과 같이,

변화에 대응하고, 고객과 협력하며 , 개인과 상호작용하는것에 가치를 두는 프로그래밍이 무엇인지를

자연스럽게 습득할 수 있었다.

 

3. 객체 지향 원리 적용 (DI컨테이너)

객체 지향적인 SOLID원칙을 준수하기 위해 순수자바로  AppConfig라는 클래스를 만들어 DI 컨테이너를 구현해본다.

모든 객체는 구현체가 아닌 추상체에 의존하도록 변경하고,

추상체 필드에 구현체에 의존성을 주입하는 부분은

AppConfig라는 DI 클래스에서 이루어지도록 모아서 관리하는 방법을 소개한다.

 

이것이 loC 제어의 역전, DI 의존성 주입 , Object 팩토리, 어셈블러 등으로 일컬어 짐도 알게 되었다.

이를 통해 기능의 확장 구현시에도, OCP를 준수하며 DI컨테이너를 통해서 연결만 수정해주면 됨을 확인하였다.

 

4. 스프링 컨테이너와 빈 (Spring 전환)

지금까지 순수자바로 작성했던 객체지향적인 설계를 스프링으로 전환하면서

얼마나 간편하고 쉽게 SOLID를 지킬 수 있는지 볼 수 있다.

 

@Configuration을 통해 수행부터 @Bean을 찾아 스프링 컨테이너에 등록해주며,

AnnotationConfigApplicationContext 를 통해 등록된 Bean을 조회해보며 동작 원리를 이해하고,

bean이 고유한 이름을 가지며, 여러빈을 받아 조회하는 방법들을 살펴본다.

 

 

 5. 싱글톤 컨테이너 (싱글톤 패턴과 주의점)

싱글톤 패턴이 왜 필요한지, 또한 설계시 무엇을 주의해야하는지를 알려주신다.

Spring Bean은 기본적으로 싱글톤 패턴을 지원하며, 아래와 같은 주의점을 명심해야 한다.

  • 무상태(stateless)로 설계해야 한다!
  • 특정 클라이언트에 의존적인 필드가 있으면 안된다
  • 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다!
  • 공유 필드 대신에 자바에서 지역변수, 파라미터, ThreadLocal 등을 사용해야 한다.
  • 스프링 빈의 필드에 공유 값을 설정하면 정말 큰 장애가 발생할 수 있다!!!

실무에서 발생했던 장애와 이슈를 예시로 들어주시면서 가르쳐주셔서 간접적으로 얼마나 중요한지를 인지할 수 있었다.

@Configuration을 통해서 @Bean 객체를 컨테이너에 등록하여 싱글톤을 보장한다는 사실을 배웠다.

 

6. 컴포넌트 스캔 (@Component)

@Configuration과 @Bean을 명시했던 AppConfig 클래스는 외부에서 빈을 등록하고 의존성을 주입하는 방식이다.

이번에는 이런 외부 DI컨테이너를 만들지 않고도

Spring에서 각 객체에 자동으로 Bean을 등록하고 의존성을 주입받는 더 쉬운 방법을 가르쳐준다.

 

각 객체별로 @Component (@Service, @Controller, @Repository .. ) 을 명시해주면,

해당 Spring 기동시 해당 컴포넌트를  스프링 컨테이너에 빈으로 자동 등록해준다.

그리고 @AutoWired를 명시해주면, 쉽게 등록된 빈 객체를 주입받을 수 있는 방법이다.

 

스프링이 어노테이션을 활용하여 쉽게 빈을 등록하고 의존성을 주입 받는 방법으로

외부 (AppConfig 와 같은) DI컨테이너를 사용하지 않는 방법을 알려주신다.

 

명시된 컴포넌트 객체들중에서 부분적으로 자동등록이 되도록 설정할 수 도 있다.

스캔하는 위치를 지정해주거나, 스캔 필터를 통해 막아주는것도 가능하다는것을 예제코드로 배운다.

 

7. 의존 관계 자동 주입 (@AutoWired)

  1. 생성자 주입
  2. 수정자 주입 / Setter 주입
  3. 필드 주입
  4. 일반 메서드 주입

4가지 방법의 의존성 주입이 있지만, 99% 1번 생성자 주입방식을 사용한다.

또한 롬복 라이브러리를 통해 @RequiredArgsConstructor 로 생성자를 작성하지 않고도 사용하게 하고,

자동 등록된 Bean이 2개 이상인 경우의 Map , List를 통해 받아드리는 방법과,

애초에 2개이상 등록을 막기위한 3가지 방법을 가르쳐주신다. (@Autowired 필드명, @Qualifier, @Primary)

 

그리고, AppConfig와 같은 수동 빈 등록 객체는

1. 기술 지원 로직 : AOP(공통 관심사), DataBase연결, 공통 로그 처리 등의

비즈니스 요구사항에 해당되는 서비스가 아닌 

공통 하위 기술들을 가급적 수동 Bean등록을 사용하여 따로 관리해주는것이 유지보수에 더 좋으며

2.  다형성을 적극 활용할 때

다양한 할인 정책 Bean과 같이 인터페이스를 활용해 다형성을 가지는 Bean을 관리할 때에는 

아래와 같이  자동 등록보다 수동 빈 등록으로 따로 관리해주는게 쉽게 연결을 구성하고 변경하기 좋고 가르쳐 주셨다.

 

8. 빈 생명주기 콜백

빈의 생명주기에서 빈의 생성 → 의존 관계 주입 이후

초기화 전소멸 전에 작업을 위한 콜백 메소드 지정하는 방법으로  @PostConstruct, @PreDestroy 의 사용법을 배운다.

 

9. 빈 스코프

싱글톤 스코프와 달리 프로토타입 스코프의 존재를 배우며, 

싱글톤빈과 사용시 싱글톤안에서 소멸되지 않는 문제를 해결하기 위한 방법으로 Provider가 있음을 배운다.

 

또한 웹 스코프의 종류와 Request 사용예제를 통해 다루는 방식을 배워보면서,

요청을 통해 만들어지는 웹 request 스코프의 빈을 먼저 컨테이너에 등록하고 주입받도록 하는

지연 초기화 기술로 ProxyMode가 있음을 배운다.

 

 

강의를 마치며...

강의를 들으면서 사실 Spring Intro에서 다루었던 내용들을 만나서 새롭고 신기 하기 보다는

복습의 개념으로 귀에 쏙쏙 들어왔다.

Intro 강의를 듣길 잘했다는 생각이 든다.

그리고 강의를 통해 일부분의 갈증은 해소되었지만,

더 많은 부분에 대한 갈증이 생긴다.

 

기초를 탄탄히 가지는걸 굉장히 좋아하는데,

꽤나 깊이 왜라는 물음을 던져가면서 가르쳐 주셨기 때문에

김영한님을 통해 Spring에 첫단추를 잘 붙인것 같다.