운영 체크리스트

ORM 성능은 한 옵션이 아니라
읽기 경로, 세션 경계, 상태 동기화를 같이 보는 일입니다.

체크리스트의 핵심은 기능 이름을 외우는 것이 아니라, 어디서 SQL이 늘고 어디서 오래된 상태가 남는지 순서대로 확인하는 것입니다.

먼저 볼 순서
1SQL 노출
2연관 조회
3세션 경계
4벌크 동기화
5캐시 선별

앞쪽에서 원인을 찾을수록 비용이 작고, 뒤쪽으로 갈수록 운영 정책과 일관성 판단이 중요해집니다.

읽기 경로

조회가 느려질 때는 SQL 수와 로딩 범위를 먼저 좁힙니다.

ORM이 편해 보여도 실제 병목은 반복 SELECT, 메모리 페이징, 오래 열린 세션에서 드러납니다.

1
쿼리 로그
관측

같은 SELECT가 화면 하나에서 반복되는가?

개발 중에는 SQL 로그와 바인딩 값을 항상 켜 두고, 예상보다 많은 쿼리가 보이면 N+1부터 의심합니다.

2
Fetch Join + 페이징
조회

컬렉션 1:N을 JOIN한 채로 페이지를 자르고 있는가?

페이지네이션은 DB가 하게 두고, 연관 컬렉션은 @BatchSize나 DTO 조회로 분리해 메모리 페이징을 피합니다.

3
OSIV
경계

세션이 응답 끝까지 열려 커넥션을 오래 잡고 있지 않은가?

API 서버라면 보통 OSIV=false 쪽이 안전합니다. Lazy 로딩이 필요하면 서비스 계층 안에서 조회를 끝냅니다.

쓰기와 재사용

DB 상태와 ORM 내부 상태가 어긋나는 지점을 정리합니다.

대량 변경 뒤의 영속성 컨텍스트와, 읽기 패턴이 맞지 않는 2차 캐시가 대표적인 함정입니다.

4
벌크 연산
쓰기

DB는 바뀌었는데 영속성 컨텍스트는 옛 엔티티를 들고 있지 않은가?

대량 UPDATEDELETE 뒤에는 flush(), clear()로 상태를 맞춰야 다음 로직이 오래된 값을 읽지 않습니다.

5
2차 캐시
재사용

조회는 많고 변경은 드문 데이터에만 캐시를 쓰고 있는가?

기준 정보처럼 잘 안 바뀌는 데이터만 @Cacheable로 선별합니다. 변경이 잦으면 캐시 무효화 비용이 더 큽니다.