부트캠프 온보딩 강의

1. 데이터의 이동 배열을 이용하라

   (1) 배열 : 한개가 아닌 여러개의 데이터를 묶어서 관리하는 자료형

   (2) int[] a = new int[3]

      ① 배열도 객체처럼 먼저 new int[3]으로 메모리에 배열 공간을 만든다

      ② 그 주소를 a에 저장한다

   (3) 객체배열 : Book[] books = new Book[3]

      ① 메모리에 Book의 주소를 저장할 수 있는 배열 공간을 만든다

      ② 그 주소를 books에 저장한다

      ③ 배열 각각 하나의 공간에 새로운 Book을 만들어서 주소를 저장한다

   (4) 배열의 장점

      ① index를 이용해서 반복문을 사용하기 편리하다

      ② 데이터를 배열로 묶어서 이동하기에 편리하다

   (5) 2차원 배열 : int[][] a = new int[3][5]

      ① 메모리에 int배열(int[])의 주소를 저정할 수 있는 공간을 3개 만든다

      ② 그 공간의 주소를 a에 저장한다

      ③ 5개짜리 int배열을 만들고 각각의 공간에 그 주소를 저장한다

 

2. 논리적인 사고력 키우기 훈련

-> 반복문, 제어문 등등 이미 아는 부분이어서 확인하는 용도로 강의를 들었음


스프링 핵심 원리 고급편 (김영한 강의) - 섹션 4 : 프록시 패턴과 데코레이터 패턴

섹션 목적 : 프록시 패턴과 데코레이터 패턴을 알아보고 적용시켜, 새로운 요구사항을 만족시켜보자

 

1. 예제 프로젝트 만들기

   (1) v1 : 인터페이스와 구현 클래스 -> 스프링빈으로 수동 등록

   (2) v2 : 인터페이스 없는 구체 클래스 -> 스프링빈으로 수동 등록

   (3) v3 : 컴포넌트 스캔으로 스프링빈 자동 등록

 

2. 요구사항 추가

   (1) "원본 코드는 전혀 수정하지 않고, 로그 추적기를 적용하라"

   (2) 이 문제를 해결하려면 먼저 프록시 개념을 이해해야함

 

3. 프록시, 프록시 패턴, 데코레이터 패턴 - 소개

   (1) 클라이언트 : 서버에 필요한 것을 요청

   (2) 서버 : 클라이언트의 요청을 처리

   (3) 일반적으로 클라이언트가 서버를 직접 호출하고 처리 결과를 받음

   (4) 그런데 서버에 직접 요청하는 것이 아닌 '대리자'를 통해서 요청할 수 있음

   (5) 여기서 이 대리자를 '프록시'라 함

   (6) 대리자가 중간에 들어와서 여러가지 이점이 있다. 예시를 보자

      ① 엄마에게 라면을 부탁 -> 집에 이미 있음 -> 빠르게 라면을 먹음 => 접근제어, 캐싱

      ② 아빠에게 주유 부탁 -> 세차까지 해줌 => 부가기능 추가

      ③ 동생에게 라면 부탁 -> 동생은 또 동생에게 부탁 => 프록시 체인

   (7) 아무 객체나 프록시가 될 수 있는것 같지만, 객체에서 프록시가 되려면 클라는 서버에 요청한 것인지 프록시에 요청한 것인지 몰라야 함

   (8) 쉽게 말해서 서버와 프록시는 같은 인터페이스 또는 같은 조상이어야 함

   (9) 그리고 클라는 사용하는 서버 객체를 프록시로 변경해도 클라 코드는 변경하지 않고 동작해야함

   (10) 프록시의 주요 기능

      ① 접근제어 : 권한에 따른 접근 제한, 캐싱, 지연로딩

      ② 부가기능 추가 : 서버가 제공하는 기능에 더해 부가기능을 추가할 수 있음(ex. 로그추적기)

   (11) 프록시 패턴과 데코레이터 패턴은 둘 다 프록시를 사용하고 코드도 비슷하다

   (12) GOF 패턴에서 이 둘을 사용 의도에 따라 구분한다

      ① 프록시 패턴 : 접근 제어가 목적

      ② 데코레이터 패턴 : 새로운 기능 추가가 목적

 

4. 프록시 패턴

   (1) Client와 Subject interface, 이를 구현한 RealSubject가 있다고 하자

   (2) 그리고 RealSubject는 1초나 걸리는 시스템에 큰 부하를 주는 데이터 조회라고 가정

   (3) 프록시를 적용하지 않으면 각 호출은 모두 1초가 걸린다(3번 호출 -> 3초)

   (4) 프록시를 통해서 캐시를 적용시켜 성능을 개선해보자

   (5) 프록시 객체는 Subject interface를 구현하고, 필드로 Subject와 cache를 갖고 있다. 여기서 Subject에는 실제 구현 객체를 주입받고, cache는 캐싱 데이터이다

   (6) 프록시 객체의 interface 메소드는 캐시에 있는지 확인하고 있으면 캐시를 내보내고 없으면 실제 객체를 동작하는 메소드 이다

   (7) 따라서, 사용할 때 프록시 객체에 실제 객체를 주입하고, 클라이언트에 프록시 객체를 주입해서 사용한다

   (8) 이렇게할 경우, 클라이언트는 코드의 변경 없이 프록시를 자유롭게 사용할 수 있다

 

5. 데코레이터 패턴

   (1) 프록시 패턴과 코드의 모양은 동일하다

   (2) 실제 객체의 interface를 구현하고 실 객체를 주입받아서 이것저것 부가기능을 한 후 실객체의 로직을 실행하는 방법이다

   (3) 프록시를 체인처럼 사용이 가능하다. 프록시 안에 프록시를 넣고 체인처럼 이어가는 방식이다

   (4) 프록시와 데코레이터 패턴은 앞서 본 것처럼 '사용의도'에 따라 구분한다

 

6. V1에 프록시 적용

   (1) Controller, Service, Repository interface를 구현해서 프록시 객체를 만든다

   (2) 이 후 프록시 안에 실 객체를 target 필드로 만든다

   (3) interface 구현 로직에 로그를 찍고 -> target.XXX() -> 로그 찍기를 넣는다

   (4) 이 후 의존관계 설정에서 실제 객체가 아닌 프록시를 스프링 빈으로 등록한다

   (5) 프록시 안에 실제 객체를 주입하고, 실제 객체에는 프록시를 주입하는 방식으로 구현한다

   (6) 너무 많은 프록시 클래스를 생성해야하지만 나중에 해결하도록 하자

 

7. V2에 프록시 적용

   (1) Controller, Service, Repository 구체 클래스를 상속받아서 프록시 객체를 만든다

   (2) 이 후 똑같이 프록시 안에 실 객체를 target 필드로 만든다

   (3) 여기서 단점은 부모 클래서의 생성자를 사용하지 않는데 자바 규칙때문에 호출해야한다는 점이다. super(null)로 부모 생성자를 호출한다

   (4) V1과 같이 부모 로직을 overriding해서 로그를 찍고 -> target.XXX() -> 로그 찍기를 넣는다

   (5) 의존관계 설정은 V1과 같다

   (6) 위 두가지 방법으로 기존 코드 변경없이 로그 추적기를 적용했다. 하지만 너무 많은 프록시 클래스를 만들어야 한다. 어떻게 해결할까?


오늘 하루도 고생 많았다!!!

'TIL(Today I Learned)' 카테고리의 다른 글

2023.07.10  (0) 2023.07.10
2023.07.08  (1) 2023.07.10
2023.07.06  (0) 2023.07.06
2023.07.05  (0) 2023.07.05
2023.07.04  (0) 2023.07.04

+ Recent posts