본문 바로가기
Web/스프링 부트와 aws로 구현하는 웹서비스

4. JPA 사용해보기

by 장인이 2021. 7. 14.

해당 게시물들은 이동욱 저자님의 "스프링 부트와 AWS로 혼자 구현하는 웹 서비스"를 공부하며 기록한 것입니다.

 

 이번 게시물에서는 JPA를 활용하여 이 책에서 앞으로 실습하게 될 게시판을 만들어 보도록 할 것이다. 이때 웹 서비스를 다루게 된다면 필수적으로 데이터베이스를 관리하게 된다. 하지만 개발을 진행할 시, 실제로 개발하는 시간보다 SQL문을 다루는 시간이 더 많아지게 된다. 객체 모델링보다는 테이블 모델링에 시간을 쏟고, 할애하게 된다.

 

 이를 위해 JPA라는 기술을 사용하게 된다. JPA를 사용하면, 개발자는 객체지향적으로 코딩을 하고, JPA가 이를 보고 SQL을 대신 생성해서 실행하는 과정을 진행하게 된다. 따라서 개발자는 SQL에 매달리는 시간을 줄일 수 있게 된다. 따라서 유지 보수에서 또한 훨씬 편하게 진행할 수 있게 된다.

 

 

 여기서 JPA는 자바 표준명세서이며, 이를 사용하기 위해서는 구현체가 필요하다. 여러 구현체들이 있으나, Spring에서 JPA를 다루는 경우 Spring Data JPA를 이용하여 구현하게 된다. 이는 

 

 JPA <- (특정 구현체) <- Spring Data JPA

 

 이런 관계를 지니며, 따라서 시간이 지나 구현체가 변하더라도 Spring Data JPA를 사용하면 쉽게 교체할 수 있다.

 

 

 또한, 처리해야 할 데이터 양이 너무 많아 관계형 데이터베이스로 감당이 안되어 MongoDB로 교체할경우, 이떄도 Spring Data MongoDB로 의존성만 교체하면 해결되는 일이다.

 

 

 하지만 실무에서 JPA를 사용하지 못하는 이유로는 높은 러닝 커브때문이라고 한다. 객체지향 프로그래밍과 관계형 데이터베이스 모두 이해해야 하기 때문인데, 하지만 그만큼 장점도 많은 기술이다.

 

 

 

 해당 책에서는 게시판을 만들고, AWS에 무중단 배포하는 것 까지 진행한다. 게시판은 게시글 조회, 등록, 수정, 삭제의 기능을 지니고 구글/네이버 로그인을 통한 회원기능, 그리고 로그인한 사용자 글 작성 권한, 본인 작성 글에 대한 권한 관리의 기능을 요구한다.

 


 

 

 그럼 우선 build.gradle에 의존성을 등록한다.

 

 

 

 그 후 domain 패키지를 web과 같은 공간에 생성한다. 이는 도메인을 담는 패키지이다. 도메인은 게시글, 회원, 결제 등 소프트웨어에 대한 요구사항 혹은 문제의 영역이다. domain 패키지에 posts 패키지와 Posts 클래스를 만들고, 코드를 입력한다.

 

 

 우선 위의 @Getter와 @NoArgsContructor는 롬복의 어노테이션로, get 메소드와 기본 생성자를 생성해준다. @Entity는 JPA의 어노테이션이며, 더 중요하므로 클래스와 더 가깝게 작성한다.

 

 Posts 클래스는 @Entity를 사용하므로서 DB과 실제로 매칭되는 Entity 클래스라고 할 수 있다. 위 코드를 보면, @Id는 해당 테이블의 pk를 나타낸다. @GenerateValue는 pk의 생성 규칙을 설정하며, 스프링부트 2.0부터 GenerationType.IDENTITY를 추가해야 auto increment가 된다. @Column은 테이블의 칼럼을 의미하며, 굳이 작성하지 않아도 default값을 지닌 칼럼이 된다. default값은 문자열의 경우 VARCHAR(255)가 기본값이며, 사이즈 혹은 타입을 변경하고 싶을 때 해당 어노테이션을 사용한다.

 

 

 여기서 한가지 특징이 Setter 메소드가 존재하지 않는다는 점이다. 그 이유는 무작정 setter를 사용할 경우, 해당 클래스의 인스턴스 값들이 어디서 변하는지 구분할 수 없어, 추후 기능 변경 시 복잡해진다. 따라서 Entity 클래스에서는 절대 Setter 메소드를 만들지 않는다.

 

 대신 필드 값을 변경해야 하면 그 의도를 명확히 파악할 수 있는 이름으로 진행해야 한다. 예를 들명 주문을 취소하는 메소드를 작성한다고 하면 .setStatus(false) 이런 방식이 아닌, .cancelOrder()와 같은 방식으로 작성하는 것을 권장한다.

 

 

 그런데 Setter를 사용하지 않는다면, 어떻게 값을 DB에 삽입해야 하는지 의문증이 생긴다. 기본적으론 생성자를 통해 삽입하고, 값을 변경해야 하는 경우에는 해당 이벤트에 맞는 public 메소드를 호출한다.

 

 위 코드에서는 @Builder를 통해 생성자를 대신하게 된다.

 

 

마지막으로 Posts 클래스로 DB에 접근할 PostsRepository를 posts 패키지에 인터페이스로 생성한다.

 

 

 주석의 내용과 같이 이는 Dao와 같은 DB layer에 접근하는 역할을 한다. 별다를 어노테이션 없이 JpaRepository<Entity 클래스, pk 타입>을 상속하면 되며, 그리고 Entity 클래스와 같은 패키지 안에 있어야 한다.


 

 이제 test 디렉토리에 domain.posts 패키지를 생성하고, PostsRepositoryTest라는 이름으로 테스트 클래스를 생성한다.

 

 

 우선 @After는 Junit에서 단위 테스트가 끝날 때마다 수행되는 메소드로서, 해당 테스트가 끝난 후 데이터를 삭제하는 역할을 한다.

 

 postsRepository.save는 테이블 posts의 insert 혹은 update 쿼리를 실행한다. id값이 있으면 update, 없으면 insert를 한다.

 

 postsRepository.findall은 posts 테이블의 모든 데이터를 조회하는 메소드다.

 

 

 해당 테스트코드를 실행해보면, 정상적으로 통과되는 것을 확인할 수 있다.

 


- 학습 내용 저장할 github

https://github.com/imgzon3/imgzon3-springboot-test

 

imgzon3/imgzon3-springboot-test

Contribute to imgzon3/imgzon3-springboot-test development by creating an account on GitHub.

github.com

 

댓글