스프링 핵심 원리 – 기본편


객체 지향 설계와 스프링


이야기 - 자바 진영의 추운 겨울과 스프링의 탄생

  • EJB ( Enterprise Java Beans ) 자바 표준 기술 중 최고봉
  • 코드가 어렵고 복잡해서 지옥이라고 불림.
  • 해결: 하이버네이트(JPA)와 스프링이라는 새로운 기술이 생김.

스프링의 역사

로드 존슨 책 출간 -> 오픈 소스 프로젝트 시작

스프링이란?

특정한 하나가 아니라 여러 개의 모음

  • 필수: 스프링 프레임워크, 스프링 부트
  • 선택: 스프링 데이터, 스프링 세션, 스프링 시큐리티, 스프링 Rest Docs, 스프링 배치, 스프링 클라우드

    스프링 프레임워크

  • 핵심기술 : 스프링 DI 컨테이너, AOP, 이벤트 기타
  • 웹 기술: 스프링 MVC, 스프링 WebFlux
  • 데이터 접근 기술: 트랜잭션, JDBC, ORM지원, XML 지원
  • 기술 통합: 캐시, 이메일, 원격접근, 스케줄링
  • 테스트: 스프링 기반 테스트 지원
  • 언어: 코틀린, 그루비

스프링부트 : 스프링을 편리하게 사용할 수 있도록 지원

스프링의 핵심 개념 및 컨셉 : 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임워크

좋은 객체 지향 프로그래밍이란?

  • 다형성 : 클라이언트에 영향을 주지 않고 새로운 기능을 추가할 수 있음.

image

  • 유연하고 변경 가능하다
  • 역할과 구현을 분리한다.
  • 역할: 인터페이스, 구현: 인터페이스를 구현한 클래스와 구현 객체
  • 자바의 다형성 : 오버라이딩
  • 클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.

** 인터페이스를 잘 설계하는 것이 중요해진다.

좋은 객체 지향 설계의 5가지 원칙(SOLID)

  • SRP : 단일 책임 원칙 (하나의 클래스는 하나의 책임만 가진다 – 변경이 있을 때, 파급효과가 작다면, 이 원칙이 잘 지켜진 코드이다.)
  • OCP: 개방-폐쇄 원칙 (확장에는 열려 있으나 변경에는 닫혀 있어야한다.)
  • LSP: 리스코프 치환 원칙 (하위 타입의 인스턴스로 바꿀 수 있어야한다.)
  • ISP: 인터페이스 분리 원칙 (기능을 적당한 크기로 분리한다.)
  • DIP: 의존관계 역전 원칙(추상화(역할)에 의존O, 구체화(구현)에는 의존X)

객체 지향 설계와 스프링

  • 스프링, DI 컨테이너 제공: 의존관계 의존성 주입으로 OCP, DIP를 가능하게 함.

스프링 핵심 원리 이해1 – 예제 만들기

프로젝트 생성

  • 스프링 부트 스타터로 스프링 프로젝트 생성

비즈니스 요구사항과 설계

회원 도메인 설계

  • 회원을 가입하고 조회할 수 있다.
  • image

  • 역할: 클라이언트, 회원 서비스, 회원 저장소
  • 회원 저장소의 구현: 메모리, DB, 외부 시스템

image

  • 회원 서비스 : MemberServiceImpl

회원 도메인 개발

회원 도메인 실행과 테스트

  • Junit : @test 코드 작성

주문과 할인 도메인 설계

image

  • 역할과 구현을 분리: 구현 객체를 조립할 수 있게 설계가 되었다.
  • Enum type 은 비교문에 있어서 ==을 사용하는 것이 맞음.

주문과 할인 도메인 개발

주문과 할인 도메인 실행과 테스트


스프링 핵심 원리 이해2 - 객체 지향 원리 적용

새로운 할인 정책 개발

새로운 할인 정책 적용과 문제점

  • 인터페이스에만 의존하도록 설계를 변경

관심사의 분리

  • AppConfig의 등장 : 구현 객체를 생성하고 연결하는 책임은 따로 클래스를 만든다.
  • image

  • 의존관계 주입

IoC, DI, 그리고 컨테이너

  • 제어의 역전 : 내가 직접 호출하는 것이 아니라, 프레임워크가 내 코드를 실행해주는 것.
  • AppConfig : 프로그램에 대한 제어 흐름에 대한 권한을 모두 가진다. Impl 클래스는 단순히 실행하는 역할만을 담당하고, AppConfig가 프로그램의 제어 흐름을 모두 가져간다.

프레임워크 vs 라이브러리

  • 프레임워크 : 내가 작성한 코드를 대신 제어하고 대신 실행 (내가 필요한 부분만 개발함.)
  • 라이브러리 : 내가 작성한 코드가 직접 제어한다.

의존 관계 주입

  • 정적인 클래스 의존 관계 (실행 없이도 확인 가능)
  • 실행 시점에 결정되는 동적인 객체 의존관계 ( 인스턴스 )
  • 의존 관계 주입은 정적인 클래스 의존관계의 변함 없이 동적인 의존관계만 변경 가능하다는 장점이 있다.

IoC컨테이너 ( = DI컨테이너, 어셈블러, 오브젝트 팩토리 )

AppConfig처럼 의존 관계 주입을 해주고 제어 흐름을 담당하는 것을 의미한다.

스프링으로 전환하기

  • AppConfig는 @Configuration 이고 하나하나의 함수는 @Bean이 된다.
  • AppConfig를 사용하기 위해서는
ApplicationContext applicationContext =  new AnnotationConfigApplicationContext(AppConfig.class); 

MemberService memberService = applicationContext.getBean("memberService", MemberService.class); 
OrderService orderService = applicationContext.getBean("orderService", OrderService.class);

로 사용한다.

  • 기존에는 개발자가 직접 자바코드로 모든 것을 했다면 이제부터는 스프링 컨테이너에 객체를 스프링 빈으로 등록 하고, 스프링 컨테이너에서 스프링 빈을 찾아서 사용하도록 변경되었다.