[TIL - 0828] 데이터 캐시, OOP, 자바, 테스트, JPA

데이터 캐시하기(2) - 스프링 캐시 추상화, redis 글로벌 캐시

스프링 캐시 추상화 - AOP, 캐시 매니져

  • AOP : @Cacheable, @CacheEvict 캐시 관련 코드를 비즈니스 로직에서 덜어낼 수 있도록 어노테이션(포인트컷)을 설정해두면 프록시? CGLib? 어찌되었건 캐시 동작(read, write)
  • @Cacheable : 캐시 서비스를 메소드 단위로 설정 어노테이션
    • name : 캐시 이름
    • 메소드 파라미터(key), 리턴 데이터(value) : 파라미터가 없을 경우 기본 키 값을 생성, 파라미터가 여러개인 경우 key=”#파라미터명” 으로 설정, 객체일 경우 key=”#객체.필드명” (SpEL)
@Cacheable("item")
public Item findByName(String name) {

}
  • @CacheEvict : 캐시 제거 메소드 단위로 설정 어노테이션
    • 캐시 단위로 삭제가능 : 모두 삭제하던지, 특정 key값을 가진 캐시 데이터만 삭제하던지
@Cacheable("bestItem")  // bestItem 이라는 캐시에 인자 name을 key로 가지는 Item을 value로 캐시
public Item findByName(String name) {
    
}


@CacheEvict(value = "item", allEntiries=true) 
public void refreshDailyBestItem() {

}

@CacheEvict(value = "item", key = "#item.name") 
public void refreshDailyBestItem(Item item) {
    
}
  • 캐시매니져 : 캐시 서비스 담당 객체
    • CacheManager 인터페이스 제공 -> 인터페이스 구현체들
    • Redis를 캐시 데이터베이스로 사용하려면 사용자 정의 클래스를 만들어야함 -> spring.data.redis에서 제공됨 - 우리는 디펜던시 등록만 하면 됨(InitilizingBean을 구현하고 있어서 빈으로 자동 설정됨)

redis 사용 글로벌 캐시 구현

  • redis : 메모리 기반 데이터 read/write
  • 도커 사용 : redis 이미지 pull 후 시작
  • 스프링에서는 캐시 설정에 대한 추상화 및 redis 캐시 매니져를 미리 생성해두고 외부 설정파일에서 설정만 해주면 사용되게 해놓음 : 어제 코드 변경없이 캐시 가능
/* application.properties */
spring.cache.type=redis


redis:6379> keys *
1) "item::jinbro"
2) "item::colin"

16:01:36.085 [DEBUG] [http-nio-8080-exec-4] [j.rediscachetest.web.ItemController] - 캐시된 데이터 : colin, 처리 시간 : 3012
16:01:39.857 [DEBUG] [http-nio-8080-exec-6] [j.rediscachetest.web.ItemController] - 캐시된 데이터 : colin, 처리 시간 : 3

Java API 시간 다루기

~ Java7

  • Date API 사용
    • 문제점 : Month가 0부터 시작, 값을 리턴하기때문에 값에 맞는 사용자가 보기 좋은 값으로 개발자가 바꿔야했음(switch 혹은 Enum으로?)
    • @Deprecated 설정되어있음
System.out.println(date.getMonth() + ", " + date.getDay());

> 7, 2 // 직관적이지 못하며 해당 데이터를 변환해야함 - 8월인데 7로 리턴되고, 화요일인데 2로 리턴됨

Java8

  • LocalDate(날짜 관련), LocalTime(시간 관련), LocalDateTime(내부적으로 LocalDate/LocaTime을 사용하고 있음)
    • get 했을 때 Month, DayOfWeek 등과 같은 객체가 리턴됨 : 필요한 API가 구현되어있음
    • Duration, Period 유틸성 클래스를 제공함
LocalDate localDate = LocalDate.now();
System.out.println(localDate.getMonth() + ", " + localDate.getDayOfWeek()); 

> AUGUST, TUESDAY      

객체지향

  • 모든 primitive type을 ref로 변경하기 : 상태값에 의해 행동하도록 코드를 변경하기위해서
    • 생각해보면 무조건적으로 바꾸기보다 하는 일이 있으면 바꾸기 : 할 일은 어떻게든 만들어지긴 할거지만..!
    • 쪼갤 때 해당 클래스에서만 사용된다면 inner class를 사용해도 됨
  • 묶을 수 있는 부분은 다 묶어서 인스턴스 변수를 줄여라 : 의미가 있다면 줄여버려서 복잡도를 줄여버리기

테스트

  • 같은 시니리오에 대해 테스트 코드를 작성하는 것 - 굳이 할 필요없음, 객체 메소드가 변경되었을 때 바꿔야할 대상이 더 많아짐
  • 테스트 읽기 좋게 setup을 너무 많이 활용하지말자 : 테스트 케이스 진행될 때마다 그만큼 생각이 따라가야할 수도 있음

JPA

JPQL과 native sql

  • native sql과 JPQL 사용 : native sql을 쓸 때 특정 데이터베이스에서만 사용하는 sql이 있을 수 있음 - 특정 RDBMS에 종속되게 되는 것, 고로 JPA 사용 장점 중 하나를 버리고 시작하는 것일 수 있음
    • 되도록이면 JPQL을 사용하기