| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 |
- 프로젝트 이름 변경
- N + 1
- @Transaction(readOnly=true)
- 컨트리뷰터
- fetch join
- AWS
- MySQLTransactionRollbackException
- ngrinder
- awspring
- Commit
- injellij
- intellij
- assert
- OIDC
- 이펙티브 자바
- redis
- convertAndSendToUser
- naturalid
- 정적 팩터리 메서드
- @RequestMapping
- spring
- JPA
- mockito
- batch insert
- Git
- Cannotacquirelockexception
- @controller
- oauth2.0
- websocket
- spring-cloud-starter-aws
- Today
- Total
정리정리
소소한 스프링 레디스 컨트리뷰트 이야기 본문
이슈
최근에 새로 업데이트된 Spring boot 4.0.0를 이용해 코드를 작성해보고 있었는데, Spring Redis를 사용하는 코드에서 문제가 발생하였다.
List<Object> results = stringRedisTemplate.executePipelined(
new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
StringRedisConnection stringRedisConn = (StringRedisConnection) connection; // 예외 발생 부분
...
return null;
}
}
);
해당 코드는 Spring Redis Docs의 Pipelining 부분에 예제 코드로 나와있을 만큼 간단하면서 검증이 된 코드였다.
기존의 Spring Boot 3.x 버전에서도 잘 동작하는 것을 알고 있었기 때문에 4.0으로 올라가면서 문제가 발생했을 거라는 생각이 들어 디버깅을 해봤다.
디버깅
java.lang.ClassCastException: class jdk.proxy3.$Proxy128 cannot be cast to class org.springframework.data.redis.connection.StringRedisConnection
우선 doInRedis메서드의 파라미터로 넘어온 RedisConnection을 StringRedisConnection으로 캐스팅하는 과정에서 ClassCastException이 발생했으므로 RedisConnection의 구체 클래스를 만드는 부분을 찾아봤다.

RedisTemplate의 executePipelined 메서드를 타고 들어가다보면 execute 메서드에서 RedisConnection을 전처리하는 코드를 찾을 수 있다.

우선 RedisTemplate에서는 해당 메서드에 들어가면 별다른 작업 없이 그대로 connection을 반환한다.

이때 Spring Boot 3.x 버전에서는 RedisTemplate를 상속한 StringRedisTemplate에서 차이가 발생한다.
StringRedisTemplate에서 이 메서드를 오버라이딩하여 새로운 프록시 connection을 생성하여 반환하기 때문에 위의 코드에서 StringRedisConnection으로 캐스팅이 가능했다.

그런데 이 부분이 필요없다고 판단했는지, 4.0으로 넘어오면서 해당 부분을 삭제한 커밋(3a930ce)을 찾을 수 있었다.
이 변경 때문에 RedisTemplate에서 그대로 리턴된 connection을 StringRedisConnection으로 캐스팅하는 과정에서 예외가 발생하게 되었던 것이다.
Docs에도 여전히 예제 코드로 캐스팅을 하는 부분이 남아있었기 때문에 이 부분을 수정하면 좋을 것 같다는 생각을 했다.
그래서 어떤 식으로 고치면 좋을지 찾아보다가 해당 커밋에서 답을 쉽게 얻을 수 있었다.

테스트코드에서도 단순히 외부에서 StringRedisConnection 프록시 객체를 만들어 사용한 부분을 보고, 예제 코드도 테스트 코드와 결이 비슷하다 생각해 동일하게 수정 후 PR을 올렸다.
결과


그 결과, 컨트리뷰터 배지와 함께 공식 문서의 예제 코드에 내 수정사항이 올라가게 되었다.
정말 별거 아닌 내용이기도 하고 PR올릴 때 엄청 떨리고 무섭기도 했지만 많은 사람들이 사용하는 코드에 조금이나마 기여를 했다는 생각에 보람찼다!
https://github.com/spring-projects/spring-data-redis/pull/3281
Fix example code in Pipelining docs by wlsh44 · Pull Request #3281 · spring-projects/spring-data-redis
Issue When executing the example code from the Pipelining documentation using Spring Data Redis 4.0.0, a ClassCastException is thrown while attempting to cast RedisConnection to StringRedisConnecti...
github.com
https://docs.spring.io/spring-data/redis/reference/redis/pipelining.html
Pipelining :: Spring Data Redis
The Lettuce driver supports fine-grained flush control that allows to either flush commands as they appear, buffer or send them at connection close. LettuceConnectionFactory factory = // ... factory.setPipeliningFlushPolicy(PipeliningFlushPolicy.buffered(3
docs.spring.io
'Spring' 카테고리의 다른 글
| webSocket convertAndSendToUser 예외 처리 동작과정 및 삽질기 (1) | 2025.08.18 |
|---|---|
| 스프링6 @RequestMapping Handler 등록 방식 변화 (feat. @Controller) (0) | 2023.11.16 |
| 스프링 부트 버전에 따른 io.awspring.cloud s3 연결시 주의점 (0) | 2023.04.20 |
| org.springframework.cloud VS io.awspring.cloud (0) | 2023.04.17 |