JSON 컬럼 처리 전략 변경을 통한 조회 성능 개선
1. 문제상황
실무 중에 한 조회 API의 개선 요청이 있었습니다. 해당 API는 분 단위로 적재되는 데이터(하루 약 1,440건)을 조회한 뒤, 각 row에 포함된 JSON 컬럼에서 특정 key-value를 추출한 뒤 가공하여 반환하는 구조였습니다. Native Query를 사용해 인터페이스 기반 Projection에 매핑해 이를 파싱하는 형태로 구현된 상태였습니다.
문제는 한 번의 요청으로 최소 5일치 이상의 데이터를 조회해야 한다는 점이었습니다. 실제 수행 시간은 30일 조회 시 6~7분, 10일 조회 시 약 1분 30초 ~ 2분 정도였습니다. 초기에는 대량 데이터 조회로 인한 DB 쿼리 성능이 병목일 것이라 생각했습니다.
2. 병목분석
동일한 쿼리를 DB에서 직접 실행해보았을 때, 결과는 예상과 달랐습니다. 쿼리 자체의 실행 속도는 매우 빨랐으며, DB 성능은 병목이 아니었습니다. 어떤 구간이 병목이었는지를 확인하기 위해 StopWatch를 활용하여 메소드 실행을 구간별로 나누어 측정하였습니다.
분석 결과, 조회 과정에서 DB에 TEXT 형태로 저장된 JSON 컬럼을 인터페이스 기반 Projection에서 Map<String, Object>로 변환하는 과정이 전체 수행 시간의 대부분을 차지하고 있음을 확인할 수 있었습니다.
3. 실패한 해결방법
그렇다면 JSON 파싱 비용을 줄이기 위해, 쿼리 단계에서 JSON 컬럼을 미리 파싱하여 필요한 값만 전달하는 방식을 시도했습니다. 이렇게 하니 인터페이스 기반 Projection에 매핑하는 과정은 매우 빨라졌지만 문제는 DB 쿼리 실행 자체였습니다. JSON 연산이 DB로 이동하며 쿼리 실행 비용이 증가했고, 결과적으로 전체 수행 시간은 더 길어졌습니다.
JSON 파싱 비용을 줄이기 위해 처리 위치를 DB로 옮겼지만, 단순히 비용의 위치만 바뀌었을 뿐 근본적인 해결은 아니었습니다. JPA Repository를 통한 Entity 조회 방식도 시도했지만, 이 경우에는 JSON 파싱 비용이 여전히 애플리케이션 레벨에 남아 있었고, 영속성 컨텍스트 관리 및 객체 매핑 비용까지 추가되며 성능 개선에는 도움이 되지 않았습니다.
4. Entity Manager VS JDBC Template
DB와 ORM 레벨에서 접근은 한계가 있다고 판단하여, 조회 방식 자체를 변경하는 방향으로 접근하였습니다.
먼저 EntityManager를 활용하여 Native Query 실행을 시도하였습니다. 기존 방식에 비해 확실히 속도가 빨라졌지만, 기본적으로는 결과를 모두 조회한 뒤 중간 객체에 담은 후 처리하는 구조였습니다.
이번에는 JDBC Template을 사용하였습니다. ResultSet을 순회하면서 각 row를 읽는 즉시 처리할 수 있었습니다. 이를 통해 JSON 파싱을 조회와 동시에 수행할 수 있었고, 중간 객체를 최소화하여 바로 최종 형태로 변환하는 구조를 구성할 수 있었습니다.
기존 구조가 “전체 조회 → JSON 파싱 → DTO 변환” 이었고, JDBC Template은 “조회와 동시에 JSON 파싱 및 DTO 변환”이 가능한 구조였습니다.
여기에 더해 JSON 파싱 방식도 개선하였습니다. 기존에는 Jackson을 통해 JSON 문자열을 Map<String, Object>로 전체 역직렬화를 하고 있었는데, 이 과정에서 불필요한 객체 생성 비용이 발생했습니다.
이를 JsonNode 기반으로 변경하여 필요한 필드만 선택적으로 접근할 수 있도록 수정하였습니다. 이를 통해 전체 구조를 객체로 변환하는 비용을 줄이고, 실제로 사용하는 데이터만 처리할 수 있도록 최적화를 할 수 있었습니다.
이러한 구조 개선과 파싱 전략 변경을 통해, 10일 기준 약 1분 30초 ~ 2분 수준이던 응답 시간을 약 15초 ~ 20초 수준으로 단축할 수 있었습니다.
5. 결론
이번 문제는 ORM이나 쿼리 방식 자체가 아니라, JSON 데이터를 조회 시점마다 반복적으로 파싱하는 구조에서 발생한 것이었습니다. 조회 방식과 파싱 전략을 함께 개선함으로써 성능을 크게 향상시킬 수 있었지만, 근본적인 해결을 위해서는 데이터 저장 구조 자체를 개선할 필요가 있어보입니다.
Yang