[02.08] 내일배움캠프[Spring] TIL-67

박상훈·2023년 2월 8일
0

내일배움캠프[TIL]

목록 보기
67/72

[02.08] 내일배움캠프[Spring] TIL-67

1. Spring Final Project

  • 오늘 진행상황
    1) 어제 작성한 UML, ERD, 와이어프레임 워크를 가지고 튜터님과 긴 상의를 걸친 결과
    정확이 이프로젝의 목적성과 방향성에 큰 혼돈이 왔고, 초기 구상보다 더 무거워진 모습을 발견했다.
    2) 따라서 정확한 목적을 다시 잡고, 처음부터 다시 가볍게 진행하고 있다.
    3) 오늘은 와이어 프레임 워크를 간단하게 다시 작성했고, 내일은 이것을 바탕으로 UML, ERD를 가볍게 리빌딩 한 후, 금요일에 실질적 개발에 들어갈 것 같다.
  • 혼돈의 카오스 흐름
    1) 재능 마켓을 구현하자! -> 견적서? -> 프로필로 신청할까? 게시글을 올릴까? -> 비용처리는 어떻게 할까? ->
    뭔가 무거워 지고 이상하다...!

2. 다시 그린 와이어 프레임 워크

  • 우리는 백앤드 개발에 초점을 맞춰야한다. 와이어 프레임 워크는 디테일 하게 신경쓰지 말고, 프로젝트의 흐름을 잡는 용도로 사용하자
  • 가볍게 처음 취지에 알맞게 진행하고, 이후 리팩토링을 통해 다듬고 추가 기능을 구현해보자.
  • 추가적으로 오늘은 Refresh토큰등의 사용을 위해 redis를 개인적으로 조금 공부해봤다.
  • 공부 배경 : JWT토큰, Refresh토큰의 저장과 확인을 위한 캐시 저장소가 필요!
  • 아래 글은 참고 블로그에서 따라 작성한 것이며, 순수 공부 목적입니다.(필기)
    https://wildeveloperetrain.tistory.com/59

2. 개념(Cache)

  • DB가 있음에도 인메모리 데이터 구조 저장소를 사용하는 이유가 뭘까?
    -> DB는 물리적 디스크에 직접 쓰기 때문에 서버에 문제가 발생하여 다운되더라도 데이터가 손실되지 않는다.
    -> 매번 디스크에 접근해야 하기 때문에 사용자가 많아질수록 부하가 많아져서 느려질 수 있다.
    -> 한번 읽어온 데이터를 임이의 공간에 저장하여 다음에 읽을 때 빠르게 결과값을 받을 수 있도록 도와주는 역할을 한다(캐시)
    1. 클라이언트가 데이터를 요청
    1. 웹 서버는 데이터가 존재하는지 Cache서버에 먼저 확인
    1. Cache서버에 데이터가 있으면 DB를 조회하지 않고 Cache서버에 있는 결과값을 클라이언트에게 바로 반환(Cache Hit)
    1. Cache서버에 데이터가 없으면 DB에 데이터를 조회하여 Cache서버에 저장하고, 결과값을 클라이언트에게 반환(Cache Miss)
    1. 웹서버는 모든 데이터를 Cache서버에 저장
    1. Cache서버에 특정 시간 동안 데이터가 저장됨
    1. Cache서버에 있는 데이터를 DB에 저장
    1. DB에 저장된 Cache 서버의 데이터를 삭제

3. Redis

  • Key, Value 구조이기 때문에 쿼리를 사용할 필요가 없다.
  • 데이터를 디스크에 쓰는 구조가 아니라 메모리에서 데이터를 처리하기 때문에 속도가 빠르다.
  • String, Lists, Sets, Sorted Sets, Hashes 자료구조를 지원한다.

4. Spring Boot Redis사용

// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis', version: '2.4.10'
  • Spring Boot에서는 Spring Data Redis를 통해 Lettuce, Jedis라는 두 가지 오픈소스 Java라이브러리를 사용할 수 있다.
  • Lettuce는 별도의 설정 없이 사용할 수 있으며, Jedis를 사용하고자 하면, 별도의 의존성을 필요로 한다.

Spring Data Redis의 접근방식

  • 1) RedisTemplate
    2) RedisRepository
    -> 두 방식 모두 Redis에 접근하기 위해서 Redis 저장소와 연결하는 과정이 필요하다.
'package org.springframework.data.redis.connection;' 
패키지의 RedisConnectionFactory 인터페이스를 사용
@RequiredArgsConstructor
@Configuration
@EnableRedisRepositories
public class RedisRepositoryConfig {

    private final RedisProperties redisProperties;

    // lettuce
    @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());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}
  • RedisConnectionFactory인터페이스를 통해 LettuceConnectionFactory
    를 생성하여 반환한다.
  • setKeySerializer, setValueSerializer
    -> RedisTemplate 사용 시 , Srping - Redis간 데이터 직렬화, 역직렬화 시 사용하는 방식이 Jdk 직렬화 방식이기 때문.
    -> 동작에 문제는 없지만, Redis - Cli를 통해 직접 데이터를 보려고 할 때 알아볼 수 없는 형태로 출력되기 때문에 따로 설정한 것!

ProperTies Setting

# Redis
spring.redis.host=localhost
spring.redis.port=6379

RedisTemplate을 활용한 방법

String refreshToken = jwtTokenProvider.createRefreshToken();

ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
valueOperations.set(rRTKey + user.getIdx(), refreshToken);
log.info("redis RT : {}", valueOperations.get(rRTKey + user.getIdx()));

Redis 메소드

  • opsForValue : Strings를 쉽게 Serialize / Deserialize 해주는 interface
    opsForList : List를 쉽게 Serialize / Deserialize 해주는 interface
    opsForSet : : Set을 쉽게 Serialize / Deserialize 해주는 interface
    opsForZSet ZSet을 쉽게 Serialize / Deserialize 해주는 interface
    opsForHash : Hash를 쉽게 Serialize / Deserialize 해주는 interface

RedisRepository를 사용한 객체 저장방법

@Getter
@Setter
@RedisHash("member")
public class Member {

    @Id
    private String id;
    private String name;
    private int age;

    public Member(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
  • @RedisHash : 어노테이션을 통해 설정한 값을 Redis의 Key Prefix로 사용
  • @Id : JPA와 동일한 역할 수행

Repository 생성

public interface MemberRedisRepository extends CrudRepository<Member, String> {
}
  • CRUDRepsitory는 어차피 JpaRepository상위 개념이니까 상관없을듯..?(개인생각)
profile
기록하는 습관

0개의 댓글