[Database][TIL] ORM을 사용하면서 쿼리가 복잡해질 경우

Trippy·2024년 2월 6일

DB

목록 보기
5/5
post-thumbnail

ORM

ORM(Object-Relational-Mapping)을 사용하면 일반적으로 쿼리 작성과 데이터베이스와의 상호작용이 훨씬 편리하지만, 복잡한 쿼리의 경우에는 ORM만으로는 처리하기 어려울 수 있다. 이러한 상황에서 다음과 같은 방법들을 고려해 볼 수 있다.

1. Raw Query 사용하기.

  • ORM에서 제공하는 추상화 기능만으로는 처리하기 어려운 복잡한 쿼리나 최적화가 필요한 상황에서는 ORM이 지원하는 Raw SQL 기능을 사용할 수 있다. 이를 통해 성능을 향상시키고 복잡한 쿼리를 보다 효율적으로 처리할 수 있다.

예를 들어 내가 자주 사용하는 TypeORM에서 제공하는 Raw SQL기능을 활용하여 해결할 수 있는데 이를 통해 추상화 기능을을 벗어나 데이터베이스에 직접 SQL 쿼리를 실행할 수 있으며 이는 성능 최적화나 복잡한 쿼리를 처리해야 하는 상황에서 유용하다.

TypeORM에서는 EntityManagerquery메소드를 사용하여 Raw SQL쿼리를 실행할 수 있다.

async function executeComplexQuery() {
    const entityManager = getManager();
    const results = await entityManager.query(`
        SELECT u.*, o.order_count
        FROM users u
        LEFT JOIN (
            SELECT user_id, COUNT(*) AS order_count
            FROM orders
            GROUP BY user_id
        ) o ON u.id = o.user_id
        WHERE u.active = true
    `);
    console.log(results);
}

주의사항

  • SQL Injection
    Raw SQL 쿼리를 사용할 때는 SQL Injection 공격에 주의해야 한다. 사용자 입력을 포함하는 쿼리를 작성할 때는 항상 파라미터화된 쿼리를 사용하고, 사용자 입력을 직접 쿼리에 포함하지 않도록 한다.
  • 성능 최적화
    복잡한 쿼리를 사용할 때는 성능에 주의해야 한다. 가능한 인덱스를 활용하고, 쿼리 플랜을 분석하여 성능을 최적화하는 것이 중요하다.

2. 쿼리 최적화

  • Select 필드 최소화
    필요한 필드만 선택하여 데이터를 가져오는 것이 성능에 도움이 된다.
  • Join 사용 최소화
    가능하면 join 사용을 최소화하고, 필요한 경우에만 사용한다. ORM에서 제공하는 lazy loading, eager loading 같은 기능을 적절히 활용하는 것도 중요하다.
  • 인덱스 활용
    데이터베이스의 인덱스를 적절히 활용하여 조회 성능을 향상 시킬 수 있다.

Lazy loading, Eager loading이란?

lazy loading

  • 연관된 엔티티나 컬렉션을 실제로 사용하는 순간까지 데이터 로딩을 지연시키는 방법이다., 즉 처음에 엔티티를 로드할 때는 연관된 데이터를 로드하지 않고, 해당 데이터에 접근할 때 비로소 해당 데이터를 로드하는 방식이다.

Eager loading

  • 연관된 엔티티나 컬렉션을 최초의 엔티티 로드 시에 함께 로드하는 방법이다. 즉, 처음부터 필요한 모든 데이터를 사전에 로드하는 방식으로, 연관 데이터에 별도의 쿼리 없이 즉시 접근할 수 있다.

3. Cashing 사용

데이터베이스 쿼리 결과를 캐싱하여 재사용함으로써 데이터베이스 부하를 줄이고 성능을 향상시킬 수 있다. ORM에서 제공하는 캐싱 기능을 활용하거나, 외부 캐시 시스템 ( Redis ) 를 도입할 수 있다.

4. 비즈니스 로직 분리

복잡한 쿼리가 발생하는 원인 중 하나는 비즈니스 로직이 데이터베이스 쿼리 내에 과도하게 포함되어 있는 경우이다. 비즈니스 로직을 데이터베이스 쿼리와 분리하여, 가능한 한 애플리케이션 레벨에서 처리하도록 한다.

5. 성능 모니터링 및 분석

사실상 가장 중요하고도 많이 투자를 하게 될 부분이라고 생각한다 애플리케이션의 성능을 주기적으로 모니터링하고 분석하여 병목 지점을 찾아내고 개선한다. 이 과정에서 ORM이 생성하는 쿼리를 확인하고, 필요한 경우 최적화를 수행할 수 있다.


ORM을 사용하면 개발 생산성이 향상되지만, 성능 문제가 발생할 수 있으므로 적절한 최적화 전략과 함께 사용하는 것이 중요하다. 필자가 프로젝트 중 겪었던 N+1 쿼리 문제등도 이처럼 ORM에서 제공하는 Query Builder로 sql 쿼리를 동적으로 작성할 수 있는 기능을 사용하여 복잡한 쿼리를 더욱 간단하게 작성하는 방식으로 해결한 바 있었다.

관련 내용은 `https://velog.io/@jgw987/DatabaseTIL-%EB%8C%80%EB%9F%89%EC%9D%98-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B2%98%EB%A6%AC-%EC%A0%91%EA%B7%BC-%EB%B0%A9%EC%8B%9D-N1-%EC%BF%BC%EB%A6%AC-%EB%AC%B8%EC%A0%9C

profile
감금 당하고 개발만 하고 싶어요

0개의 댓글