본문 바로가기
캠프 개발일지

개발일지 - 16일차: 버그 해결 및 원인 분석(2)

by JHBang 2024. 3. 15.

2. 

JsonParseException

 

어떤 상황에서 발생한 버그인가?

이전 포스트에서 결정한 랭킹 조회 알고리즘을 코드로 작성하고 테스트를 해 보던 와중 발생한 버그이다.

 

일단 스케줄러를 이용해서 일정 시간마다 resolution 테이블에서 likeCount 내림차순으로 10개를 가져온다.

이 후 해당 값을 redis에 List 형으로 저장한 후, 랭킹 조회 api가 호출될 시 redis에서 랭킹 데이터를 가져오는 방식이였다.

 

조회 api는 오직 redis만 바라보고 있어야 하기 때문에(RDB에 접근하는 코드가 있어서는 안된다.) redis에 저장된 데이터의 value가 바로 Response로 반환할 수 있어야 하는 값이어야 한다고 생각했다. 따라서 스케쥴러를 이용해 redis에 데이터를 집어넣는 과정에서 value의 데이터 타입을 responseDTO로 설정했다. 아래는 그 코드이다.

 @Scheduled(fixedRate = 120000)
    fun getResolutionTop10(){
        redisTemplate.delete("ranking")
        resolutionRepository.getResolutionRanking()
            .forEach{
                redisTemplate.opsForList().rightPush("ranking", SimpleResolutionResponse.from(it))
            }
    }

 

이 코드에서 DTO를 value에 넣기 위해서 직렬화 방식을 GenericJackson2JsonRedisSerializer를 사용했다.

이는 객체를 JSON 형태롤 직렬화/역직렬화 하는 방식의 직렬화 알고리즘이다.

 

RedisConnection 클래스에서 설정할 수 있다.

 @Bean
    fun redisTemplate(): RedisTemplate<*,*>{
        return RedisTemplate<Any, Any>().apply{
            this.connectionFactory = lettuceConnectionFactory()
            this.keySerializer = StringRedisSerializer()
            this.valueSerializer = GenericJackson2JsonRedisSerializer()
            this.hashKeySerializer = StringRedisSerializer()
            this.hashValueSerializer = StringRedisSerializer()
        }
    }

 

이 후 Service 단에서 redis의 데이터를 조회할 때 계속해서 역직렬화 오류가 발생했기에 계속해서 방법을 찾아가며 다양한 방법을 시도했었다.

 

마지막으로 시도한 방식이 바로 Service에서 직접 ObjectMapper를 이용해 JSON 형태를 바꿔주는 방법이였다.

override fun getResolutionRanking(): List<SimpleResolutionResponse> {
        val resolutionRanking = redisTemplate.opsForList().range("ranking", 0, -1)
        val objectMapper = ObjectMapper()

        return resolutionRanking?.map {
            objectMapper.readValue(it.toString(), SimpleResolutionResponse::class.java)
        } ?: emptyList()
    }

 

이 방법도 안되면 어떻게 해야 하나 막막했다. 별별 방법을 많이 시도했기 때문이였다.

 

이 때 발생한 오류 코드가 아래와 같다.

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'SimpleResolutionResponse': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: (String)"SimpleResolutionResponse(title=string, category=string, likeCount=1)"; line: 1, column: 25]

 

어떻게 해결했나?

 

에러 메세지를 살펴보니 String형 데이터를 JSON으로 역직렬화 하는 부분에 있어서 오류가 발생한다고 한다.

 

응? 난 String형 데이터를 준 적이 없는데.... 혹시 it.toString() 이 부분이 문제인가? 하는 생각이 들었다.

 

혹시 몰라서 objectMapper 부분을 삭제하고 테스트 해 봤다.

 

그랬더니...

잘 작동한다!!

 

 

결론적으로 말하면 GenericJackson2JsonRedisSerializer는 아무 잘못 없었다.

계속 직렬화/역직렬화 부분에서 오류가 발생하다 보니 정말 여러 방법을 시도해 봤다.

 

하지만 버그를 잡기위해 다양한 방법을 시도한게 오히려 다른 버그를 낳게 된 것 같다.

A+B도 시도해보고 C+D도 시도해 봤는데 정답은 A+D였던 상황인것이다.