개발Log

Spring Boot | @Transactional과 Redis를 함께 사용할 수 없는 이유 및 Redis 트랜잭션 사용법

이진유진 2024. 7. 8. 20:06
반응형
오늘은 회사에서 레디스 세션 체크를 통한 로그아웃 로직을 구현하며 알게 된 것을 정리해보려 합니다!
Redis주소는 맞게 들어가는데, 왜 값을 못가져올까??
처음 보는 상황에 많이 당황했었는데요..
Spring Transactional을 사용하면 Redis와 다르게 처리가 되는 방식이라, 제대로 작동이 되지 않았던 것이었습니다!
오랜만에 새롭게 알게 된 내용이라 한번 정리를 해보려 합니다. 



Spring framework를 사용해 애플리케이션을 개발 시, 

데이터베이스 트랜잭션 관리를 위해 흔히 @Transactional을 사용하고 있습니다. 

그러나 Redis와 NoSQL 데이터베이스를 사용할 때는 @Transactional을 동일하게 사용할 수 없습니다. 

 

이번 글에서는 그 이유와 Redis에서 트랜잭션을 사용하는 방법에 대하여 알아보겠습니다!

 

Spring @Transactional 이란?

Spring에서 제공하는 트랜잭션 관리 메커니즘입니다. 

주로 관계형 데이터베이스와 함께 사용되며, 다음과 같은 ACID 속성을 보장합니다. 

 

* Atomicity (원자성) - 모든 작업들이 성공적으로 완료되거나, 전혀 완료되지 않음을 보장
* Consistency (일관성) - 트랜잭션이 완료된 후 데이터의 일관성을 보장 
* Isolation (고립성) - 트랜잭션이 서로 간섭하지 않도록 보장 
* Durability (지속성) - 트랜잭션이 완료된 후 영구적으로 데이터를 보관 

 

@Transactional은 주로 JPA와 같은 ORM 프레임워크와 함께 사용되며, 

DataSourceTransactionManager 나 JpaTransactionManager를 통해 트랜잭션을 관리합니다. 

 

Redis와 트랜잭션 관리의 차이점 

Redis는 전통적인 관계형 데이터베이스가 아니라 NoSQL 데이터베이스입니다. 

따라서 스프링의 @Transactional 과는 다음과 같은 차이점이 있습니다. 

 

1. 트랜잭션 지원의 차이 

관계형 데이터베이스

- ACID 속성을 완벽히 지원하며, 스프링의 @Transactional을 통해 트랜잭션을 쉽게 관리할 수 있습니다. 

Redis 

- 기본적으로 ACID 속성을 완벽하게 지원하지 않습니다. Redis는 트랜잭션을 위해 'MULTI' , 'EXEC' , 'DISCARD', 'WATCH' 등의 명령어를 제공합니다. 하지만 이는 스프링의 @Transactional과 같은 방식의 트랜잭션 관리는 아닙니다. 

 

2. 트랜잭션 매니저의 차이 

스프링 트랜잭션 매니저 

- DataSourceTransactionManager, JpaTransactionManager와 같은 트랜잭션 매니저를 사용하여 트랜잭션을 관리합니다. 

Redis 

- Redis는 자체 트랜잭션 매니저를 제공하지 않으며, RedisTemplate를 사용하여 명령어를 실행합니다. 

 

Redis에서 트랜잭션 사용 예시 

Redis에서 트랜잭션이 필요하다면, 

'MULTI' / 'EXEC' 명령어를 사용해 트랜잭션을 수행할 수 있습니다. 

스프링에서는 RedisTemplate와 SessionCallback을 사용하여 트랜잭션을 처리할 수 있습니다. 

 

예시코드

@Autowired
private StringRedisTemplate stringRedisTemplate;

public void performRedisTransaction() {
    List<Object> results = stringRedisTemplate.execute(new SessionCallback<List<Object>>() {
        @Override
        public List<Object> execute(RedisOperations operations) throws DataAccessException {
            operations.multi();  // 트랜잭션 시작
            operations.opsForValue().set("key1", "value1");
            operations.opsForValue().set("key2", "value2");
            return operations.exec();  // 트랜잭션 커밋
        }
    });

    System.out.println("Transaction results: " + results);
}

 

위의 코드는 StringRedisTemplate을 사용해 Redis 트랜잭션을 수행하는 예시입니다. 

multi() 메서드를 호출하여 트랜잭션을 시작하고, 여러 Redis 명령어를 실행한 후 'exec()' 메서드를 호출하여 트랜잭션을 커밋합니다. 

 

결론

스프링의 @Transactional은 주로 관계형 데이터베이스와 함께 사용되며, 

Redis와 같은 NoSQL데이터베이스와는 다른 방식으로 동작합니다. 

Redis와 트랜잭션 관리가 필요한 경우, Redis의 트랜잭션 명령어를 직접 사용하는 것이 적합합니다. 

Redis와 관계형 데이터베이스를 함께 사용하는 경우, 

각각의 트랜잭션을 별도로 관리하거나, 애플리케이션 레벨에서 트랜잭션 일관성을 유지하는 추가 로직을 구현해야 합니다. 

 

 

반응형