JPA로 데이터베이스 다뤄보자

박일한·2021년 11월 15일
0

JPA란

Java Persistence API의 줄임말로 현재 자바 진영의 ORM 기술 표준으로, 인터페이스의 모음이다.
Jpa 인터페이스를 구현한 대표적인 오픈소스가 Hibernate이다.

JPA와 MYBATIS의 차이

기존에 자바를 공부할때부터 mybatis를 사용해왔으니 ibatis부터해서 총 8년정도?? 사용해본것 같다.
spring framework를 사용하면서 mybatis는 빼놓을 수 없는 SQL framework일 것이다.
1) 기본적인 CRUD를 만들지 않아도된다.(JPA는 기본적인 쿼리문을 제공한다.)
2) Mybatis는 DB에 대한 관계지향적 프로그래밍에 가까워지고 JPA는 객체지향적 프로그래밍을 한다.

JPA에도 쿼리문이 존재한다. 하지만 그건 데이터베이스를 기준으로 하는것이 아니라 객체를 기준으로 작성을 하는 것이다.

JPA에 대한 나의 생각

현재 자체 서비스를 하는 회사들은 많이 사용하고 있는 추세이다.
그 이유는 좀더 객체지향 스러운 개발과 불필요한 SQL문을 만들필요없이 개발이 가능하기 때문이지 않을까? 생각한다.
그리고 jpa를 공부하면서 느낀점은 mybatis의 관계지향적인 코드에서는 테스트코드를 작성하기가
매우 어려웠다.
요즘 말하는 패러다임의 불일치 문제가 여기서 대두 되는 것이다.
유지보수 측면에서도 그렇고 메시지를 기반으로 도메인에서 관리하는 관점이 중요했다.
하지만 JPA를 배우기 위해선 SQL문도 작성을 할줄 알아야되고 도메인에 대한 지식도 알아야된다.
즉 진입장벽이 생각보다 높다. 도메인을 모르면 자동으로 생성되는 쿼리문에서 문제가 발생되어
메모리 누수나 잘못된 쿼리문이 나갈 수 있기 때문이다.

SPRING DATA JPA

spring에서 jpa를 다룰때 hibernate, eclipse link를 이용하지않고 spring data jpa를 이용하여 개발한다.
JPA <- hibernate <- Spring data jpa
spring data jpa를 사용하는 이유는 유지보수 및 구현체 교체 용이성, 저장소 교체의 용이성에
있다.
무엇인가 교체가 되었을때 Spring Data 하위에 있는 것들과 인터페이스가 같기 때문에 불필요한 코드 교체가 필요 없어진다.

H2 Database

인텔리제이를 사용하면서 많이 사용한 DB이다.
h2DB는 인메모리 관계형 데이터 베이스 이다.
별도의 설치가 필요없이 프로젝트 의존성만으로도 관리 할 수 있다.

SPRING DATA 적용하기

data base 설정


여기서 필요한 부분은 starter-data-jpa, starter-test, lombok, h2database 이다.
H2 Database를 사용하면서 설정이 몇가지 필요한데

해당 application.properties가 전체적인 구성을 관리할 것이다.

책에서의 버전에서는 memory db만 사용했을때 spring.datasource부분이 없어도
자동으로 testdb가 생성이 되었는데 버전이 변경되면서 해당 구문을 넣어줘야 되었다.
위에 properties는 다 작성할 필요는 없지만 나는 보통 다 가져가는것을 좋아한다.
기존에는 h2 db를 설치해서 사용했는데
properties 중에 spring.h2.console.enabled을 사용하여 웹 브라우저에서DB console 기능을 사용가능하게 도와준다.
해당 기능을 사용하면 http://localhost:8080/h2-console/ 을 통하여 DB에 접속할 수 있다.
기본적인 database 세팅은 끝난것 같다.

내가 위에서 언급한 설치에 대한 부분은 별도로 알아보는 것이 좋다.
위의 saved settings에서 embedded가 아닌 server로 설정하여 사용이 가능하다.

domain 설정


JPA는 Entity라는 어노테이션을 통하여 DB에 접근이 가능하다.
그래서 보통 JPA를 개발하면 Entity영역과 Dto영역을 분리한다.
mybatis에서는 해당 부분을 보통 dto로 사용했을 것이다.
분리되는 이유는 entity에 접근을하여 조작을 했을시 바로 db에 영향을 미친다는 것이다.
즉 한순간의 실수로 data가 다 날라갈수도 있고 view에서 db에대한 사이드이팩트를 가져올수 있다. 즉 기존의 mybatis를 사용한 것과 다르지않고 오히려 더 위험해진다.
위에 어노테이션을 살펴보면
@Getter는 getter 메서드, @NoArgsConstructor는 기본생성자를 자동으로 만들어준다.
해당 어노테이션은 lombok에서 제공을 해준다.
db의 Pk는 @Id로 보통 Long의 형을 가지고 사용한다. 이부분은 회사마다 정책에 따라 바뀔수 있기 때문에 맞춰서 개발을 진행하면된다.
그리고 사용하는 database에 맞춰서 identity나 sequence 전략을 가져가면된다.
mysql/mariadb,mssql : identity
oracle : sequence

해당 클래스는 baseTimeEntity를 상속받는데 이부분은 생성날짜, 생성자, 수정날짜, 수정자를
상속받은 것이다.

이 클래스는 DB에 바로 접근하는 객체가 아니기 때문에 Entity가 없는것이다.
Entity가 아닌 MappedSuperClass라는 것을 선언하여 상속관계를 정의하여 사용한다.
이런 부분은 불필요하게 테이블마다 공통으로 가져가는 부분을 제공해 주는것이다.
자바 1.8부터는 LocalDateTime을 제공한다.
기존에는 Date, Calendar를 사용했는데 이제는 localDateTime을 사용하는것 같다.

위에 @Column은 실제 DB의 column을 명세 한 것이다.
db에 대한 수정이 있을시 해당 entity클래스를 수정하여 작업한다.
클래스 생성은 끝났다. 이제 우리가 사용하던 dao / repository를 알아보자.

Repository


위의 이미지는 repository를 작성한 코드를 보여준 것이고
아래의 이미지는 상속받은 JpaRepository의 내부에 연결되어있는 부분의 한 부분이다.
보면 기본적인 CRUD를 제공하고 있다.
repository 사용방법은 generic부분에 도메인과 해당 도메인의 PK 형 타입을 입력하면 사용가능하다. 그리고 repository는 entity와 1:1 관계에 놓여 있다.
기본적인 CRUD만 사용하면 내가 작성한 findAllDesc도 필요가 없다.

SERVICE


겉으로만 보면 우리가 알던 service 코드와 유사하다.
dao -> service에 연결하는 부분과 유사하다고 보면된다.
jpa에서는 영속성안에서만 동작을 하기 때문에 Transcational을 걸어준다.
조회에서는 Transactional을 하지않아도 사용 가능하다.
별도의 insert, update 구문을 repository에서도 입력하지 않았지만 사용이 가능하다.
save, findById는 메서드명으로만 봐도 알 수 있지만 update는 특이하다.
기존의 pk를 가지고 수정할 내역을 불러와서 수정을 한뒤에 다시 저장한다.
변수나 List의 generic을보면 dto라는것을 눈치 챘을것이다. 이부분도 위에 언급된 내용과 동일하다.

Controller


이책을 보다보니 mapping의 종류는 다양하게 그리고 역할에 맞게 사용을 하였다.
기존에 controller를 사용할때 requestMapping에 타입은 post, get을 설정하여 사용했는데
이렇게 다양하게 사용 가능한 것을 알 수 있다.
Pathvariable : mapping에서 정의한 {} 명시된 변수를 받아온다.
RequestBody : 클라이언트가 전송하는 Json(application/json) 형태의 HTTP Body 내용을 Java Object로 변환시켜주는 역할을 한다.
그리고 body가 존재하지않은 get 메서드에 사용시 에러가 발생된다.

Test

1) repositoryTest

repositroryTest를 보면 특별한건 없다.
보면 afterEach로 delete를 해주는데 그 이유는 전체테스트시 테스트완료된 데이터를 가지고 있고 전체 테스트가 끝날시 반영이 되기때문에 메서드별 정확한 테스트를 위해서 삭제를 한것이다.
repository의 의존성을 주입하기 위하여 @SpringBootTest를 선언하였다.

2) controllerTest

controllerTest도 마찬가지로 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)선언하였는데 추가로 webEnvironment.RANDOM_PORT를 추가 하였다.
MOCK : mock servlet environment. 내장 톰캣 구동 안함.
RANDOM_PORT : 내장 톰캣 구동, mockmvc 대신에 restTemplate를 사용

책을 따라하다보면 기본적으로는 테스트가 잘 될것이다. 하지만 jpa를 연결하고나서 에러가 발생 했다.
이유는 jpa가 모든 test코드에 영향을 주게 되므로써 문제가 생긴 것이다.
책에서는 완전판으로 git의 source를 받아 분석하고 책을 보게 되면 알았을 것이다.
jpaConfig 파일이 존재한다.

기존에 application context에 있던 어노테이션을 별도로 분리하고 진행하였다.

이번 챕터의 나의 생각

H2 DB사용이나 JPA는 인프런강의를 통해서 이미 경험을 해봐서 그런지 별 문제가 없었다.
하지만 그냥 이책을 보고 따라해서 안풀리는 문제도 많을것이다.
혹시나 이 블로그를 보는 사람들은 별도의 JPA 인프런강의를 들어도 좋을것 같다.
그리고 jpa를 하고 tdd를 하면서 객체지향체조 10가지 항목이 있는데 같이 보면 좋을것 같다.
mybatis가 나쁘다는것은 아니다. 하지만 내가 java나 객체지향적인 프로그래밍을 했을때 얻을 수 있는 장점이 더 좋다는 것이다.
이제부터는 설정 및 스프링 시큐리시티등 그런것들이 많다.
JPA는 더 공부해야겠다.

profile
긍정적인 삶을 갖자~~

0개의 댓글