SpringBoot

[Spring Boot] Redis 캐싱 서버 적용하기

코카멍멍 2023. 5. 1. 13:11
반응형

Redis란 무엇인가?

Redis(Remote Dictionary Server)로 오픈 소스 기반의 인 메모리 데이터 저장소입니다.

Redis의 특징

  • 메모리 내 데이터 저장
  • Key : Value 타입
  • 다양한 데이터 구조지원
  • 메시징 큐 구현 가능
  • 싱글 스레드 방식

Redis 사용 용도

일반적으로는 캐싱, 세션 관리, 풀링, 메시지 브로커, 게임 랭킹 등 다양한 영역에서 사용됩니다.

Redis의 장점

  • Key:Value로 이뤄져 있는 만큼 빠른 속도로 데이터를 검색할 수 있습니다.
  • 비관계형 데이터베이스로 확장성에 있어서 이점이 있습니다.
  • in-memory 방식으로 디스크 방식보다 빠릅니다.

Redis의 단점

  • 데이터 일관성, 동시성 제어를 위한 기능이 미약합니다.

Redis 캐싱 서버 적용하기

Redis의 서버를 적용하게 된 이유는 Member.class는 유저의 권한이 필요한 경우 매번 DB를 조회하게 되는데
이 것은 DB에 많은 부하를 줍니다. DB를 조회하기 전에 캐싱서버에서 Member 클래스를 가져올 수 있게 하면 좋겠다 생각 되어 적용하게 되었습니다.

주의 사항

위의 예시를 한번 들어보겠습니다. Member 클래스를 자주 업데이트 하는 상황이 발생하면 Update가 될때마다 업데이트 된 유저의 데이터를 Redis에 적용해 주어야 합니다.

 

작성 리스트

  • redis build.gradle 추가
  • redis configuration 빈 등록하기
  • Member Cache DAO 생성하기
  • Member 서비스단에서 Caching OR DB조회
  • 로그인시 redis에 캐싱

Redis build.gradle

implementation 'org.springframework.boot:spring-boot-starter-data-redis'

data-redis 의존성을 추가해줍니다.

Maven Repository

Redis Configuration 빈 등록하기

@Configuration
@EnableRedisRepositories
@RequiredArgsConstructor
public class RedisConfiguration {
    private final RedisProperties properties; //1
    @Bean
    public RedisConnectionFactory redisConnectionFactory(){
        RedisURI redisURI = RedisURI.create(properties.getUrl());
        org.springframework.data.redis.connection.RedisConfiguration configuration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
        LettuceConnectionFactory factory = new LettuceConnectionFactory(configuration);
        factory.afterPropertiesSet();
        return factory;
    }

    @Bean
    public RedisTemplate<String, Member> redisTemplate() {
        RedisTemplate<String, Member> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory());
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new Jackson2JsonRedisSerializer<Member>(Member.class));
        return template;
    }
  1. properties는 yml에서 적용해주는 spring.data.redis 에 설정한 값들을 가져오는 클래스입니다.

redisConnectionFactory는 스프링과 Redis가 동작할 수 있게 연결해주는 설정들입니다.
RedisTemplate은 JpaRepository를 만드는 것처럼 RedisRepository를 만드는 겁니다.
redis 템플릿에 Factory 설정을 해주고 key 설정과 Value 설정을 해주고 반환해줍니다.

Member Cache DAO 생성하기

@Slf4j
@Repository
@RequiredArgsConstructor
public class MemberCacheRepository {

    private final RedisTemplate<String, Member> template;
    private final Duration expiredTime = Duration.ofDays(3);

    public void setMember(Member member) {
        String key = getKey(member.getName());
        log.info("Set Member Redis {} : {}", key, member);
        template.opsForValue().set(key, member, expiredTime);
    }

    public Optional<Member> getMember(String username) {
        Member member = template.opsForValue().get(getKey(username));
        log.info("Get member Redis: {}", username);
        return Optional.ofNullable(member);
    }

    private String getKey(String userName){
        return "UID:"+userName;
    }
}

Redis에서 getMember 메소드와 setMember 메소드를 만들었습니다.
ExpiredTime을 3일로 설정해서 3일뒤에 데이터를 소멸하게 설정했습니다.

Member 서비스단에서 Caching OR DB조회

public Member loadMemberByMemberName(String userName) {
        return cacheRepository.getMember(userName)
                .orElseGet(
                        () -> memberRepository.findByName(userName).map(Member::fromEntity).orElseThrow(() ->
                                        new SnsException(Errorcode.NOT_EXISTS_USERNAME, String.format("%s not founded", userName)))
                        );

    }

캐시 서버에 Member의 관한 정보가 없으면 DB를 조회하는 코드입니다.

로그인시 redis에 캐싱

public String login(String username, String password) {
        // username 유저 가져오기
        Member member = loadMemberByMemberName(username);

        // 비밀번호 체크
        if (!encoder.matches(password, member.getPassword())){
            throw new SnsException(Errorcode.NOT_MATCH_PASSWORD);
        }
        // 멤버 캐싱
        cacheRepository.setMember(member);

        // 토큰 생성
        return JwtTokenUtils.generateToken(username, secretKey, expiredTimeMs);
    }

로그인을 할 때 Member의 정보를 캐싱해주는 로직입니다.

사실 Redis를 적용하고 테스트 코드에도 적용하기 위해서 많이 찾아봤지만 나중에 기회되면 포스팅하겠습니다.

긴글 봐주셔서 감사합니다. (_ _)

깃허브 Repository

반응형