• [인프런 김영한 로드맵2]스프링 핵심 원리 정리(2)

    2022. 1. 29.

    by. 웰시코더

    반응형

    -인프런 김영한 강사님의 스프링 핵심 원리를 정리한다.
    -모든 소스는 깃허브에서 관리한다.(https://github.com/coderahn/Spring-Lecture2)


    2.스프링 핵심 원리 이해1 - 예제 만들기

    지금까지 객체지향의 원리에 대한 전반적인 설명과 이 원리가 스프링과 어떤 연관성이 있고 스프링이 객체지향적으로 개발을 할 수 있게 해준다는 점을 언급하였다.

    이 파트에서는 프로젝트를 생성하고 회원 도메인 설계와 개발 및 테스트, 주문과 할인 도메인 설계, 개발 및 테스트를 진행한다. 순수한 자바코드로 진행한다.

    1)프로젝트 생성

    스프링 이니셜라이져 사이트(https://start.spring.io/)에서 프로젝트를 생성한다.

    다음과 같은 스펙으로 생성한다.

    • Project : Gradle Project
    • Language : Java
    • Spring Boot : 2.6.3(스냅샷버전은 개발중이거나 안전성이 좀 부족할 수 있기 때문에 이를 제외한 최신버전으로 선택)
    • Project Metadata 
      • Group : hello
      • Artifact : core
      • Name : core
      • Description : Demo project for Spring Boot
      • Package name : hello.core
      • Packaging : Jar
      • Java : 11
    • Dependencies : 추가 없음(순수한 자바 코드로 개발할 예정)

     

    참고로 인텔리제이 사용시 실제 실행하면 Gradle을 통해 실행하여 느리다. 다음과 같이 Settings에 들어가서 자바로 바로 실행되도록 변경해준다.(Mac의 경우 Preferences)

     

    Gradle proejcts에서 Build and run using과 Run tests using에 IntelliJ IDEA로 바꿔준다.


    2)비즈니스 요구사항과 설계

    '회원'과 '주문과 할인 정책'의 요구사항을 설계한다.

    회원은 가입, 조회 기능이 있고 등급은 일반, VIP 2가지가 있다. 회원 데이터는 자체 DB 구축을 할 수 있고 외부 시스템과 연동할 수 있는데 미확정이다.

    주문과 할인 정책에서는 회원이 상품을 주문할 수 있는데 등급에 따라 할인 정책이 적용된다. 모든 VIP는 1,000원 할인의 고정 할인을 적용한다. 이것은 추후 변경될 수 있다. 할인 정책은 추후 변경 가능성이 높다.

    전반적으로 지금 결정할 수 없는 사항들이 있다. DB를 자체로 쓸 것인지 외부 시스템을 쓸 것인지 등..
    그때까지 개발을 안 할 수는 없다. 객체지향 설계 방법을 활용하여 인터페이스를 만들고 구현체를 언제든지 갈아끼울 수 있도록 설계한다.

    3)회원 도메인 설계

    클라이언트가 회원 저장소를 사용할 때 자체 DB를 쓸지 외부시스템을 쓸지 알 수 없다고 했다. 회원 저장소를 인터페이스로 만들어 의존하면 OCP원칙을 지킬 수 있는 설계가 된다. 우선 예제는 메모리 회원 저장소부터 개발하도록 한다.

    다음의 김영한님 참고자료 그림을 참고한다.

     

     

    런타임시에는 회원 서비스(MemberServiceImpl)은 구현체인 MemoryMemberRepository에 의존하게 된다. 그리고 인텔리제이 오버라이드, getter and setter 단축키는 윈도우 기준 alt + enter이다.

    4)회원 도메인 개발 5)회원 도메인 실행과 테스트

    개발 후 테스트를 진행한다. 애플리케이션의 System.out.println()은 좋은 방법이 아니다. JUnit을 사용한다.

     

    테스트시에 given, when, then으로 습관을 들이자

     

    현재 회원 도메인은 다음과 같은 문제점을 갖고 있다.

     

    new MemoryMemberRepository()를 의존한다.


    위의 코드에서 클라이언트(MemberServiceImpl)은 인터페이스인 memberRepository를 의존하고 있다. 그러나 이 인터페이스의 구현체를 클라이언트에서 생성하고 있다. 추후 변경 발생시 클라이언트 코드가 변경된다. 즉, OCP원칙을 위배하게 된다. 또한 추상화에 의존해야 한다는 DIP원칙도 위배하게 된다.

     

    6)주문과 할인 도메인 설계

     

    회원이 상품을 주문할 수 있으며 회원 등급(일반, VIP)에 따라 할인 정책을 적용할 수 있다.

    현재 요구사항은 VIP는 1000원 고정 금액 할인이다. 이 정책은 변경 가능성이 높다고 가정한다.

     

    변경 가능성이 높은 요구사항은 항상 인터페이스로 역할부터 정의한 후 구현해간다. 고정금액할인으로 구현하고 추후 변동금액할인으로 구현한 다음 구현체를 바꿔 사용한다. 

     

     

    출처 : 김영한님 인프런 강의 자료

     

    출처 : 김영한님 인프런 강의 자료

     

     

    7)주문과 할인 도메인 개발

     

    주문 서비스 역할을 하는 OrderServiceImpl의 주문 메소드는 다음과 같다.

     

     

    위의 코드에서 알 수 있는 부분은 우선 memberRepository, discountPolicy에 의존하는 코드는 인터페이스뿐만 아니라 인스턴스 구현체 자체도 의존하기 떄문에 OCP에 위반한다. 그리고 createOrder()는 '회원조회 -> 할인적용 -> 주문결과 반환'이라는 기능을 담당한다. 각각 역할에 맞는 메소드들을 호출한다.

     

    추후 할인 적용을 바꾸고 싶으면 new FixDiscountPolicy()를 바꾸면 된다. 현재는 인스턴스에 직접 의존하여 OCP에 위반되지만, 스프링 컨테이너를 활용하게 되면 클라이언트(OrderServiceImpl)의 변경없이 구현체를 바꿔 사용할 수 있을 것이다.

     

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

     

    최종적인 테스트 코드는 '회원가입 진행 -> 주문생성 요청 -> 회원조회 -> 할인적용 -> 주문결과 반환'이다.

     

    다음과 같다.

     

     

    위의 테스트 메소드(createOrder())가 클라이언트 역할을 하고 주문 서비스에 주문 생성을 요청한다. 고정 할인 금액을 1000원 적용하여 VIP인경우 1,000원 할인 되기 때문에 isEqualTo(1000)으로 비교한다.

     

     

     

     

     

    반응형

    댓글