Spring 44

[Spring] 동적 프록시의 추상화, ProxyFactory

1. ProxyFactory 스프링은 항상 비슷한 기능들을 묶어 *추상화*해 관리한다. 인터페이스 기반의 프록시 기술인 `JDK 동적 프록시`, 클래스 기반의 프록시 기술인 `CGLIB`를 생각해보자. 모든 경우에 항상 인터페이스 기반의 프록시만 필요하거나, 클래스 기반의 프록시만 필요할 수 없다. 따라서 스프링은 이 문제를 해결하기 위해 `ProxyFactory`라는 추상화된 개념을 도입한다. 이제 동적 프록시를 얻으려면 `ProxyFactory에 접근하면된다. 다만, 남은 문제가 있다. JDK 동적 프록시, CGLIB 중 어떤 기술을 사용할 지 모르니 `InvocationHandler`와 `MethodInterceptor`를 둘 다 만들어놔야하지 않는가? 이는 중복이다. 스프링은 이 문제를 어떻게 해..

Spring 2024.03.06

[Spring] 동적 프록시(JDK Dynamic Proxy, CGLIB)

1. 개요 이전 포스팅에서 직접 프록시를 생성하면서 원본 코드에 영향을 주지 않고 부가 기능을 수행할 수 있도록 공부해봤다. 하지만 프록시를 적용해야하는 클래스가 수백개로 늘어난다면, 프록시 클래스를 그에 맞게 생성해줘야하는 번거로움이 존재했다. 이번 시간에는 단 하나의 클래스를 생성해 모든 클래스에 프록시를 적용할 수 있는 *동적 프록시 기술*에 대해 알아볼 것이다. 참고로 동적 프록시 기술은 런타임에 동적으로 클래스 및 메서드를 생성하기 때문에 *리플렉션*을 활용한다. 본 포스팅에서는 리플렉션에 대해서 자세히 다루지는 않는다. 2. JDK 동적 프록시 JDK 동적 프록시는 자바 언어에서 기본으로 제공하는 기능이다. *주로 인터페이스 기반의 동적 프록시 생성에 사용된다.* * 후에 기술할 CGLIB가 ..

Spring 2024.03.05

[Spring] 프록시 패턴과 데코레이터 패턴

1. 프록시 - 소개 프록시라는 개념은 상당히 넓게 사용된다. 일반적으로 클라이언트와 서버 또한 좁게 봤을 때는 하나의 애플리케이션 내에서 객체 간의 상호작용으로 볼 수 도 있고, 넓게 보면 웹 브라우저와 API 서버를 의미할 수 도 있다. 프록시는 클라이언트가 요청한 결과를 서버에 직접 요청하는 것이 아니라 어떤 *대리자*를 통해서 간접적으로 요청할 수 있도록 하는 것이다. 여기서 프록시는 대리자를 의미한다. 음 그러면 아무나 프록시가 될 수 있나? 생각해보면 아니다. 클라이언트 입장에서는 서버에 요청한 것인지, 대리자인 프록시에게 요청한 것인지 모르고 원하는 결과를 받아야한다. 쉽게 이야기하면 프록시와 서버는 *같은 인터페이스*를 사용하거나 *상속 관계*에 있어야 한다는 것이다. 따라서 *DI*를 사..

Spring 2024.03.04

[Spring] 스프링의 템플릿 콜백 패턴

1. 소개 스프링을 사용한다면 JdbcTemplate, RedisTemplate 등 `XXXTemplate`에 대한 단어를 접해봤을 것이다. 이는 모두 *템플릿 콜백 패턴*이라는 디자인 패턴을 사용한 기술들이다. 템플릿 콜백 패턴 자체가 GOF에서 소개하는 디자인 패턴은 아니지만, 스프링에서 나름대로 입맛에 맞게 재정의한 디자인 패턴이라고 보면 된다. 예시로 들었던 JdbcTemplate, RedisTemplate 처럼, 스프링의 많은 기술은 템플릿 콜백 패턴을 통해 핵심 비지니스 로직과 부가적인 기능을 분리한다. 템플릿 콜백 패턴이 어떻게 등장하게 되었는가를 보다 쉽게 이해하기 위해서 연관성이 있는 *템플릿 메서드 패턴*과 *전략 패턴*에 대해 먼저 알아보며 시작해보자. 우선 현재 예제 프로젝트의 문제..

Spring 2024.03.03

[Spring] 필드 동기화와 ThreadLocal

1. 문제 상황 - 예제와 요구사항 본 예제는 일반적인 스프링 애플리케이션 상황을 기반으로 구성되며 아래와 같은 요구사항이 추가되어 개발 중인 상황이다. 모든 public 메서드의 호출과 응답 정보를 로그로 출력 애플리케이션의 흐름을 변경하면 안된다. 로그를 남긴다고 해서 비지니스 로직의 동작에 영향을 주면 안된다. 메서드 호출에 걸린 시간 출력 정상 흐름과 예외 흐름을 구분 예외 발생 시 예외 정보가 남아야 한다. HTTP 요청을 구분 트랜잭션 ID를 생성해 하나의 HTTP 요청을 구분해야 한다. - 현재 상황 현재 위 요구사항을 만족하는 가장 Low한 버전의 로그 추적기가 완성된 상태이다. HTTP 요청의 트랜잭션 ID를 `Controller` 부터 `Repository`까지 동기화 시키고 호출의 d..

Spring 2024.03.01

[Spring] 스프링 트랜잭션 전파(Propagation)

1. 트랜잭션 전파 - 트랜잭션 전파란? 이전까지 스프링 트랜잭션에 관해 내부 원리와 함께 깊이 있는 학습을 했다. 이번에는 좀 더 나아가 *만약 하나의 트랜잭션 안에 또 다른 트랜잭션을 진행*한다면 어떻게 처리해야하는지, 즉 트랜잭션 전파가 어떻게 이뤄지는지 알아볼 것이다. 내용을 학습하기 전, 미리 짐작해봤을 때 다양한 상황이 존재할 것 같았다. 모든 트랜잭션이 성공해야만 커밋으로 인정할까? 성공한 트랜잭션은 커밋하고, 실패한 트랜잭션은 따로 롤백할까? (이 경우가 쓰일까..?) - 스프링의 기본 설정 스프링 트랜잭션에서 따로 전파(propagation)설정을 하지 않으면 `REQUIRED`모드로 작동한다. 이는 모든 트랜잭션이 커밋되어야 최종 트랜잭션이 커밋되고, 하나의 트랜잭션이라도 롤백된다면 최..

Spring 2024.02.28

[Spring] @Transactional의 다양한 기능과 주의사항

1. 트랜잭션 적용 여부 확인 `@Transactional`은 AOP를 통해 트랜잭션을 처리하도록 도와준다. 따라서 순수한 비지니스 로직만 남길 수 있다는 장점을 가져왔다. 하지만 반대로, 트랜잭션 관련 코드가 없기 때문에 실제로 트랜잭션이 잘 적용되고 있는건지 확인하기 어렵다. 간단하게 트랜잭션 적용 여부를 확인하는 방법에 대해 알아보자. static class BasicService { @Transactional public void tx() { log.info("call tx"); boolean txActive = TransactionSynchronizationManager.isActualTransactionActive(); log.info("tx active={}", txActive); } pub..

Spring 2024.02.27

[Spring] 스프링의 RuntimeException 추상화

이전 포스팅에서 체크 예외는 되도록이면 언체크 예외로 변환해 던져야 한다는 것을 배웠다. 실제 코드로 적용해보고, 나아가 스프링의 이런 RuntimeException 추상화에 대해 알아보자. 커스텀 런타임 예외 적용 우선 기존 서비스 계층으로 올라오는 JDBC 기술 관련 체크 예외인 SQLException을 처리하기 위해 런타임 예외를 하나 생성하자. public class MyDbException extends RuntimeException{ public MyDbException() { } public MyDbException(String message) { super(message); } public MyDbException(String message, Throwable cause) { super(m..

Spring 2023.12.18

[Spring] 자바 예외 계층 이해

각 계층 간 종속적으로 올라오는 예외를 처리하기 위해서는 예외 또한 추상화가 필요하다. 실제로 스프링이 어떻게 예외 추상화를 제공하는지 이해하기 전에 먼저 말하자면 *예외는 자바 기본 문법이다.* 예외 계층에 대해 다시 한 번 복습하고, 실무에서는 예외를 어떻게 활용하는지 알아보자. 예외 계층 자바의 예외 계층 구조를 살펴보자. Thorwable : 최상위 예외이다. Error : 애플리케이션에서 복구 불가능한 수준의 시스템 예외이다. 개발자가 이 예외를 잡으려고 신경쓰면 안된다. Exception : 체크 예외이다. 애플리케이션에서 다루는 실질적인 최상위 예외 계층이다. Exception을 포함한 그 하위 예외는 체크 예외로, 컴파일러가 체크해주는 예외이다. RuntimeException 만 예외적으로..

Spring 2023.12.16

[Spring] 스프링의 트랜잭션 기술

이전 포스팅과 이어지는 내용입니다. https://dong-woo.tistory.com/148 [Spring] 트랜잭션에 대한 이해와 과거의 활용 데이터를 저장할 때 단순 파일에 저장해도 되지만 현대의 웹 애플리케이션은 왜 데이터베이스에 저장할까? 이는 데이터베이스가 트랜잭션이라는 개념을 지원하기 때문이다. 현대의 우리는 스 dong-woo.tistory.com 직접 구현한 트랜잭션의 문제점 이전 포스팅에서는 커넥션을 파라미터로 넘겨, 직접 트랜잭션을 구현했다. 하지만 현재 단계는 문제점이 상당히 많다. 트랜잭션 관련 문제 만약 JDBC에서 JPA로 데이터 접근 기술을 변경한다면 서비스 계층의 트랜잭션 코드도 변경되어야 한다. 커넥션을 동기화하기 위해서 파라미터로 계속 커넥션을 넘겨준다. 서비스 계층이 ..

Spring 2023.12.16