Dandy Now!
  • [Sequelize] `findAll` 옵션: `raw`와 `nest`는 언제 사용할까?
    2025년 04월 28일 14시 15분 09초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    Sequelize findAll 옵션: rawnest는 언제 사용할까?

    Node.js에서 Sequelize ORM을 사용하다 보면 데이터를 조회하는 findAll 메서드를 자주 사용하게 된다. 이때 raw: truenest: true 같은 옵션들을 마주치게 되는데, 이 옵션들이 정확히 어떤 역할을 하고 언제 사용하는 것이 좋은지 정리해 보았다.

    1. Sequelize findAll의 기본 동작

    기본적으로 findAll 메서드는 데이터베이스에서 조회한 결과를 Sequelize 모델 인스턴스(Instance)의 배열로 반환한다.

    // 예시: User 모델 사용
    const users = await models.User.findAll({
      where: { status: 'active' }
    });
    
    // users 배열의 각 요소는 Sequelize 모델 인스턴스이다.
    if (users.length > 0) {
      console.log(users[0].name); // 인스턴스의 속성 접근
      // await users[0].update({ name: 'newName' }); // 인스턴스 메서드 사용 가능
    }
    • 장점: 모델 인스턴스는 내장된 update, destroy, save 등의 유용한 메서드를 제공하며, 가상 필드나 연관 관계 메서드 접근이 용이하다.
    • 단점: 단순 데이터 조회가 목적일 경우, 인스턴스 생성에 따른 약간의 메모리 및 성능 오버헤드가 발생할 수 있다.

    2. raw: true 옵션: 성능 최적화의 시작

    조회한 데이터를 단순히 읽기용으로 사용하거나 다른 형태로 가공할 목적이라면, Sequelize 모델 인스턴스까지 만들 필요가 없을 수 있다. 이때 raw: true 옵션이 유용하다.

    const activeUserNames = await models.User.findAll({
      where: { status: 'active' },
      attributes: ['name'], // 필요한 컬럼만 지정
      raw: true, // <-- 여기!
    });
    
    // activeUserNames 배열의 각 요소는 순수 JavaScript 객체이다.
    // 예: [ { name: '김일남' }, { name: '김이남' } ]
    if (activeUserNames.length > 0) {
      console.log(activeUserNames[0].name); // 객체의 속성 접근
      // activeUserNames[0].update is not a function 오류 발생! (인스턴스 메서드 없음)
    }
    • raw: true: Sequelize가 모델 인스턴스를 생성하는 대신, 조회 결과를 순수한 JavaScript 객체(Plain JavaScript Object) 배열로 반환하도록 한다.
    • 장점: 모델 인스턴스 생성 비용이 없으므로, 특히 대량의 데이터를 조회할 때 성능 및 메모리 사용량 측면에서 이점이 있다. 조회한 데이터를 가공하여 API 응답으로 보내거나 다른 데이터 구조로 변환할 때 편리하다.
    • 단점: 반환된 객체는 Sequelize 인스턴스 메서드(예: update, save)를 가지고 있지 않다.

    3. nest: true 옵션: JOIN 결과 구조화

    nest: true 옵션은 주로 include 옵션을 사용하여 연관된 테이블을 함께 조회(JOIN)할 때, 그리고 raw: true 옵션과 함께 사용될 때 의미가 있다. JOIN된 결과를 중첩된 객체 형태로 만들어준다.

    // 가정: User 모델은 Profile 모델과 1:1 관계 (User.hasOne(models.Profile))
    
    // 1. raw: true 만 사용 (nest: false 와 동일)
    const usersFlat = await models.User.findAll({
      include: {
        model: models.Profile,
        attributes: ['bio']
      },
      attributes: ['id', 'name'],
      where: { status: 'active' },
      raw: true,
    });
    // 결과 예시 (평면적):
    // [
    //   { id: 1, name: '김일남', 'Profile.bio': 'Developer' },
    //   { id: 2, name: '김이남', 'Profile.bio': 'Designer' }
    // ]
    
    // 2. raw: true 와 nest: true 함께 사용
    const usersNested = await models.User.findAll({
      include: {
        model: models.Profile,
        attributes: ['bio']
      },
      attributes: ['id', 'name'],
      where: { status: 'active' },
      raw: true,
      nest: true, // <-- 여기!
    });
    // 결과 예시 (중첩적):
    // [
    //   { id: 1, name: '김일남', Profile: { bio: 'Developer' } },
    //   { id: 2, name: '김이남이남', Profile: { bio: 'Designer' } }
    // ]
    • nest: true: includeraw: true가 함께 사용될 때, JOIN된 연관 모델의 속성들을 점(.)으로 연결된 평면적인 키 대신, 중첩된 객체 안으로 구조화한다.
    • 주의: include 옵션 없이 단일 테이블만 조회하거나, raw: true 옵션이 없다면 nest: true는 아무런 효과를 내지 못한다. 불필요하게 사용하면 코드를 혼란스럽게 만들 수 있다.

    4. 언제 어떤 옵션을 사용해야 할까? (요약)

    • 데이터 조회 후 바로 사용하거나 인스턴스 메서드가 필요할 때: 기본값 사용 (옵션 X)
    • 단순 데이터 조회(읽기 전용)가 목적이고 성능이 중요할 때: raw: true 사용
    • JOIN된 데이터를 조회하고 그 결과를 중첩된 순수 객체로 받고 싶을 때: include + raw: true + nest: true 사용
    • JOIN된 데이터를 모델 인스턴스 형태로 다루고 싶을 때: include 사용 (옵션 X 또는 raw: false)
    • JOIN이 없을 때: nest: true는 사용하지 않는다.

    각 옵션의 정확한 역할을 이해하고 상황에 맞게 사용한다면, Sequelize를 더욱 효율적으로 활용하고 코드의 의도를 명확하게 전달할 수 있을 것이다.

    728x90
    반응형
    댓글