웹 개발
정렬 순서가 예상과 다를 때
데이터를 가져오는 순서가 자꾸 바뀌거나, 페이지네이션에서 같은 항목이 중복으로 보이는 경우가 있다. 원인을 빠르게 찾는 방법을 정리했다.
정렬 문제는 보통 조용하게 발생한다. 테스트할 때는 데이터가 적어서 눈에 띄지 않다가, 프로덕션에서 데이터가 많아지면 나타난다.
데이터베이스 쿼리부터 확인
Prisma로 데이터를 가져올 때 정렬 옵션을 명시적으로 지정했는지 본다.
// 잘못된 방식 - 정렬 없음
const users = await prisma.user.findMany();
// 올바른 방식 - 명확한 정렬
const users = await prisma.user.findMany({
orderBy: { createdAt: 'desc' }
});
ORDER BY 절이 없으면, 데이터베이스는 아무 순서로나 반환할 수 있다. 특히 인덱스가 있으면 인덱스 순서대로 오지만, 데이터가 갱신되면서 변할 수 있다.
페이지네이션에서 중복 항목 문제
페이지네이션을 할 때 정렬이 일관되지 않으면 항목이 중복되거나 빠질 수 있다.
// 문제 있는 코드
const page1 = await prisma.user.findMany({
take: 10,
skip: 0
// orderBy 없음!
});
const page2 = await prisma.user.findMany({
take: 10,
skip: 10
// orderBy 없음!
});
// 올바른 코드
const page1 = await prisma.user.findMany({
take: 10,
skip: 0,
orderBy: { id: 'asc' } // 고유값으로 정렬
});
특히 동일한 값을 가진 컬럼으로 정렬하면 (예: createdAt이 같은 여러 항목), 순서가 불안정해진다. 고유한 컬럼(id, 타임스탬프)을 보조 정렬로 추가한다.
다중 정렬 순서
const users = await prisma.user.findMany({
orderBy: [
{ department: 'asc' },
{ name: 'asc' }
]
});
첫 번째 정렬 조건(department)이 같은 항목들은 두 번째 조건(name)으로 정렬된다.
정렬 키의 컬럼이 인덱스에 포함되는지
정렬 성능을 위해서는 해당 컬럼에 인덱스가 있어야 한다.
model User {
id Int @id
email String
createdAt DateTime
@@index([createdAt]) // createdAt로 정렬할 때 빠르다
@@index([createdAt, id]) // 페이지네이션 시 이상적
}
클라이언트 측 정렬 확인
backend에서 정렬된 데이터를 받았는데, frontend에서 또 정렬하고 있지는 않은지 본다.
// React에서
const sortedUsers = users.sort((a, b) =>
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
);
API에서 이미 정렬된 데이터를 받았다면, 클라이언트 정렬은 불필요하고 오히려 느려질 수 있다.
쿼리 로그 확인
실제로 어떤 SQL이 실행되는지 본다.
// Prisma 쿼리 로깅 활성화
const prisma = new PrismaClient();
prisma.$on('query', (e) => {
console.log('Query:', e.query);
console.log('Params:', e.params);
console.log('Duration:', e.duration + 'ms');
});
또는 데이터베이스에서 직접:
-- PostgreSQL (slow query log)
SET log_statement = 'all';
SET log_min_duration_statement = 0;
테스트 데이터로 재현
정렬이 불안정한지 확인하려면, 같은 조건의 데이터를 여러 개 생성한 후 여러 번 쿼리한다.
# 예: createdAt이 모두 같은 데이터 100개
for i in {1..100}; do
curl -X POST http://localhost:3000/api/users \
-d '{"name": "User'$i'"}'
done
# 그 다음 여러 번 조회해서 순서가 바뀌는지 확인
curl http://localhost:3000/api/users?page=1
curl http://localhost:3000/api/users?page=1
curl http://localhost:3000/api/users?page=1
순서가 매번 바뀌면, 정렬이 불안정한 것이다. orderBy에 고유 컬럼을 추가해서 안정화한다.