47DAYS) [Spring MVC] JDBC 기반 데이터 액세스 계층 - 도메인 엔티티 및 테이블 설계, 구현

nacSeo (낙서)·2022년 12월 24일
0

◉ 학습목표

1. Spring Data JDBC 기반 도메인 엔티티 및 테이블을 설계할 수 있다.
2. Spring Data JDBC를 통한 데이터 액세스 계층을 구현할 수 있다.
  1. Spring Data JDBC 기반 도메인 엔티티 및 테이블 설계

⦿ 학습내용

☞ DDD (Domain Driven Design, 도메인 주도 설계)

✔︎ 도메인 위주의 설계 기법

☞ 도메인 (Domain)

✔︎ 애플리케이션 개발에서 사용하는 도메인이란 용어는 주로 비즈니스적인 어떤 업무 영역과 관련 있음
✔︎ 애플리케이션을 구현하기 위해 필요한 업무들을 자세히 알면 알수록 퀄리티 높은 애플리케이션 제작 가능
✔︎ 비즈니스 업무 영역을 의미하는 도메인 지식(Domain Knowleage)들을 서비스 계층에서 비즈니스 로직으로 구현

☞ DDD 사용 용어

✔︎ 애그리거트 (Aggregate)

  • 비슷한 업무의 하위 수준 도메인들의 묶음

✔︎ 애그리거트 루트 (Aggregate Root)

  • 애그리거트 내의 대표 도메인
  • 애그리거트 루트 선정 기준
    • 각 애그리거트 내 도메인 중에서 다른 모든 도메인들과 직간접적으로 연관이 있는 도메인으로 선정

☞ 테이블 간 관계 🆚 클래스 간 관계

✔︎ 데이터베이스의 테이블 간 관계외래키를 통해 맺어짐
✔︎ 도메인 엔티티 클래스 간 관계객체의 참조를 통해 맺어짐

※ 학습 예제를 바탕으로 한 엔티티 설계

※ 학습 예제를 바탕으로 한 테이블 설계

  1. Spring Data JDBC를 통한 데이터 액세스 계층 구현(1) - 도메인 엔티티 클래스 정의

⦿ 학습내용

☞ 테이블 간의 관계 🆚 클래스 간의 관계

✔︎ 테이블 간의 관계는 외래키를 통해서 이루어짐
✔︎ 클래스 간의 관계는 해당 클래스의 객체 참조를 통해서 이루어짐

☞ AggregateReference 클래스

✔︎ 다른 애그리거트 루트 간의 참조 역할 수행
✔︎ 테이블의 외래키처럼 다른 객체의 ID 값을 참조할 수 있도록 해줌

☞ 애그리거트 객체 매핑 규칙

✔︎ 모든 엔티티 객체의 상태는 애그리거트 루트를 통해서만 변경 가능❗️ 🌟🌟🌟
✔︎ 하나의 동일한 애그리거트 내에서의 엔티티 객체 참조

  • 동일한 하나의 애그리거트 내에서는 엔티티 간에 객체로 참조

✔︎ 애그리거트 루트-애그리거트 루트 간의 엔티티 객체 참조

  • 애그리거트 루트 간의 참조는 객체 참조 대신에 ID로 참조
  • 1대N 관계일 때는 AggregateReference 사용 ⭕️ → 테이블 간 외래키 방식과 동일
  • N대N 관계일 때는 참조할 테이블에 해당되는 클래스의 @Id 필드를 멤버 변수로 가지는 별도의 참조 클래스 사용
  1. Spring Data JDBC를 통한 데이터 액세스 계층 구현(2) - 서비스, 리포지토리 구현

⦿ 학습내용

☞ 리포지토리(Repository) 인터페이스

✔︎ 데이터 액세스 계층에서 데이터베이스와 상호작용하는 역할을 하는 인터페이스
✔︎ DDD(Domain Driven Design, 도메인 주도 설계)에서 사용하는 용어

☞ 리포지토리(Repository) 인터페이스 구현

✔︎ Spring Data JDBC의 CrudRepository 인터페이스를 상속하면 CrudRepository에서 제공하는 CRUD 메서드 사용 ⭕️

  • 편리하게 데이터를 데이터베이스의 테이블에 저장, 조회, 수정, 삭제 가능

✔︎ Spring Data JDBC에서는 SQL 쿼리를 대신하는 다양한 쿼리 메서드(Query Method) 작성 지원

  • 쿼리 메서드(Query Method)
    • SQL 쿼리문을 사용하지 않고 데이터베이스에 질의 가능
    • 조건에 맞는 데이터를 테이블에서 조회
    • 기본 형식 : find + By + SQL 쿼리문에서 WHERE절의 컬럼명 + (WHERE절 컬럼의 조건이 되는 데이터)
    • WHERE절의 조건 컬럼을 여러 개 지정하고 싶으면 And 사용
    • 예제
      Optional<Member> findByEmail(String email);
      Optional<Member> findByEmailAndName(String email, String name);
    • ※ 주의사항 🚨
      : findBy~에서 사용하는 컬럼명은 반드시 엔티티 클래스의 멤버 변수명으로 정의

✔︎ Spring Data JDBC에서 지원하는 쿼리 메서드의 정의가 어렵다면 @Query 애너테이션을 이용해서 SQL 쿼리 직접 작성

  • @Query 애너테이션
    • 쿼리 메서드명을 기준으로 SQL 쿼리문을 생성하는 것이 아니라, 개발자가 직접 쿼리문을 작성해서 질의
    • 복잡한 쿼리문일 때 유용 (단순 쿼리일 때는 쿼리 메서드 사용이 간결 코드 유지와 생산성 면에서 바람직)
    • 예제
      @Query("SELECT * FROM COFFEE WHERE COFFEE_ID = :coffeeId")
      Optional<Coffee> findByCoffee(Long CoffeeId);
    • :coffeeIdfindByCoffee(Long coffeeId)coffeeId 변수 값이 채워지는 동적 쿼리 파라미터(named parameter)

☞ 서비스 클래스

✔︎ Spring Data JDBC 기술이 적용된 Repository 인터페이스를 사용하도록 메서드 코드 수정

☞ 서비스 클래스 구현

✔︎ 리소스를 데이터베이스에 Insert할 경우 이미 Insert된 리소스인지 여부를 검증하는 로직이 필요
✔︎ Optional을 이용하면 데이터 검증에 대한 로직을 간결하게 작성
✔︎ 복잡한 DTO 클래스와 엔티티 클래스의 매핑은 Mapper 인터페이스에 default 메서드를 직접 구현해서 개발자가 직접 매핑 로직 작성

◉ 느낀 점

☞ 엔티티 클래스와 테이블을 예제를 통해 직접 손으로 그려보고, 인텔리제이를 통해 직접 코드를 입력해보며 설계 방법을 효과적으로 익혔던 것 같다. (그만큼 시간이 소요됐지만 ^^,,) 구현 쪽 내용들은 복잡한 코드들이 너무나도 많아 입력해보며 이해하려 해봐도 잘 이해가 가질 않는 부분들이 많았다. 반복적인 학습을 통해 익힐 필요성이 있다.

그래도 전체적으로 어느 정도 이해할 수 있었고, 추가적으로 이 것을 내 것으로 만들기 위해 많은 노력이 필요할 것으로 보인다. 내일있을 실습을 통해 좀 더 익힐 수 있는 시간이 되었으면 한다.

◉ 내일의 키워드

・ Spring Data JDBC를 이용한 데이터 액세스 실습
profile
백엔드 개발자 김창하입니다 🙇‍♂️

0개의 댓글