[Spring] Redis Cache 사용하기

dh·2023년 2월 8일
0
post-thumbnail

이전에 한 부동산매매정보 프로젝트에서 카카오맵을 기반으로 지도이동 이벤트가 있을때 마다 db를 조회해서 얻은 데이터로 마커를 그려줬었다.
데이터가 밀집된 지역은 살짝 버벅거리기도 했고,
지도를 살짝 움직여도 같은 데이터를 또 가져와서 비효율적이라 생각했다.
처음에는 데이터를 검색하는 과정이 느려서라고 생각하여 데이터를 조회하는 쿼리의 where에 쓰이는 컬럼에 인덱스를 걸어 적용해봤다.
하지만 근본적인 문제는 같은 데이터를 가져오기 위해 DB에 또 접근하는 것이 문제였다.
(지금 생각해 보면 애초에 현재 행정동을 저장했다가 다른 행정동으로 영역이 변할 때만 지도를 다시 그려주는게 베스트였던것 같다....)
그래서 여기다 레디스 캐시를 적용하면 좋을것 같단 생각이 들었다.

Spring, Redis 연결하기

나는 Docker를 Redis서버로 사용했다.

# 이미지 다운 (docker images 로 확인 가능)
$ docker pull redis

# 컨테이너로 레디스 실행 (--name: 컨테이너 이름 설정, -p: 포트 포워딩, -d: 백그라운드에서 실행)
$ docker run --name some-redis -p 6379:6379 -d redis

# redis-cli 접속, --raw를 써줘야 한글이 안깨진다
$ docker exec -it some-redis redis-cli --raw

pom.xml

 <dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-redis</artifactId>
	<version>2.2.1.RELEASE</version>
</dependency>
		  	
<dependency>
	<groupId>io.lettuce</groupId>
	<artifactId>lettuce-core</artifactId>
	<version>6.0.2.RELEASE</version>
</dependency>

RedisConfig.java

@Configuration
public class RedisConfig {
	
	@Bean
	public RedisConnectionFactory redisConnectionFactory() {
		RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
		redisStandaloneConfiguration.setHostName("127.0.0.1");
		redisStandaloneConfiguration.setPort(6379);
		LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration);
		return lettuceConnectionFactory;
	}
	
	// Redis 서버에 커맨드를 수행하기 위한 hight-level 추상화 제공, Redis 서버에 데이터 CRUD를 위한 interface 제공
	//RedisTemplate은 Redis 사용에 중요한 역할을 합니다. 전달 받은 자바 객체를 serialization/deserialization 기능을 통해 key,value 형태로 Redis 메모리에 저장하거나 가져옵니다.
	@Bean
	public RedisTemplate<?, ?> redisTemplate(){
		RedisTemplate<String, RealEstateDTO> redisTemplate = new RedisTemplate<String, RealEstateDTO>();
		redisTemplate.setConnectionFactory(redisConnectionFactory());
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
		return redisTemplate;
	}	 	
}

RedisTemplate를 이용해 실습

레디스에 대해 찾아보고 사용을 해봤는데 사실 이렇게 쓰는게 맞는건지(?)는 잘모르겠다.

AptDAO.java

DB에서 조회하여 서비스로 넘겨준다.

@Repository
public class AptDAO {
	@Autowired
	private SqlSession sqlSession;
	private final String NAMESPACE = "com.goodee.home.apt.AptDAO.";
	
	public List<RealEstateDTO> getAptRoadName(AptDTO aptDTO)throws Exception{
		System.out.println("DB 조회");
		return sqlSession.selectList(NAMESPACE+"getAptRoadName",aptDTO);
	}
}

AptService.java

서비스에서 레디스에 key,value를 저장할거임
키가 조회할때 키가 있으면 키에 대한 값을 넘기고, 키가 없으면 db에서 조회하고 키를 저장한다.

@Service
public class AptService {
	@Autowired
	private AptDAO aptDAO;
	@Autowired
	private RedisTemplate<String, Object> redisTemplate;
	
	public List<RealEstateDTO> getAptRoadName(AptDTO aptDTO) throws Exception{
		ValueOperations<String, Object> list = redisTemplate.opsForValue();
		
		
		String key = aptDTO.getSigungu();
		
		if(redisTemplate.hasKey(aptDTO.getSigungu())) {
			System.out.println("==============================================");
			System.out.println(aptDTO.getSigungu() + " 키가 이미 있음");
			System.out.println("==============================================");
			return (List<RealEstateDTO>) list.get(key);
		}else {
			System.out.println("==============================================");
			System.out.println(aptDTO.getSigungu() + " 키가 없음");
			List<RealEstateDTO> value = aptDAO.getAptRoadName(aptDTO);
			list.set(key, value, 300, TimeUnit.SECONDS); //키 유효시간 300초로 설정
			System.out.println("Redis에" + aptDTO.getSigungu() + " 키 저장");
			System.out.println("==============================================");
			return value;
		}
		
	}
}

결과

- 먼저 아무것도 하지않았을 때

- 인덱스를 적용해봤을 때

대략 10%정도 빨라진것 같다

- Redis 적용 후

그래프를 보면 처음에는 레디스에 키값이 없기 때문에 DB에서 데이터를 가져와 오래걸리지만 그 이후 키값을 캐시에 저장하고 나서는 속도가 빨라졌다. 대략 10배정도 빨라진 것 같다.


그리고 redis-cli에서 key확인 결과 키가 잘 들어갔다.

- Redis + 인덱스

마지막으로 인덱스까지 적용해봤다.
마찬가지로 대략 10%정도 빨라진것 같다.

레디스와 인덱스를 사용해봤을 때 속도가 더 빨라진 것을 확인할 수 있었는데,
애초에 지도 위에 마커를 유지했다가 행정동 구역이 달라질 때만 다시 그려주는 방법이 최선인 것 같았다.

0개의 댓글