📕

[자바 객체 지향] Chapter 7. 스프링 삼각형과 설정 정보

작성일자
Sep 21, 2022
태그
SUB PAGE
프로젝트
자바 객체 지향
책 종류
본 게시글은 하단 책을 읽고 학습한 내용을 제 생각으로 요약, 정리한 글입니다.
목차

1. IoC/DI - 제어의 역전/의존성 주입

1) 프로그래밍에서 의존성이란?

  • 의사 코드로 살펴보는 의존성
    • 🚗
      운전자가 자동차를 생산한다. 자동차는 내부적으로 타이어를 생산한다.
    • 의존성 → 자동차(전체)가 타이어(부분)에 의존함
  • 의존성: A클래스가 B클래스의 객체를 생성해 사용하는 것.
    • A와 B는 의존 관계에 있다.
    • A는 B에 의존한다.
  • 의존성: 다른 객체를 참조하는 것 ⇒ 객체 참조 변수
 

2) 의존성을 직접 해결

  • 의존성 직접 해결 → 자동차 내부에서 타이어를 직접 생산
  • 의사 코드
    • 🚗
      운전자가 자동차를 생산해 사용한다. 자동차가 내부적으로 타이어를 생산해 사용한다.
  • 실제 코드 요약
    • Driver 클래스
      • Car 클래스
      • 실제 코드
        • Tire.java
          KoreaTire.java
          AmericaTire.java
          Car.javaTire를 생산하고 사용함: Car는 Tire에 의존함
          Driver.java Car를 생산하고 사용함: Driver는 Car에 의존함
          CarTest.java → Driver.java와 같은 역할
      • 문제점 & 해결책
        • 문제점
          • 특정 자동차가 생산될 때 “어떤 타이어를 생산해서 장착할까”를 자동차 스스로가 결정함.
          • 운전자는“어떤 자동차를 생산할지”만 결정 할 수 있고, 선택한 자동차에 “어떤 타이어를 장착할지” 는 결정할 수 없음(유연성 ↓)
        • 해결책
          • “어떤 타이어 장착할지”는 자동차가 아니라 운전자가 결정해야 함.
          • 운전자가 타이어를 생산함. 자동차는 운전자가 생산한 타이어를 건네받아 장착만 함.
          • 즉, 의존성을 내부에서 직접 해결하는 게 아니라, 외부에서 주입 받아 해결해야 함.
          •  

      3) 스프링 없이 의존성 주입 1 - 생성자를 통한 의존성 주입 (생성자의 인자 주입으로 의존성을 해결)

      • 의존성 주입 → 자동차 외부에서 생산된 타이어를 자동차에 장착
      • 생성자를 통한 의존성 주입 → 생성자의 인자를 통해 타이어 건네 받음.
      • 주입의 장점
        • Car는 KoreaTire, AmericaTire…등 몰라도 됨. Car는 Tire만 알면 됨.
        • 따라서 새로운 타이어 브랜드(ChinaTire…) 얼마든지 생겨도, Car는 알 필요도 없기에 코드를 변경할 필요 없음.(확장성 ↑)
      • 의사 코드
        • 🚗
          운전자가 타이어를 생산한다. 운전자가 자동차를 생산하면서 타이어를 장착한다.
        • 자동차는 외부(운전자)에서 생산한 타이어를 장착해 사용한다.
        • 단, 타이어 장착은 자동차를 생산하는 순간에만 이뤄질 수 있다. 추후 타이어 교체 불가.
      • 실제 코드 요약
        • Driver 클래스
        • 실제 코드
          • Car.javaTire를 주입 받아 사용함.
            Driver.java → Tire를 생산함. Car를 생산하면서 생산해둔 Tire를 주입시킴. Car를 사용함.
        • 문제점 & 해결책
          • 문제점
            • 자동차를 생산할 때 한 번 타이어를 장착하면 더 이상 타이어를 교체할 방법이 없음
          • 해결책
            • 운전자가 원할 때 자동차의 타이어 교체할 수 있어야 함.
            • 생성자가 아닌 속성을 통한 의존성 주입으로 해결해야 함.
            • 이를 통해 자동차 생산과 타이어 장착을 한 번에 하지 않고 따로 따로 할 수 있게 분리함.
            •  

        4) 스프링 없이 의존성 주입 2 - 속성을 통한 의존성 주입

        • 속성을 통한 의존성 주입 → 속성 접근자 메서드의 인자를 통해 타이어 건네 받음.
        • 의사 코드
          • 🚗
            운전자가 타이어를 생산한다. 운전자가 자동차를 생산한다. 운전자가 자동차에 타이어를 장착한다.
        • 실제 코드 요약
          • Driver 클래스
          • 실제 코드
            • Car.javaTire를 주입 받아 사용함.
              Driver.java → Tire를 생산함. Car를 생산함. Car에 생산해둔 Tire를 주입시킴. Car를 사용함.
          • 문제점 & 해결책
            • 문제점
              • 타이어 종류 바꾸려면 운전자 코드가 바뀌어야 함.
            • 해결책
              • 종합쇼핑몰 같은 곳에서 타이어를 구매해오는 형태라면 타이어 바꿀 때 종합쇼핑몰에서 구매하는 타이어의 종류만 바꾸면 되므로 종합쇼핑몰의 코드만 바뀌면 됨.
              •  

          5) 스프링을 통한 의존성 주입 - XML 파일 사용

          • XML 파일 사용한 의존성 주입 → 종합 쇼핑몰(스프링 프레임워크)에서 생산된 타이어를 구매해 자동차에 장착
          • 의사 코드
            • 🚗
              운전자가 종합 쇼핑몰에서 타이어를 구매한다. 운전자가 종합 쇼핑몰에서 자동차를 구매한다. 운전자가 자동차에 타이어를 장착한다.
          • 실제 코드 요약
            • Driver 클래스
            • 실제 코드
              • Car.javaTire를 주입 받아 사용함. - 변동 없음
                Driver.java → 쇼핑몰에서 Tire와 Car를 구매함. Car에 Tire를 주입시킴. Car를 사용함.
                expert002.xml → Tire와 Car 상품을 쇼핑몰에 등록함
            • 문제점 & 해결책
              • 문제점
                • 운전자는 쇼핑몰에서 car와 tire를 사와서 car에 tire를 장착하는데,
                • 쇼핑몰에서 파는 tire는 한 종류(KoreaTire)밖에 없음.
              • 해결책
                • 쇼핑몰에서 tire를 장착한 car를 팔면 됨. 쇼핑몰 내엔 여러 tire 있으니 americaTire, koreaTire 등 여러 종류 타이어 장착 가능.
                 

            6) 스프링을 통한 의존성 주입 - 스프링 설정 파일(XML)에서 속성 주입

            • XML 파일에서 속성 주입 → 종합 쇼핑몰에서 타이어가 장착되어 판매되는 차를 구매해 사용
            • 의사 코드
              • 🚗
                운전자가 종합 쇼핑몰에서 자동차를 구매 요청한다. 종합 쇼핑몰은 자동차를 생산한다. 종합 쇼핑몰은 타이어를 생산한다. 종합 쇼핑몰은 자동차에 타이어를 장착한다. 종합 쇼핑몰은 운전자에게 자동차를 전달한다.
            • 실제 코드 요약
              • Driver 클래스
                • XML
                • 실제 코드
                  • Car.javaTire를 주입 받아 사용함. - 변동 없음
                    Driver.java → 쇼핑몰에서 Car를 구매함. Car를 사용함.
                    expert002.xml → Tire와 Car 상품을 쇼핑몰에 등록함. Car에 Tire를 주입시킴
                 

                7) 스프링을 통한 의존성 주입 - @Autowired를 통한 속성 주입

                • @Autowired를 통한 속성 주입 →
                • 의사 코드 (이전과 동일)
                  • 🚗
                    운전자가 종합 쇼핑몰에서 자동차를 구매 요청한다. 종합 쇼핑몰은 자동차를 생산한다. 종합 쇼핑몰은 타이어를 생산한다. 종합 쇼핑몰은 자동차에 타이어를 장착한다. 종합 쇼핑몰은 운전자에게 자동차를 전달한다.
                     

                2. AOP - Aspect? 관점? 핵심 관심사? 횡단 관심사?

                1) 스프링에서 AOP란?

                • 정의)
                  • 공통 관심 사항(cross-cutting concern)과 핵심 관심 사항(core concern) 분리한 후, 분리한 공통 관심 사항을 원하는 곳에 적용
                    • 자바의 AOP 구현체: AspectJ, 스프링 AOP
                  • 관점 지향 프로그래밍(Aspect-oriented Programming)
                    • 어떤 로직을 기준으로 관점으로 나누어 보고, 그 관점을 기준으로 각각 모듈화하는 프로그래밍 기법
                    • ex) 그림 - 공통 관심사를 모듈로 분리한 후, 후에 원하는 곳에 공통관심사를 적용함
                      notion image
                      • 여러 클래스, 메서드에 걸쳐서 나타나는 비슷한 코드들(노랑, 파랑, 빨강)이 각 관점의 관심사임
                      • 관심사(노랑, 파랑, 빨강 코드)를 관점(X, Y, Z) 별로 모듈화함
                      • 후에 이를 핵심적인 비즈니스 로직에서 재사용함
                • 용어)
                  • Concern
                    • 관심사
                    • 코드 = 공통 관심사(횡단 관심사) + 핵심 관심사
                  • Aspect
                    • 관점
                    • 흩어진 공통 관심사를 묶어서 모듈화한 하나의 모듈
                    • Aspect = Point Cut들 + Advice들
                  • Target
                    • Aspect가 가지고 있는 Advice가 적용되는 대상(클래스, 메서드)
                  • Point Cut
                    • Aspect 적용 위치 지정자
                    • 스프링 → 공통 관심사를 적용할 타깃 클래스의 타깃 메서드 지정자
                  • Join Point
                    • Aspect 적용이 가능한(Point cut의 후보가 되는) 모든 지점
                    • Join Point Point cut
                  • Advice
                    • 조언, 충고
                    • Pointcut에 언제, 무엇을 적용할지 정의한 메서드
                • 장점)
                  • 핵심 관심사항과 공통 관심 사항을 분리함
                    • 핵심 관심 사항을 깔끔하게 유지할 수 있음.
                    • 원하는 적용 대상을 선택할 수 있음
                    • 변경이 필요하면 공통 로직 하나만 변경하면 됨
                      • 단일 책임 원칙 적용

                2) AOP가 필요한 상황

                • 예시
                  • 상황) 모든 메서드의 호출 시간을 측정하고 싶음
                  • 코드) 각 메서드에 시간 측정 코드 넣음
                  • 문제)
                    • 회원 가입, 회원 조회에 시간을 측정하는 기능은 핵심 관심 사항이 아님
                    • 시간을 측정하는 로직은 공통 관심 사항임.
                    • 시간을 측정하는 로직과 핵심 비즈니스 로직이 섞여 있어 유지 보수가 어려움
                    • 시간을 측정하는 로직을 별도의 공통 로직으로 만들기 매우 어려움
                    • 시간을 측정하는 로직을 변경할 때 모든 로직을 찾아가면서 변경해야 함
                  • 해결) AOP(Aspect Oriented Programming) 사용
                    • 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern) 분리

                3) AOP 적용

                1. AOP 패키지 만들기 hello.hellospring.aop
                1. TimeTraceAop 클래스 만들기
                  1. TimeTraceAop.java
                1. @Aspect 붙이기
                    • 에러) @Aspect 임포트가 안됨
                    • 해결)
                      • aop 의존성 추가하기 위해 build gradle에 implementation 'org.springframework.boot:spring-boot-starter-aop' 추가
                      • 추가하고 build.gradle을 수정한 후 reload버튼을 클릭
                        • reload 버튼 위치
                          build.gradle 수정 후 좌측에 Gradle 창 열면 코드 좌측 상단에 자동으로 함께 뜸
                          notion image
                1. 코드 작성
                  1. main/java/hello.hellospring.aop/TimeTraceAop.java
                1. 스프링 빈으로 등록하기
                  1. 1) @Component 붙여서 컴포넌트 스캔
                    main/java/hello.hellospring.aop/TimeTraceAop.java
                    2) 스프링 빈에 등록해서 쓰기
                    main/java/hello.hellospring/SpringConfig
                1. 공통 관심사를 어디에 적용할지 타겟팅 @Around
                  1. main/java/hello.hellospring.aop/TimeTraceAop.java
                    • 적용 대상 변경
                      • ex) service에만 적용
                        • @Around("execution(* hello.hellospring.service..*(..))")
                1. 기존에 적어둔 시간 측정 코드 주석 처리하고 원래대로 되돌리기
                  1. main/java/hello.hellospring.service/MemberService.jav
                1. 회원 목록 들어가서 시간 측정 결과 확인
                  1. 터미널 (전체 적용)
                    터미널 (service만 적용)
                     
                [자바 객체 지향] Chapter 7. 스프링 삼각형과 설정 정보