TypeORM은 Node.js 생태계에서 매우 인기가 많은 ORM(Object-Relational Mapping) 라이브러리 중 하나입니다. 많은 메소드를 제공하며 특히 데이터베이스에서 데이터를 조회할 때 자주 사용되는 메소드 중 하나가 바로 getRawOne()입니다. 이 포스트에서는 이 메소드의 반환값에 대한 흔한 오해와 이를 올바르게 사용하는 방법을 살펴보겠습니다.

getRawOne 메소드란?

TypeORM에서 데이터 조회를 위한 메소드는 크게 두 가지 형태가 있습니다:

  • Entity 객체를 반환하는 메소드: findOne(), getOne()
  • Raw 객체(JSON 형태)를 반환하는 메소드: getRawOne(), getRawMany()

이 중 getRawOne()은 SQL 쿼리로부터 데이터를 가져올 때, Entity 객체가 아닌 Raw 데이터를 반환합니다. 여기서 Raw 데이터란 데이터베이스에서 조회된 그대로의 JSON 형태의 데이터를 의미합니다.

왜 Entity가 아닌 Raw 데이터를 반환하는가?

많은 개발자들이 getRawOne()을 사용하다가 종종 다음과 같은 에러 메시지를 접하게 됩니다:

TypeError: result.someEntityMethod is not a function

이는 반환된 객체가 Entity가 아니라 단순한 Raw 데이터이기 때문입니다. Raw 데이터는 Entity 클래스에 정의된 메소드와 같은 부가 기능을 가지지 않고, 순수한 데이터만을 갖고 있는 객체입니다.

특히, 특정 컬럼만 조회하거나 SUM(), COUNT(), AVG()와 같은 집계 함수를 사용하여 복합적인 쿼리를 구성했을 때는 Entity로의 반환이 적합하지 않습니다. 이 때문에 TypeORM은 Raw 데이터 형태로 결과를 반환합니다.

Raw 데이터를 Entity로 변환하는 방법

Raw 데이터를 받아 이를 다시 Entity로 변환하여 사용하고 싶다면, 다음과 같은 방법을 사용할 수 있습니다:

class-transformer의 plainToInstance 사용

가장 많이 사용되는 방법은 class-transformer 라이브러리의 plainToInstance() 함수를 사용하는 것입니다:

import { plainToInstance } from 'class-transformer';

const rawResult = await repository
  .createQueryBuilder("user")
  .select(["user.id", "user.firstName", "user.lastName"])
  .getRawOne();

const userEntity = plainToInstance(User, rawResult);

이 방법을 사용하면 Entity 클래스에 정의된 메소드와 프로퍼티를 모두 사용할 수 있습니다.

직접 Entity 생성자를 통해 변환

조금 더 직접적인 방법으로 Entity 클래스의 생성자를 활용할 수도 있습니다:

const rawResult = await repository
  .createQueryBuilder("user")
  .select(["user.id", "user.firstName", "user.lastName"])
  .getRawOne();

const userEntity = new User(rawResult);

하지만 이 방식은 생성자의 구조와 Raw 데이터의 키가 정확히 일치해야 하며, TypeORM의 일부 내부 로직과 충돌할 수 있으니 주의가 필요합니다.

언제 Raw 데이터를 사용해야 할까?

getRawOne()은 다음과 같은 경우에 적극적으로 사용하면 좋습니다:

  • 복잡한 SQL 쿼리를 수행해야 하는 경우
  • 특정 컬럼만 선택적으로 조회할 때
  • 집계함수(SUM, COUNT 등)를 사용할 때
  • 빠른 성능이 중요한 리포트 또는 분석성 데이터 조회 시

이 경우 불필요한 Entity 객체의 메모리 사용을 줄이고, 성능을 향상시킬 수 있습니다.

결론

TypeORM의 getRawOne() 메소드를 정확히 이해하고 활용하면 데이터 조회 시 더 유연하고 효율적인 프로그래밍이 가능합니다. Entity로의 변환이 필요하다면 class-transformer를 사용하는 방식을 추천하며, Raw 데이터를 사용하는 상황을 잘 파악하여 효율적으로 메소드를 선택하시기 바랍니다.