• 티스토리 홈
  • 프로필사진
    아몬드맛빼빼로
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
아몬드맛빼빼로
  • 프로필사진
    아몬드맛빼빼로
    • 분류 전체보기 (49) N
      • Java (10) N
      • C (3)
      • Springboot (7)
      • Kotlin (2)
      • 회고 (5)
      • Backend (14) N
      • 기타 (5)
      • DevOps (3)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
# Home
# 공지사항
#
# 태그
# 검색결과
# 방명록
  • [Backend] Exposed DAO vs DSL
    2025년 12월 01일
    • 아몬드맛빼빼로
    • 작성자
    • 2025.12.01.:16
    반응형

    Spring Boot와 Exposed ORM

    보통 Spring Boot에선 JPA를 ORM으로 사용한다.그러나 Spring Boot와 Kotlin 조합으로 사용한다면 ORM 선택지가 하나 더 늘어난다고 볼 수 있는데 바로 Exposed가 그것이다.

    Spring Boot에서 Spring Data JPA와 함께 사용한다면 JpaRepository를 확장하여 사용하는 방식을 주로 사용하게 될텐데 Exposed는 비슷하게 2가지 방법을 지원한다.아래에서 그 2가지 방법을 비교해볼 것이다.

    DAO

    보통 DTO(Data Transfer Object),DAO(Data Access Object),VO(Value Object)로 많이 묶여서 한번에 공부하게 되는 DAO는 많이들 쓰이는 Spring Data JPA에선 사실상 사용되지 않는 방식이다.그러나 Exposed에선 조금 이야기가 다른데 Kotlin의 특징을 잘 활용하고 현대적으로 재해석되어 설계되었기에 상당히 괜찮아졌다.

     

    Exposed의 DAO는 크게 3가지 특징이 있다.

    • Active Record 패턴 기반
    • 엔티티 클래스 중심의 ORM 접근
    • 객체 지향적 데이터 조작
    object Users : IntIdTable() {
        val name = varchar("name", 50)
    }
    
    class User(id: EntityID<Int>) : IntEntity(id) {
        companion object : IntEntityClass<User>(Users)
        var name by Users.name
    }
    
    val user = User.findById(1)
    val allUsers = User.all()
    
    val newUser = User.new {
        name = "John"
    }
    
    user.name = "Jane"

    간단하게 사용가능하고 findById와 같은 것들만 보면 이 패턴을 쓰는게 JPA와 유사하게 보일 수도 있다.그러나 해당 방식은 단점도 명확하다.

    • 복잡한 쿼리 제한
    • 오버헤드
    • N+1 등 성능 문제

    복잡한 쿼리를 만들지 못하고 그렇다 보니 연관관계가 복잡할 때 N+1 등의 문제가 쉽게 발생하여 이를 해결하기가 어렵다.

    DSL

    DSL(Domain Specific Language)은 SQL과 유사하지만 타입 안전한 쿼리 빌더를 사용하는 방식으로 함수형 프로그래밍이 가능하고 직접적인 DB 테이블 조작이 가능하다.다음과 같은 장점들이 있다.

    • 성능 최적화 용이
    • 복잡한 쿼리 작성 용이
    • 경량
    object Users : Table() {
        val id = integer("id").autoIncrement()
        val name = varchar("name", 50)
        override val primaryKey = PrimaryKey(id)
    }
    
    val users = Users.selectAll().map { 
        User(it[Users.id], it[Users.name]) 
    }
    
    Users.insert {
        it[name] = "John"
    }
    
    Users.update({ Users.id eq 1 }) {
        it[name] = "Jane"
    }

    하지만 명확한 단점도 있는데 

    • 보일러플레이트 발생
    • 관계 관리 수동
    • 높은 초기 학습 비용

    DSL 방식은 JPA의 QueryDSL 방식과 유사하게 쿼리를 '빌드'하는 것에 가깝기 때문에 DAO 방식에 비해 상대적으로 사용하기 어렵다.

    뭘 선택해서 써야 하는데

    정답은 없지만 크게 보면 다음과 같은 선택기준이 있을 것이다.

    DSL?

    • 집계 연산 등 복잡한 쿼리가 필요한 경우
    • 대량 데이터 또는 배치 처리
    • 성능 최적화가 필수적인 경우

    DAO?

    • 단순한 CRUD 작업이 필요한 경우
    • 빠른 개발이 필요한 경우
    • 객체관 관계 정리 및 도메인 분리가 명확한 경우

    또한 특정 1가지만을 선택해야 하는것이 아닌 혼용 전략을 취할 수도 있다.

    val user = User.findById(1)
    user.name = "Updated"
    
    val stats = Users
        .slice(Users.name, Users.createdAt.count())
        .selectAll()
        .groupBy(Users.name)
        .having { Users.createdAt.count() greater 5 }

    Spring과 쓸때

    결론적으론 Spring에서 사용 할 때 자연스러운 것은 DSL 방식이다.해당 접근법이 일반적으로 Spring Data에서 권장하는 엔티티(Entity)와 레포지터리(Repository)를 분리하는 패턴에 적합하고 DAO는 암묵적 트랜젝션을 사용하기에 Spring Data의 명시적 트랜젝션과는 조금 차이가 있다.필자도 DSL 방식을 선호하며 보일러플레이트와 같은 문제는 Kotlin의 확장 함수와 같은 해결책이 있기에 성능 최적화를 더 할 수 있고 깔끔한 아키택쳐 구축이 가능한 DSL을 선호한다.

    저작자표시 비영리 변경금지 (새창열림)

    'Backend' 카테고리의 다른 글

    [Backend] pt-online-schema-change  (0) 2025.09.04
    [Backend] 네이버가 오픈소스를..? Fixture Monkey  (0) 2025.08.24
    [Backend] EDA  (0) 2025.07.15
    [Backend] OAuth와 JWT  (0) 2025.06.08
    [Backend] MQ  (0) 2025.05.05
    다음글
    다음 글이 없습니다.
    이전글
    이전 글이 없습니다.
    댓글
조회된 결과가 없습니다.
스킨 업데이트 안내
현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
목차
표시할 목차가 없습니다.
    • 안녕하세요
    • 감사해요
    • 잘있어요

    티스토리툴바