PlayData 백엔드 부트캠프 정리

다시 시작하는 부트 캠프 하루 후기 9일차

효건 2024. 11. 6. 09:05

<Redis>

https://github.com/microsoftarchive/redis/releases

 

Releases · microsoftarchive/redis

Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes - microsoftarchive/redis

github.com

윈도우에서는

이 깃허브에서 Redis.msi를 다운받은후 무지성 next 와 install 버튼을 누른후 cDrive -> prgram files-> redis폴더의 redis-cli.exe를 실행시키면 redis 터미널을 열 수있고 사용할수있다.

MACOS에서는 brew를 통해서 redis를 설치하고 사용할수있다. Mac은 brew가 짱인듯 싶다.

 

set user:email:1 "abc1234@gmail.com" nx 이라는 명령어를 사용하면 이 이메일은 시간제한없이 사용가능하다. 그러나 

ex20이라는 명령어를 nx 대신 사용하면 20초 제한으로 사용이 가능하다. 이후에는 자동으로 소멸된다. 

 

자바에서도 설정을 해줘야한다. RedisConfig.java파일을 만들고 아래와 같이 만든다. 여기서도 당연히 JSON형식으로 소통한다. 

@Configuration
public class RedisConfig {

    @Value("${spring.data.redis.host}")
    private String host;

    @Value("${spring.data.redis.port}")
    private int port;

    // Redis 서버와의 연결을 설정하는 역할을 하는 RedisConnectionFactory
    // Redis 접속엥 필욯나 설정을 지정한 후 구현체를 빈으로 등록
    @Bean
    @Qualifier("user-redis-factory")
    // Redis는 16개의 DB를 제공함. 각 DB마다 서로 다른 데이터를 저장할 수 있다.
    // Redis에 접속하는 객체는 RedisConnectionFactory -> 같은 타입의 빈이 여러개 등록될수있다.
    // 같은 타입의 빈을 구분할 수있도록 @Qualifier를 붙여서 구분한다.
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        configuration.setHostName(host);
        configuration.setPort(port);
        configuration.setDatabase(1); //1번 DB를 사요하겠다 default->0
        return new LettuceConnectionFactory(configuration);
    }

    // RedisTemplate은 radis와 상호작용할때 redis key, value의 형식을 정의.
    @Bean
    @Qualifier("user_template")
    public RedisTemplate<String, Object> redisTemplate(
        @Qualifier("user-redis-factory")RedisConnectionFactory factory){

        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //Redis의 키를 문자열로 직렬화 시키겠다.
        template.setKeySerializer(new StringRedisSerializer());
        // value는 JSON으로 직렬화 시키겠다.
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setConnectionFactory(factory);
        return template;
        }
    }

 

이후 user Controller에 아래와 같이 redis template를 가져온다.

@Qualifier("user-template")
private final RedisTemplate<String, String> redisTemplate;

 user Controller에 아래와 같이 추가해준다.

// refresh Token을 DB에 저장하자. -> redis에 저장.
redisTemplate.opsForValue().set(token, refreshToken);

 

추가적으로 token이 만료되었을때 다시 발급해주는 로직을 만들어서 재로그인을 할수있게 해준다.


// access token이 만료되어 새 토큰을 요청
@PostMapping("/refresh")
public ResponseEntity<?> refreshToken(@RequestBody String id) {
    log.info("/user/refresh: POST, id: {}", id);
    User user = userService.findById(Long.parseLong(id));

    // email로 redis를 조회해서 refresh token을 가져오자
    Object obj = redisTemplate.opsForValue().get(user.getEmail());
    if (obj == null) { // refresh token의 수명이 다됨.
        return new ResponseEntity<>(new CommonErrorDto(
                HttpStatus.UNAUTHORIZED,
                "리프레시 토큰도 만료됨! 로그인 필요!"
        ), HttpStatus.UNAUTHORIZED);
    }

    // 새로운 access token을 발급하자.
    String newAccessToken
            = jwtTokenProvider.createToken(user.getEmail(), user.getRole().toString());

    Map<String, Object> info = new HashMap<>();
    info.put("token", newAccessToken);
    CommonResDto resDto
            = new CommonResDto(HttpStatus.OK, "새 토큰 발급됨!", info);

    return new ResponseEntity<>(resDto, HttpStatus.OK);
}