(TypeORM) TypeORM - Repository

최건·2025년 5월 11일

참고 문서

Repository란?

  • TypeORM에서 특정 엔티티(User 등) 에 대해 데이터베이스 작업(조회, 저장, 삭제 등)을 수행하는 전용 도구
  • EntityManager와 유사하지만, 하나의 엔티티에만 집중하도록 설계되어 있어 타입 안전성(Type Safety) 이 높고, 코드가 간결해진다.

Repository는 특정 엔티티 전용의 EntityManager다.

import { User } from "./entity/User"

const userRepository = dataSource.getRepository(User)
const user = await userRepository.findOneBy({
    id: 1,
})
user.name = "Umed"
await userRepository.save(user)

주요 옵션

1. select

  • 반환되는 객체에서 가져올 컬럼만 지정
userRepository.find({
  select: {
    firstName: true,
    lastName: true,
  },
})
// → SELECT "firstName", "lastName" FROM "user"

2. relations

  • 관계 설정된 엔티티도 함께 가져옴 (JOIN)
userRepository.find({
  relations: {
    profile: true,
    photos: true,
  },
})
  • 중첩도 가능:
relations: {
  videos: {
    videoAttributes: true,
  },
}

3. where

  • 조건 설정. AND 연산자처럼 작동
where: {
  firstName: "Timber",
  lastName: "Saw",
}
  • 관계 엔티티 조건:
where: {
  project: {
    name: "TypeORM",
    initials: "TORM",
  },
}

4. OR 조건

  • 여러 조건 중 하나라도 만족하면
where: [
  { firstName: "Timber", lastName: "Saw" },
  { firstName: "Stan", lastName: "Lee" },
]

5. order

  • 정렬 지정
order: {
  name: "ASC",
  id: "DESC",
}

6. skip + take

  • pagination 구현 시 사용:
skip: 5,   // OFFSET
take: 10,  // LIMIT

MSSQL에서는 order 없으면 오류 발생하므로 함께 사용해야 함


7. withDeleted

  • softDelete된 데이터까지 포함
withDeleted: true

8. cache

  • 결과 캐싱 사용
cache: true

9. lock

lock: { mode: "optimistic", version: 1 }

조건자(Advanced Operators)

findBy() 또는 where에서 사용할 수 있는 조건자들

연산자의미예시 코드
Not(...)값이 아닌 경우Not(Equal("About #2"))
LessThan(n)n보다 작은 값LessThan(10)
MoreThanOrEqual(n)n 이상MoreThanOrEqual(5)
Like('%text%')SQL LIKELike("%out%")
ILike('%text%')대소문자 구분 없는 LIKE (Postgres)ILike("%out%")
Between(a, b)두 값 사이Between(1, 10)
In([a, b])여러 값 중 하나In(["About #2", "About #3"])
IsNull()null인 경우IsNull()
Raw(...)커스텀 SQL 삽입Raw(alias => \${alias} > NOW()`)`
And(...), Or(...)복합 조건And(Not(Equal("About #2")), ILike("%About%"))

Repository 주요 기능

기능설명
create()엔티티 인스턴스 생성
save()엔티티 저장 (insert or update 자동 감지)
remove() / delete()엔티티 삭제
find() / findOne() / findBy()데이터 조회
update() / upsert()조건부 수정 또는 없으면 삽입
preload() / merge()기존 데이터 덮어쓰기 또는 병합
increment() / decrement()수치형 필드 증감
exists() / count()존재 여부 / 개수 확인
softDelete() / restore()soft-delete 기능 사용
query() / clear()raw SQL 실행 / 테이블 비우기
createQueryBuilder()복잡한 SQL 생성기 사용 가능

사용 예시

기본 생성 & 저장

const user = repository.create({ firstName: "Timber" })
await repository.save(user)

조건 검색

await repository.find({ where: { firstName: "Timber" } })
await repository.findBy({ firstName: "Timber" }) // 더 단순

업데이트 & 업서트

await repository.update(1, { age: 30 })
await repository.upsert([{ externalId: "abc123", name: "Timber" }], ["externalId"])

삭제

await repository.delete(1)
await repository.softDelete({ name: "Timber" })
await repository.restore(1)

통계 메서드

await repository.countBy({ firstName: "Timber" })
await repository.sum("age", { active: true })
await repository.maximum("score", {})

Raw Query

await repository.query("SELECT * FROM user WHERE name = ?", ["John"])

preload() vs merge() 차이

메서드사용 상황
merge()메모리 상에서 단순 병합
preload()DB에서 엔티티 불러오고 병합하여 반환 (비동기)

Additional Options 예시

Save 시

await repository.save(users, {
  chunk: 1000, // 매우 큰 데이터 분할 저장
  transaction: false, // 트랜잭션 사용 안함
  listeners: false // subscriber 이벤트 발생 안함
})

Remove 시

await repository.remove(users, {
  chunk: 1000,
  transaction: false,
})
profile
개발이 즐거운 백엔드 개발자

0개의 댓글