콘텐츠로 이동

2023 11 16

2023-11-16

Slick에서 Tuple이 Case Class로 매핑되는 과정

case class User(id: Long, firstName: String, lastName: String, email: String)

class Users(tag: Tag) extends Table[User](tag, "users") {
    def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
    def firstName = column[String]("FIRST_NAME")
    def lastName = column[String]("LAST_NAME")
    def email = column[String]("EMAIL")
    def * = (id, firstName, lastName, email) <> ((User.apply _).tupled, User.unapply)
}
  • 여기에서 *를 봐보자
    • (id, firstName, lastName, email) 은 각각 테이블에서 얘기하는 필드
    • * 메서드는 슬릭에게 해당 튜플을 apply, unapply를 통해 매핑하라는 뜻
    • User.apply _는 Case Class의 생성자를 참조
      • (Long, String, String, String) 타입의 생성자
    • tupled 메서드는 여기에 매치시킨다는데 뭔소리여
    • User.unapply는 스칼라 컴파일러에서 제공하는 Case class의 메서드
      • User의 필드를 tuple 옵션으로 변경
  • 좀 더 *를 봐보자
    • (id, firstName, lastName, email) : 데이터베이스 테이블의 칼럼을 가지는 튜플
    • <> : Tuple4 타입과 case class User를 변환해주는 연산을 수행
      • def <>[R : ClassTag](f: (U => R), g: (R => Option[U])) = new MappedProjection[R, U](shape.toNode(value), MappedScalaType.Mapper(g.andThen(_.get).asInstanceOf[Any => Any], f.asInstanceOf[Any => Any], None), implicitly[ClassTag[R]])
    • ((User.apply _).tupled, User.unapply) : case class User와 튜플 (id, firstName, lastName, email)을 변환해주는 역할
      • 스칼라에서 케이스 클래스 만들때 apply() 메서드 쓰잖아
    • Rep[Long] -> Long 변경 절차는 lifted embedding으로 슬릭이 해줘
      • embedded DSL로써... Rep 가상 타입을 직접 접근 없이 오페레이션 수행토록
    • Slick이 Rep[Sth] -> Sth 으로 뒤에서 뚝딱 처리해줌.
      • 해당 과정은 db.run(query)를 통해 수행됨
  • Slick은 JdbcTemplate을 쓰는건가?
    • 아님
    • 슬릭은 FRM
    • 스칼라 진영에서 DB 접근 기술이 별도로 있어
    • 컴파일 타임 Safety 하도록 지원
    • 절차
      1. 테이블 정의 -> 스키마는 슬릭의 타입세이프 방식을 사용 (칼럼, 타입 관계 매핑)
      2. 슬릭은 스칼라로 써있는 데이터베이스 연산을 AST (Abstract Syntax Tree)로 만들어
      3. 슬릭은 SQL 쿼리를 JDBC를 통해 디비에 보낸다. 이때, AST를 SQL로 변경
      4. 데이터베이스로부터 결과값 받아서 정의된 타입으로 매핑해줌 (case class, tuple 등)
  • Slick vs QueryDSL
    • 공통점
      1. 타입 세이프
      2. 데이터베이스에 구애받지 않음: SQL 방언에 따라 SQL 생성 가능
      3. 쿼리 스타일: 원시 SQL 대신 프로그래밍 도움 받음
    • 차이점
      1. 언어/생태계 : Slick은 implicit, case class 등 사용
      2. 중심 사항 :
        • Slick은 데이터베이스 쿼리 액세스 라이브러리. 기능적인 방식으로 DB와 연결. SQL 직접 표현 가능
        • QueryDSL은 광범위한 데이터베이스 플랫폼 지원 (JPA, MongoDB, JDBC)
      3. 데이터 처리:
        • Slick은 JDBC 기저 위에 reactive streams. 비동기 연산 최대한
        • QueryDSL: 블락킹 연산임