목차
06. 데이터베이스 연동
ㄴ6.1 마리아DB 설치
ㄴ6.2 ORM
ㄴ6.3 JPA
ㄴ6.4 하이버네이트
ㄴ6.4.1 Spring Data JPA
ㄴ6.5 영속성 컨텍스트
ㄴ6.5.1 엔티티 매니저
ㄴ6.5.2 엔티티의 생명 주기
ㄴ6.6 데이터베이스 연동
ㄴ6.6.1 프로젝트 생성
ㄴ6.7 엔티티 설계
ㄴ6.7.1 엔티티 관련 기본 어노테이션
ㄴ6.8 리포지토리 인터페이스 설계
ㄴ6.8.1 리포지토리 인터페이스 생성
ㄴ6.8.2 리포지토리 메서드의 생성규칙
ㄴ6.9 DAO 설계
ㄴ6.9.1 DAO 클래스 생성
ㄴ6.10 DAO 연동을 위한 컨트롤러와 서비스 설계
ㄴ6.10.1 서비스 클래스 만들기
ㄴ6.10.2 컨트롤러 생성
ㄴ6.10.3 Swagger API를 통한 동작확인
ㄴ6.11 [한걸음 더] 반복되는 코드의 작성을 생략하는 방법 - 롬복
ㄴ6.11.1 롬복 설치
ㄴ6.11.2 롬복 적용
ㄴ6.11.3 롬보의 주요 어노테이션
애플리케이션은 데이터(리소스)를 주고받는 것이 주 목적이다.
엔터프라이즈급 애플리케이션에서 정상적으로 로직이 동작하기 위해서는 데이터베이스가 꼭 필요합니다.
이 책에서는 그중에서도 가장 널리사용되는 마리아DB(MariaDB)를 애플리케이션에 적용한다.
6.1 마리아DB 설치
Download MariaDB Server - MariaDB.org
REST API Release Schedule Reporting Bugs … Continue reading "Download MariaDB Server"
mariadb.org
자신에게 맞는 운영체제와 아키텍쳐를 고른 다음 경로의 편의성을 위해 MSI Package로 다운로드한다.
Mirror는 이미지처럼 Blendbyte - Taipei로 설정하면 됨. 예전에는 South Korea 버전이 있긴 했으나 없어졌다.
MariaDB Server Version은 적당한 LTS으로 잘 다운로드 하자.
설치 이미지는 다음과 같다.
여기서 계속 Next를 누르다 보면 이 창이나오는데 Use UTF-8 체크하고 비밀번호를 설정해준다.
비밀번호는 꼭 잊지않게 기억하거나 보관해야한다.. root 비밀번호를 잃어버리면 어딜가나 귀찮아진다.
그럼 이게 나온다.
포트는 3306 포트가 기본인데 이전에 데이터베이스를 설치한 적이 있으면 자동으로 다른 포트번호로 매핑된다고한다. 나는 mysql을 설치해서 당연히 3307과 같은 다른 포트 넘버가 나올 줄 알았는데 3306으로 지정되서 나와서 그냥 넘어갔다..
포트넘버가 충돌하면 뭐 cmd 창이나 기타 cli 창으로 바꾸거나 kill하면 되니까 뭐.. (?)
이렇게 기본 설정을 그대로 유지한채로 설치를 마치면 서드파티 도구로 HeidiSQL이 함께 설치 된다고 함.
HeidiSQL이란 데이터 베이스에 접속해서 관리하는 GUI 도구라고 한다.
그러나 나는 IntelliJ에서 연결하고 그곳에서 데이터베이스를 실행할 것이다.
데이터베이스 생성 쿼리 : CREATE DATABASE springboot; -> springboot 이름의 데이터베이스가 생성 된다.
6.2 ORM
ORM은 Object Relational Mapping의 줄임말로 객체 관계 매핑을 의미한다. 자바와 같은 객체 지향 언어에서 의미하는 객체와 RDB(Relational Database)의 테이블을 자동으로 매핑해주는 방법이다.
객체지향 언어에서의 객체 = Class.
그러나 클래스는 데이터베이스의 table과 매핑하기 위해 만들어진 것이 아니기 때문에 RDB 테이블과 어ㅉ러수 없는 불일치가 존재한다.
이런 불일치와 제약사항을 해결해주는 것이 ORM이다.
springboot에서 @Entity하나면 ORM이 매핑해주고 자동으로 해당 테이블이 생성된다.
ORM의 장점
- ORM을 사용하면서 데이터베이스 쿼리를 객체지향적으로 조작할 수 있다.
- 객체지향적으로 데이터베이스에 접근할 수 있어 코드의 가독성을 높임
- 쿼리문을 작성하는 양이 현저히 줄어들어 개발 비용이 줄어든다.
- 재사용 및 유지보수가 편리하다.
- ORM을 통해 매핑된 객체는 모두 독립적으로 작성되어 있어 재사용에 용이함
- 객체들은 각 클래스로 나뉘어 있어 유지보수가 수월하다
- 데이터베이스에 대한 종속성이 줄어든다
- ORM을 통해 자동 생성된 SQL문은 객체를 기반으로 데이터베이스 테이블을 관리하기 때문에 데이터베이스에 종속적이지 않다.
- 데이터베이스를 교체하는 상황에서도 비교적 적은 리스크를 부담한다.
ORM의 단점
- ORM만으로 온전한 서비스를 구현하기에는 한계가 있다.
- 복잡한 서비스의 경우 직접 쿼리를 구현하지 않고 코드를 구현하기 어렵다.
- 복잡한 쿼리를 정확한 설계 없이 ORM만으로 구성하게 되면 속도 저하 등의 성능 문제가 발생할 수 있다.
- 애플리케이션의 객체 관점과 데이터베이스의 관계 관점의 불일치가 발생한다.
- 세분성(Granularity): ORM의 자동설계 방법에 따라 데이터베이스에 있는 테이블의 수와 애플리케이션의 엔티티(Entity) 클래스의 수가 다른 경우가 생긴다. (클래스가 테이블의 수보다 많아질 수 있다.)
- 상속성(Inheritance): RDBMS에는 상속이라는 개념이 없다.
- 식별성(Identity): RDBMS는 기본키(primary key)로 동일성을 정의한다. 하지만 자바는 두 객체의 값이 같아도 다르다고 판단할 수 있다. 식별과 동일성의 문제이다.
- 연관성(Associations): 객체지향 언어는 객체를 참조함으로써 연관성을 나타내지만 RDBMS는 외래키(foreign key)를 삽입함으로써 연관성을 표현합니다. 또한 객체 지향 언어에서 객체를 참조할 때는 방향성이 존재하지만, RDBMS에서 외래키를 삽입하는 것은 양방향의 관계를 가지기 때문에 방향성이 없다.
- 탐색(Navigation): 자바와 RDBMS는 어떤 값(객체)에 접근하는 방식이 다르다. 자바에서는 특정 값에 접근하기 위해 ㄱㄱ체 참조 같은 연결 수단을 활용한다. 이 방식은 객체를 연결하고 또 연결해서 접근하는 그래프 형태의 접근 방식이다.( ex> member.getOragniztion().getAddress()와 같이 접근하는 방법) 그러나 RDBMS에서는 쿼리를 최소화 하고 조인(JOIN)을 통해 여러 테이블을 로드하고 값을 추출하는 접근방식을 채택하고 있다.
- 데이터베이스에 대한 종속성이 줄어든다
- ORM을 통해 자동 생성된 SQL문은 객체를 기반으로 데이터베이스 테이블을 관리하기 때문에 데이터베이스에 종속적이지 않다.
- 데이터베이스를 교체하는 상황에서도 비교적 적은 리스크를 부담한다.
6.3 JPA
JPA(Java PErsistence API)는 자바 진영의 ORM 기술 표준으로 채택된 인터페이스의 모음입니다.
ORM이 큰 개념이라면 JPA는 더 구체화된 스펙을 포함한다.
즉, JPA는 어떻게 동작해야하는지에 대한 메커니즘을 정리한 표준 명세로 생각하면 된다. (실제로 동작하는 의미가 아님)
앞전에 ORM 자리가 JPA의 자리인 것이다. JPA의 역할 = ORM
JPA의 메커니즘을 보면 내부적으로 JDBC를 사용하나 개발자가 직접 JDBC를 구현하는 것이 아닌 JPA가 적절한 SQL을 생성하고 데이터 베이스를 조작해서 객체를 자동 매핑한다.
JPA 기반의 구현체는 그림 6.11과 같이 대표적으로 세가지가 있으나 하이버네이트(Hibernate)가 가장 많이 사용되는 구현체이다.
6.4 하이버네이트
하이버네이트는 자바의 ORM프레임 워크이며, JPA가 정의하는 인터페이스를 구현하는 JPA 구현체이다.
여기서는 우리는 spring boot에서 하이버네이트의 기능이 더욱더 편리해진 모듈인 Spring Data JPA를 활용한다는 점만 짚고, 사용할 기능에 대한 개념은 6.5절에서 살펴보겠다.
Spring Data JPA = JPA를 편리하게 사용할 수 있도록 지원하는 스프링 하위 프로젝트 중 하나.
- CRUD 처리에 필요한 인터페이스를 제공
- 하이버네이트의 엔티티매니저를 직접 다루지 않고 리포지토리를 정의해 사용함으로써 스프링이 적합한 쿼리를 동적으로 생성하는 방식으로 데이터베이스를 조작함.
- 하이버네이트에서 자주 사용되는 기능을 더 쉽게 사용할 수 있도록 구현된 라이브러리
6.5 영속성 컨텍스트
영속성 컨텍스트(Persistence Context)는 두가지 기능을 수행한다.
- 애플리케이션과 데이터베이스 사이에서 엔티티와 레코드의 괴리를 해소하는 기능
- 객체를 보관하는 기능
영속성 컨텍스트는 세션 단위의 생명주기를 가짐.
데이터베이스에 접근하기 위한 세션이 생성되면 영속성 컨텍스트가 만들어지고,
세션이 종료되면 영속성 컨텍스트도 없어진다.
엔티티 매니저는 이러한 일련의 과정에서 영속성 컨텍스트에 접근하기 위한 수단으로 사용된다.
엔티티 매니저
엔티티 매니저(EntityManager) : 엔티티를 관리하는 객체, 데이터베이스에 접근해서 CRUD 작업을 수행.
Spring Data JPA를 사용하면 리포지토리를 사용해서 데이터베이스에 접근하는데, 이때 실제 내부 구현체인 SimpleJpaRepository는 다음과 같다.
이렇게 엔티티 매니저가 사용됨을 알 수 있고 엔티티 매니저는 엔티티 매니저 팩토리(EntityManagerFactory)가 만든다.
엔티티 매니저 팩토리는 데이터 베이스에 대응하는 객체로서 스프링 부트에서 자동 설정 기능이 있기 때문에
application.properties등과 같은 파일에 최소한의 설정으로 동작한다. 하이버네이트도 의존성을 추가해주면 사용 가능하다.
---> 책의 설명이 예전 설명같음. 엔티티 매니저 팩토리를 어디서 알 수 있는지 아시는 분?
엔티티의 생명주기
엔티티 객체는 영속성 컨텍스트에서 다음과 같은 4가지 상태로 구분된다.
- 비영속(New) : 영속성 컨텍스트에 추가되지 않은 상태
- 영속(Managed) : 영속성 컨텍스트에 의해 엔티티 객체가 관리되는 상태
- 준영속(Detached) : 영속성 컨텍스트에 의해 관리되던 엔티티 객체가 컨텍스트와 분리된 상태
- 삭제(Removed) : 데이터베이스에서 레코드를 삭제하기 위해 영속성 컨텍스트에 삭제 요청을 한 상태
6.6 데이터베이스 연동
프로젝트 폴더에서 main> resources 폴더에서 application.yml파일이든 application.properites 파일이든 db설정을 해주면 연동된다.
다음음 application.prorperties 파일의 예시이다. 자신의 password를 쓰면되고 유의해야할 점은 깃헙 올릴때 .gitignore에 해당 파일을 적어 보안에 유의하자
마찬가지로 의존성에 사용할 database를 추가해야한다.
코드의 6번은 하이버네이트로 데이터베이스를 조작할 때 어떤 옵션으로 둘지 쓰면 된다.
참고로 운영환경에서는 create, create-drop, update 옵션은 보통 사용하지 않고 validate를 사용한다.
7번은 보통 true로 두어 sql 쿼리를 확인할 수 있으면 디버깅할때도 편하다.
8번줄에서 true로 설정하지 않으면 사람이 보기 좋게 포매팅해주지 않는다고 한다.
6.7 엔티티 설계
Spring Data JPA를 사용하면 데이터베이스에 테이블을 생성하기 위해 직접 쿼리를 작성할 필요가 없다.
이것을 가능하게 하는것이 엔티티이다. 내가 생각했을 때 가장 간편하고 중요한 것 같다.
프로젝트 시작 전 설계에서 엔티티를 제대로 설계 및 구현만 해놓으면 그것을 데이터베이스에 저장하고 가져오고
웹페이지에 보여주는데는 크게 어렵지 않다고 생각한다. 그만큼 엔티티에 대해서 잘 정해두면 편하다.
만일 테이블을 그림과 같이 정의했다면, 엔티티 클래스는 다음과 같다.
getter/setter 메서드 생략이라고 써있지만 어노테이션으로 @Getter @Setter 만 붙여주면 된다.
엔티티 관련 기본 어노테이션
- @Entity
- @Table
- @Id
- @GeneratedValue
- @Colulmn
- @Transient
6.8 리포지토리 인터페이스 설계
Spring Data JPA는 JpaRepository를 기반으로 더 쉽게 데이터베이스를 사용할 수 있는 아키텍쳐를 제공한다.
리포리지토리 인터페이스 생성
레포지토리(Repository)는 Spring Data JPA가 제공하는 인터페이스이다.
JpaRepository를 상속받으며 다음과 같이 생성한다.
JpaRepository<a, b> 에서 a는 어떤 엔티티, 즉 어떤테이블 관련한 리포지토리인지를 의미하고 b는 a의 pk값이 어떤 형태인지 Long인지 String인지 쓰면 된다.
JpaRepository를 상속받으면서 별도의 메서드 구현 없이도 많은 기능을 제공한다.
이것은 기본 메서드다.
List<> 값으로 반환 값을 둬도 되고 Optional<>로 두어서 에러처리에 용이하게 사용해도 된다.
JpaRepository의 상속 구조
리포지토리 메서드의 생성 규칙
자세한 퀄 ㅣ메서드는 7장에서 다루겠다.
6.9 DAO 설계
DAO (?)
6.10 DAO 연동을 위한 컨트롤러와 서비스 설계
DAO 개념을 아직 잘 모르겠으나
항상
컨트롤러 -> 서비스 -> 리포지토리 로 접근하는 것이 편하며 보통 그렇게 사용한다는 것을 생각하자.
각 레이어별로 데이터를 전달할때는 엔티티 날것으로 전달하지않고 dto 객체를 따로 만들어서 전달용 객체를 만드는것이 안전성으로 좋다.
6.11 [한걸음 더] 반복되는 코드의 작성을 생략하는 방법 - 롬복
롬복(Lombok)은 데이터(모델) 클래스를 생성할 때 반복적으로 사용하는 getter/setter 같은 메서드를 어노테이션으로 대체하는 기능을 제공하는 라이브러리이다. 매우 간편하다.
롬복 설치
프로젝트 생성 시에 롬복을 의존성애 추가해두고 플러그인 설치를 확인한다.
롬복 적용
롬복 적용은 간단하다. 롬복 설치가 되어있으면 사용이 가능하기 때문.
이게 자바 코드에 비해 매우 간단하고 가독성이 좋다.
롬복의 주요 어노테이션
- @Getter, @Setter
- 생성자 자동 생성 @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor
- ToStriing() : toString()메서드를 오버라이딩할 수 있는 어노테이션. 옵션 존재
- @EqualsAndHashCode : 객체의 동등성과 동일성을 비교하는 연산메서드 생성(자바 객체의 문제점 확인)
- @Data ( = 앞의 어노테이션을 모두 포괄하는 어노테이션) : 그러나 잦은 @Data의 사용은 지양한다고 한다.
'BookStudy > 스프링 부트 핵심 가이드' 카테고리의 다른 글
[스프링 부트 핵심 가이드] 09 연관관계 매핑 (0) | 2023.09.23 |
---|---|
[스프링 부트 핵심 가이드] 08. Spring Data JPA 활용 (0) | 2023.09.17 |
[스프링 부트 핵심 가이드] 05. API를 작성하는 다양한 방법 (0) | 2023.08.31 |
[스프링 부트 핵심 가이드] 04. 스프링 부트 애플리케이션 개발하기 (0) | 2023.08.30 |
[스프링 부트 핵심 가이드] 03. 개발 환경 구성 (0) | 2023.08.24 |