spring redis jpa, redisTemplate 사용하기

최준호·2022년 5월 27일
0

redis

목록 보기
2/3
post-thumbnail

📕Spring에서 redis cache 서버로 사용(jpa)

redis container 생성

docker run -p 6379:6379 --name redis -d redis

명령어로 실행시킨 뒤

docker exec -it redis /bin/bash

컨테이너에 접속

redis-cli

로 접근하면 redis 명령어로 조회할 수 있다.

의존성 추가

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.6.7</version>
</dependency>

redis 의존성을 추가시켜준다.

Config

@Configuration
@EnableRedisRepositories
@RequiredArgsConstructor
public class RedisConfig {
    private final RedisProperties redisProperties;

    @Bean
    public RedisConnectionFactory redisConnectionFactory(){
        return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort());
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(){
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        //redisTemplate.setKeySerializer(new StringRedisSerializer());    //key serializer
        //redisTemplate.setValueSerializer(new StringRedisSerializer());  //value serializer
        //redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        //redisTemplate.setDefaultSerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}

저장할 domian 정의

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@RedisHash(value = "refreshToken")
public class RefreshToken {
    @Id
    private String userId;
    private String refreshToken;

    @TimeToLive
    private long expiredTime;
}

redis의 hash로 저장하기 위해 코드를 작성했다.
@RedisHash 저장시 hash key 값
@TimeToLive redis 내에 저장될 시간을 정의
@Id jpa 용 hibernate id가 아닌 org.springframework.data.annotation.Id import 해야됨

repository 정의

public interface RefreshTokenRedisRepository extends CrudRepository<RefreshToken, String> {
}

service 정의

public interface AdminUserRedisService {
    RefreshToken save(RefreshToken adminUserToken);
    RefreshToken findById(String userId);
}
@Service
@RequiredArgsConstructor
@Slf4j
public class AdminUserRedisServiceImpl implements AdminUserRedisService {
    private final RefreshTokenRedisRepository refreshTokenRedisRepository;

    @Override
    public RefreshToken save(RefreshToken adminUserToken) {
        return refreshTokenRedisRepository.save(adminUserToken);
    }

    @Override
    public RefreshToken findById(String userId) {
        return refreshTokenRedisRepository.findById(userId).get();
    }
}

이렇게 정의하면 끝났다.

resdisTemplate을 사용할 수도 있는데. 우선은 내가 저장하려는 데이터가 hash 형태로 저장하는게 좋을거 같고 jpa가 자동으로 해주기 때문에 다른 코드들과 통일성 있게 가게 하기 위해서 우선 이렇게 작성했다.

TEST

@SpringBootTest(properties = "spring.cloud.config.enabled=false")
class AdminUserRedisServiceImplInteTest {

    @Autowired
    private AdminUserRedisService adminUserRedisService;

    @DisplayName("token redis 저장 success")
    @Test
    void tokenSave(){
        //given
        RefreshToken token = RefreshToken.builder()
                .userId("test")
                .refreshToken("test_token")
                .expiredTime(60)    //테스트용 1분
                .build();
        //when
        RefreshToken refreshToken = adminUserRedisService.save(token);
        //then
        RefreshToken findToken = adminUserRedisService.findById(token.getUserId());
        System.out.println(refreshToken.getRefreshToken());
        System.out.println(findToken.getRefreshToken());
        assertEquals(refreshToken.getRefreshToken(), findToken.getRefreshToken());
    }
}

해당 코드로 테스트를 해보자.

keys *
hgtall refreshToken:test

를 통해 결과를 확인해보면 다음과 같이 모두 정상적으로 등록되었고 우리가 파기 시간으로 정해둔 1분 뒤에 다시 검색해보면

파기되어진 것도 확인할 수 있다.

jpa로 활용하여 사용하니 코드 작성도 간편했고 공부할 것도 없이 잘 되었다.
redis의 다른 자료구조를 사용하고자 한다면 redisTemplate를 사용하여 적용시키면 될거 같다.

📕RedisTemplate 사용

redisTemplate를 통해 더 다양한 자료구조를 사용할 수도 있다.

Config

@Configuration
@EnableRedisRepositories
@RequiredArgsConstructor
public class RedisConfig {
    private final RedisProperties redisProperties;

    @Bean
    public RedisConnectionFactory redisConnectionFactory(){
        return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort());
    }


    @Bean
    public RedisTemplate<String, Object> redisTemplate(){
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        //redisTemplate.setKeySerializer(new StringRedisSerializer());    //key serializer
        //redisTemplate.setValueSerializer(new StringRedisSerializer());  //value serializer
        //redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        redisTemplate.setDefaultSerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}

설정 파일을 생성해주고 serializer 부분을 주석처럼 하나씩 설정해줘도 되지만 setDefaultSerializer()를 통해 한번에 설정하는 것도 가능하다.

Test

@SpringBootTest(properties = "spring.cloud.config.enabled=false")
class AdminUserRedisServiceImplInteTest {

    @Autowired
    private AdminUserRedisService adminUserRedisService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @DisplayName("token redis 저장 success")
    @Test
    void tokenSave(){
        //given
        RefreshToken token = RefreshToken.builder()
                .userId("test")
                .refreshToken("test_token")
                .expiredTime(60)    //테스트용 1분
                .build();
        //when
        RefreshToken refreshToken = adminUserRedisService.save(token);
        //then
        RefreshToken findToken = adminUserRedisService.findById(token.getUserId());
        System.out.println(refreshToken.getRefreshToken());
        System.out.println(findToken.getRefreshToken());
        assertEquals(refreshToken.getRefreshToken(), findToken.getRefreshToken());
    }

    @DisplayName("redis template 사용")
    @Test
    @Transactional
    void tokenSaveRedisTemplate(){
        //given
        String userId = "tester1";

        RefreshToken token = RefreshToken.builder()
                .userId(userId)
                .refreshToken("test_token")
                .expiredTime(60)    //테스트용 1분
                .build();

        //when
        String key = "refreshToken:"+userId;
        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
        hash.put(key, "userId", userId);
        hash.put(key, "refreshToken", token.getRefreshToken());

        //then
        Object o = redisTemplate.opsForHash().get(key, "userId");
        System.out.println(o);
    }
}

jpa와 동일하게 데이터를 넣어주고 싶다면 다음과 같이 작성해야한다. hash 내부에 hash를 넣어서 작성할 수 있기도 하지만... 단점은 해당 데이터를 가져올때 key를 통해 하나씩 가져올 수 있는데 설정도 복잡해지고 template으로 객체를 하나씩 파싱해서 넣어줘야한다...

내가 redis를 잘 안써봐서 모르는 걸수도 있다.!

데이터를 성공적으로 저장시키면 다음과 같은 반환을 받을 수 있고 데이터를 가져오는것도 key-value라서 직접 template으로 가져오려고 하면 좀 코드도 길어지고 복잡해질거 같다. 객체 자체를 저장하는 용도는 jpa를 사용하고 특정 메세지나 특정 문자열만 저장하는 용도는 template으로 간단하게 하면 될거 같다!

profile
해당 주소로 이전하였습니다. 감사합니다. https://ililil9482.tistory.com

0개의 댓글