1. 배경 : 유연하게 분산락 키 값 설정하기
Redisson library 를 기반으로 분산락을 custom annotation(@DistributedLock) 을 조인 포인트로 설정해 분산락 에스펙트를 구현하고 있었다. 분산락을 적용할 때 키 값이 필요한데, 유연한 키 값 적용을 위해 Spel(Spring Expression Language) 을 적용했다.
@DistributedLock 의 옵션에 적혀있는 Spel 을 파싱한 내용을 토대로 메서드 아규먼트(method arguemnt) 를 전달해서 분산락 키를 설정하려고 했다.
2. 문제 : 조인포인트 파라미터 값이 null 이 반환된다?
그런데 joinPoint 에서 메서드 아규먼트를 주입하는 과정에서 계속해서 에러가 발생했다. joinpoint.getSigniture() 부분을 디버깅해보니 파라미터 이름이 전달되지 않고 null 을 반환했다. 이전에 한번 적용했던 경험이 있는데 Spring 5 버전에서는 (Spring Boot 2.x) 발생하지 않았다. 이전과의 차이점은 스프링 버전이었다. 해답은 SpringFramework 6.1 Release Notes 에서 있었다.
3. 원인 : Spring 6.1 부터 Parameter Name Retention 변경됐다.
Spring 6.1 버전부터 더 이상 바이트코드를 파싱하여 매개변수 이름을 추론하려고 시도하지 않는다.
이전 버전의 Spring 은 LocalVariableTableParameterNameDiscover 이라는 구현체에서 컴파일된 .class 파일의 LocalVariableTable 라는 공간에서 메서드 파라미터 이름을 조회했다.
하지만, Spring 6.1 버전부터 StandardReflectionParameterNameDiscoverer 으로 JDK 의 Reflection 기능을 활용해 메서드 파라미터 이름을 조회하는 방식으로 변경되어 컴파일러의 `-parameter` 플래그에 의존한다.
4. 해결 : -parameters 컴파일 옵션 추가하기
(1) Gradle 환경에서 -parameters 컴파일 옵션을 추가하는 방법
Gradle 을 기반으로 스프링 프로젝트를 빌드하는 경우에는 자바 컴파일 시점에 -parameters 를 추가해 해결할 수 있다. 아래와 같이 컴파일 아규먼트를 추가하면 프로젝트 빌드 시에 `-parameters` 옵션을 추가하여 빌드하므로 파라미터가 주입되지 않는 문제를 해결할 수 있다.
tasks.withType<JavaCompile>(){
options.compilerArgs.add("-parameters")
}
(2) Intellij 에서 설정하는 방법
위치 : Settings > Build, Execution, Deployment > Compiler > Java Compiler > Additional command line parameters
위와 같은 위치에 접속하여 `-parameters` 옵션을 설정하고 rebuild (cmd + shift + F9) 할 경우, 해당 컴파일러 옵션을 추가할 수 있다.
Reference
'spring > trouble shooting' 카테고리의 다른 글
분산락 AOP 를 @Transactional 보다 나중에 실행시키기 (0) | 2025.01.27 |
---|---|
QueryDSL transform() 에서 꼭 @Transactional 을 사용해야 하는 이유 (0) | 2024.01.29 |
테스트에서 @Sql 로 테스트 데이터가 들어가지 않았던 이유 (with. custom TestExecutionListener) (1) | 2024.01.24 |