스프링 AOP의 문제점 및 한계
·
Study/Spring
스프링은 프록시 방식의 AOP를 사용하기 때문에 AOP를 적용하려면 항상 프록시를 통해서 대상 객체(Target)을 호출해야 한다. 스프링은 의존관계 주입 시에 프록시 객체를 주입하여 대상 객체 대신에 프록시를 스프링 빈으로 등록하여 적용할 수 있다. 여기서 문제가 발생하는데 대상 객체의 내부에서 메서드 호출이 발생하면 프록시를 거치지 않고 대상 객체를 직접 호출하는 문제가 발생한다. 즉, 부가 기능이 적용되지 않게 된다. 문제 발생 import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @Slf4j @Component public class CallServiceV0 { public void external() ..
AOP (Aspect - Oriented Programming)와 @Aspect
·
Study/Spring
AOP 애스펙트를 사용한 프로그래밍 방식을 관점 지향 프로그래밍 AOP(Aspect-Oriented Programming)이라 한다. 참고로 AOP는 OOP를 대체하기 위한 것이 아니라 횡단 관심사를 깔끔하게 처리하기 어려운 OOP의 부족한 부분을 보조하는 목적으로 개발되었다. 횡단 관심사: 여러 기능들 사이에 걸쳐서 들어가는 관심사 AspectJ 프레임워크 AOP의 대표적인 구현으로 스프링도 AOP를 지원하지만 대부분 AspectJ의 문법을 차용하고 AspectJ가 제공하는 일부 기능만 제공한다. 기능 횡단 관심사의 깔끔한 모듈화 오류 검사 및 처리 동기화 성능 최적화(캐싱) 모니터링 및 로깅 AOP를 적용 방식 크게 3가지 (컴파일 시점, 클래스 로딩 시점, 런타임 시점)으로 나뉘는데, 런타임 시점이..
빈 후처리기(Bean PostProcessor)와 어드바이저
·
Study/Spring
빈 후처리기 스프링이 빈 저장소에 등록할 목적으로 생성한 객체를 빈 저장소에 등록하기 직전에 조작할 때 사용한다. 이름 그대로 빈을 생성한 후에 무언가를 처리하는 용도로 사용한다 기능 객체 조작 객체 바꿔치기 구현 BeanPostProcessor을 구현하고 빈으로 등록하면 된다. 다음은 beanA를 등록했지만 beanB로 바꿔치기 하는 예제 코드이다. 분명 A클래스의 빈 이름이 beanA로 등록되어 있지만 결과는 getBean을 통해 beanA를 조회하면 B로 반환되고, A 클래스의 빈은 조회되지 않음을 확인할 수 있다. public class BeanPostProcessorTest { @Test void postProcessor() { ApplicationContext applicationContext..
리플렉션과 프록시 팩토리
·
Study/Spring
리플렉션 프록시를 사용하면 기존 코드를 수정하지 않고 부가 기능을 추가할 수 있다. 그치만 모든 클래스마다 프록시 클래스를 만드는 것은 비효율적일 것이다. 자바에서는 JDK 동적 프록시 기술이나 CGLIB 같은 오픈소스 기술을 활용하여 동적으로 프록시를 생성할 수 있는데 이때 사용하는 것이 리플렉션이라고 한다. 리플렉션은 클래스나 메서드의 메타정보를 사용해서 동적으로 호출하는 메소드를 변경할 수 있다. 다음 예시를 살펴보자. 다음 메소드의 호출 결과를 출력하고자 할 때 공통 로직을 처리하기 위한 리플렉션 코드이다. @Slf4j static class Hello { public String callA() { log.info("callA"); return "A"; } public String callB() ..
데코레이터 패턴 - 로그 추적기 적용 (3)
·
Study/Design Pattern
데코레이터 패턴에 대한 설명은 이전 글을 참고 간단히 프록시 클래스를 만들어 실제 호출을 하는 target을 설정하고 그 안에서 기능을 추가할 것이다. 코드는 크게 인터페이스 기반 프록시, 실제 구현 클래스 기반 프록시로 나뉜다. 인터페이스 기반 프록시 인터페이스 기반이기 때문에 Controller, Service, Repository가 다음과 같이인터페이스를 통해 구현되어 있다. 따라서 구현하고자 하는 의존 관계는 다음과 같다. 데코레이터 패턴을 적용하기 위해서 프록시 컨트롤러에서 실제 구체 클래스(OrderControllerV1 target)를 포함하고 있다. 부가 기능을 위한 로그 추적기 LogTrace 또한 추가해주었다. @RequiredArgsConstructor public class Orde..
프록시 패턴과 데코레이터 패턴
·
Study/OOP
두 패턴 모두 프록시를 활용한 디자인 패턴이다. 디자인 패턴은 구분하는 기준은 '의도'에 의해 구분되기 때문에 비슷하게 구현되는 패턴들이 많다. 이 두 패턴도 그러한 유형이다. 그럼 프록시 패턴과, 데이코레이터의 패턴의 의도를 알아보기 전에 프록시란 무엇인지 부터 알아보자. 프록시, Proxy 그대로 번역하면 '대리자'라는 뜻을 가진다. 웹은 기본적으로 Client -> Server 로 호출을 한다. 프록시를 활용하게 되면 Client -> Proxy -> Server로 중간에 대리자를 끼게 된다. 중간에는 꼭 하나의 프록시만 존재할 수 있는 것은 아니다. 경우에 따라 여러 개의 프록시가 존재할 수 있다. 그렇다면 프록시가 될 수 있는 조건은 무엇일까? 조건 객체에서 프록시가 되려면, 클라이언트는 서버에..
템플릿 콜백 패턴(전략 패턴) - 로그 추적기 적용 (2)
·
Study/Design Pattern
템플릿 메소드 패턴은 공통부분을 템플릿으로 만들어 부모 클래스에서 다루고 변경되는 부분을 자식 클래스에서 다루는 디자인 패턴이다. 따라서 상속에서 오는 단점을 그대로 가져오기 때문에 이런 단점을 해결한 전략 패턴을 도입할 예정이다. 템플릿 메소드 패턴과 전략 패턴은 GOF 디자인 패턴에 포함되지만 템플릿 콜백 패턴은 전략 패턴을 활용했을 뿐 GOF 패턴은 아니다. 단순히 전략 패턴에서 템플릿과 콜백 패턴이 강조되었고 스프링 내부에서 자주 사용되기 때문에 템플릿 콜백 패턴이라고 불려진다. 스프링에서는 JdbcTemplate , RestTemplate , TransactionTemplate , RedisTemplate 처럼 다양한 템플릿 콜백 패턴이 사용된다. 스프링에서 이름에 XxxTemplate 가 있다..
템플릿 메소드 - 로그 추적기 적용 (1)
·
Study/Design Pattern
순수 자바로 로그 추적기를 개발하며 공부하던 중 최적화를 위해 템플릿 메소드를 적용해 보았다. 적용하기 전 템플릿 메소드에 대해 먼저 알아보자. 템플릿 메소드 패턴 작업에서 알고리즘의 골격을 정의하고 일부 단계를 하위 클래스로 연기함으로써 하위 클래스가 알고리즘의 구조를 변경하지 않고도 알고리즘의 특정 단계를 재정의할 수 있다. - GOF 디자인 패턴 즉, 부모 클래스에서 알고리즘의 골격인 템플릿을 정의하고, 일부 변경되는 로직은 자식 클래스에 정의함으로써 자식 클래스가 알고리즘의 전체 구조를 변경하지 않고, 특정 부분만 재정의할 수 있도록 상속과 오버라이딩을 통한 다형성으로 문제를 해결하는 것이다. 적용 - 로그 추적기 템플릿 클래스 로그 추적기를 적용하기 위해 부모 클래스이자 추상 클래스이다. 각 레..
[JPA] OSIV를 활용한 성능 최적화
·
Study/JPA
OSIV Open Session In View - 하이버네이트 Open EntityManager In View - JPA JPA 표준 이전에 하이버네이트를 사용해와서 관례상 OSIV라고 부른다. 스프링에서는 spring.jpa.open-in-view를 통해 설정할 수 있다. Open EntityManager In View 말 그대로 View 레벨에서 EntityManager를 open 열어두겠다. = 사용하겠다. 라는 의미이다. EntityManager : 영속성 컨텍스트 영속성 컨텍스트는 DB와 통신하며 데이터를 주고 받는다. 따라서 영속성 컨텍스트는 기본적으로 트랙잭션 범위 안에서 사용해야 하지만 Contoller, View 단에서도 사용할 수 있도록 영속성 컨텍스트 범위를 늘려주는 것이 바로 Ope..
[JPA] xToMany 성능 최적화
·
Study/JPA
이전 포스팅에서 4개의 연관필드들을 join fetch를 통해 한방 쿼리로 가져와 늘어난 row를 distinct까지 적용시켜 원하는 결과를 얻어보았다. 결미부분에서 언급한 이 방법의 문제점과 해결방법 및 성능 최적화에 대해 알아보는 포스팅을 작성하려고 한다. 이전 포스팅(xToOne 성능 최적화) 부분은 관심 없을 수 있으니 간단히 도메인 설명을 추가한다. 현재 사용하는 도메인이고 Order를 조회하며 연관 필드인 Member, Delivery, OrderItem, (추가로 Item)까지 조회하는 쿼리를 진행한다. 당연히 연관관계 OneToMany, ManyToOne 등의 연관관계를 위주로 살펴보자. 바로 결론으로 문제점을 확인해보자. 문제점 모두 join fetch를 통해 한방쿼리로 모두 가져오면 발..