페이징 없이 전체 조회를 짜는 개발자에게
by 그릿 | GROWTH_ESSAY | 2026-11-15
#백엔드 #성능 #데이터베이스"어드민이나 마이페이지를 만들 때, 데이터가 몇 건 안 되니까 전체 조회를 해서 프론트에 넘겼습니다."
멘토링을 하면서 주니어 개발자들의 코드를 볼 때 자주 마주치는 장면입니다. 로컬 환경에서는 데이터가 20건 남짓이라 응답 속도는 10ms도 안 걸립니다. 화면도 빠르게 뜨고 아무 문제 없어 보입니다.
하지만 운영 환경은 다릅니다. 데이터는 잠든 사이에도 쌓입니다. 데이터가 100건일 때 무심코 작성한 코드가, 서비스 오픈 3개월 뒤 데이터가 수만 건으로 늘어나는 순간 서버 전체를 멈춰 세웁니다.
메모리는 무한하지 않습니다
많은 주니어 개발자가 DB에서 데이터를 조회할 때 메모리 비용을 계산하지 않습니다. 조건 없는 전체 조회나 findAll()을 호출하면, DB는 수만 건의 데이터를 네트워크 패킷으로 쪼개어 애플리케이션으로 쏟아붓습니다.
애플리케이션은 이 수만 개의 행을 하나하나 힙 메모리에 객체로 올립니다. 사용자 한 명이 목록을 새로고침할 때마다 수십 메가바이트의 메모리가 순간적으로 잠식당합니다. 동시 요청이 10건만 겹쳐도 가비지 컬렉터가 작동하며 시스템 전체가 멈추고, 남는 것은 OutOfMemoryError와 서버 다운뿐입니다.
데이터가 적다는 건 착각입니다
"초기 서비스라 데이터가 거의 없어서 나중에 페이징을 붙이려고 했습니다."
저희가 200명 넘는 멘티를 만나며 가장 많이 들은 변명입니다. 서비스가 성공하면 데이터는 계속 늘어납니다. 데이터가 적어서 페이징이 필요 없는 게 아니라, 페이징을 구현하지 않아서 서비스가 커질 자격을 갖추지 못한 것입니다.
운영 환경을 단 한 번이라도 상상해본 개발자라면, 10건이든 100건이든 목록 조회 API에는 반드시 최대 조회 개수(limit) 제한을 둡니다. 상한선 없는 쿼리는 시스템에 시한폭탄을 심어두는 것과 같습니다.
페이징도 단순히 offset만 쓰면 안 됩니다
Pageable 객체를 붙이고 LIMIT과 OFFSET으로 페이징을 끝냈다고 안심해서는 안 됩니다. 데이터가 100만 건으로 불어났을 때 90만 번째 페이지를 조회하면 무슨 일이 벌어질까요?
DB는 앞선 90만 건의 행을 전부 읽어서 버린 뒤에야 원하는 10건을 반환합니다. 뒤로 갈수록 쿼리는 느려지고 DB의 CPU는 치솟습니다. 진짜 백엔드 엔지니어라면 데이터 특성에 맞춰 커서 기반 페이징(No-offset)을 적용할지 고민해야 합니다. 마지막으로 읽은 식별자를 기준으로 다음 데이터를 탐색하는 쿼리를 짜야 트래픽 앞에서도 무너지지 않습니다.
목록을 조회하는 모든 API는 잠재적인 장애 지점입니다. "데이터가 적으니까"라는 핑계는 기술 부채를 떠넘기는 게으름일 뿐입니다. 오늘 작성한 코드에서 상한선 없는 쿼리를 찾아내고, 페이징 기준을 세우십시오. 운영 환경을 상상하며 코드를 짜는 사람만이 진짜 백엔드 엔지니어로 남습니다.