끊임없이 검증하라

나에게 당연할지라도

Project

P1_클론 프로젝트(feat. 스프링부트와 AWS로 혼자 구현하는 웹 서비스)_3-1

fadet 2022. 3. 25. 18:10

* 이 포스트는 전 배달의민족, 현재 인프런에 계시고 유튜브 개발바닥의 크리에이터이신 개발자 이동욱님의 '스프링부트와 AWS로 혼자 구현하는 웹 서비스'를 기반으로 작성되었음을 알립니다. 포스트 맨 아래에 관련 링크가 있습니다. 책의 내용을 기반으로 작성되기에 실습 중이라면 책을 main 해당 포스트를 sub로 참고해주세요. 책의 설명이 부족한 부분 위주로 포스트가 구성됩니다.


3장은 스프링에서 DB 관리에 대해 다루는데 기존에 Model에 해당하는 도메인들(post, user 등)을 관리할때 sql 문법의 쿼리를 작성하였었던 사람들에게는 조금 생소할지도 모르는 JPA를 배웁니다. 왜 JPA를 사용하는지는 책에 아주 자세히 나와있으니 생략하고 JPA에 대한 간략한 추가 설명만 하고 넘어가겠습니다.

 

3.1 JPA 소개

 

# JPA

JPA(Java Persistence Api)란 쉽게 내가 Class를 작성하여 객체를 생성하면 쿼리 없이 그 객체를 테이블에 옮겨주는 놈이라고 생각하면 됩니다. 이를 ORM(Object Realational Mapping)이라 부르고 DB마다 사용하는 SQL이 다르기에 흔히들 아는 MyBatis는 쿼리 자체를, ORM은 객체를 테이블에 매핑해줍니다. 자세한 것은 추후 다루도록 할 것이고 JPA는 앞서 나왔듯 Api기에 추상적이고 역할과 구현 중 역할에 해당한다고 보면 됩니다. 이를 구현한 것이 hibernate, Spring Data Jpa이고 이 둘에 대한 설명은 책에 나와 있으니 생략하겠습니다.

 

이 JPA를 책에서 가장 먼저 배우는 이유는 DB에 쿼리를 직접 날리는 것은 최근 백엔드 개발 동향에는 많이 벗어나기 때문입니다. 당연히 학습 초기에는 DB를 직접 열어보고 쿼리도 날려보는 경험이 필요하겠지만 책에도 설명되어 있듯 실 서비스에선 DB에 쿼리를 직접 날리는 만큼 시간이 낭비된다고 보시면 됩니다. 따라서 요즘은 queryDSL이라는 JPA 기반 ORM 프레임워크를 주로 사용하며 이를 정확히 사용하기 위해선 JPA에 대한 선행 지식을 습득하고 있어야하기에 이 책에서 가장 먼저 소개했으리라 생각합니다.

 

3.2 프로젝트에 Spring DATA JPA 적용

 

# 시작 전 설정(이전 포스트 참고)

원래라면 개발자에겐 (골치아픈) 요구를 할 주체가 있겠지만 이 책은 대신 요구사항이 주어집니다. 이 요구사항을 실천하기 위해 이번 장부터 본격적인 빌드를 할 것입니다. 그것을 위해 앞서 소개한 Spring-data-jpa와 h2에 대한 dependency를 추가합니다. 여기서 h2란 책에 소개된대로 인메모리 DB인데 이에 대한 추가 설명을 짧게하고 가겠습니다.

 

DB란 기본적으로 대용량의 Data를 저장하기 위한 공간입니다. 인메모리 DB는 메모리를 사용하는데 좁은 메모리 공간에서 그 큰 데이터를 다룰 수 없을 뿐더러 메모리는 기본적으로 휘발성이기에 이를 단순히 사용하면 Durablity(지속성)이라는 DB의 원칙에 위배됩니다. 그렇기에 인메모리 DB는 모든 작업 사항을 디스크에 로그로 저장해두고 시스템 구동시 로그를 읽어 데이터를 메모리 위에 올려 사용합니다. 여기서 인메모리 DB는 당연히 메모리를 사용하기에 일반 DB보다 성능이 좋지만 앞서 말한 대용량의 데이터를 다루기엔 역시 부적절하고 그래서 세션 등의 작은 용량이 필요한 정보를 캐싱하는데 주목적을 둡니다. 이책에선 redis 등 주로 실제 서비스에 사용하는 툴보단 매우매우 설치가 쉽고 설정이 간단하며 Jpa를 실습하는데 최적의 인메모리 RDB인 h2를 사용합니다.

 

h2의 설정법은 스프링 버전업에 따라 조금 복잡해졌습니다. 그렇기에 저자의 블로그나 필자의 이전 포스트를 참고하여 h2를 설정하도록 하길 바랍니다.

 

# Posts

다음은 도메인 생성인데 책의 내용에 기반하여 @Entity를 중심으로 패키지를 구성할 것입니다. JPA에선 쿼리를 날리는 대신 객체를 매핑한다고 했었는데 그 매핑되는 대상이 @Entity가 붙은 도메인이 됩니다. 사실 JPA는 여기서 아주 기초만 소개되어있기에 많이들 접한 n+1 문제, 일대다 관계 등의 개념도 다루지 않습니다. 이 개념이나 이를 적용한 커스텀 등은 책의 내용을 마친 뒤 포스트할 수 있으면 하겠습니다.

 

Posts에 대한 설명은 책으로 충분할 것 같지만 한가지 짚고 가자면 Id의 경우 @GeneratedValue가 붙어있는데 쉽게 말해서 테이블에 post 하나가 추가될 때마다 id가 1,2,3 ... 이렇게 자동으로 부여된다는 의미로 알면 됩니다. 유니크 키나 PK, FK 등의 개념들은 DB를 조금 공부하신 분들이라면 다들 알 것이고 추후 JPA 관련 포스트에서 다루겠지만 간단하게 말하자면 각 테이블의 메인 구분자가 PK(Primary Key)이고 테이블을 다른 테이블과 엮는 구분자를 FK(Foreign Key)로 알고 넘어가도 책을 진행하는데 큰 무리가 없을 것입니다.

 

# @Builder

다음으로 @Builder에 대해 다룰텐데 책에 언급된 setter에 대한 주의점은 넘어가고, 사실 빌더패턴은 장점이 많습니다. 그 중 가장 큰 것은 책에 소개된 것 처럼 객체 생성시 순서에 개의치않고 param에 대한 정보를 명시하며 생성할 수 있다는 것입니다. 하지만 최근에 인텔리제이 등 IDE가 너무 잘 되어 있어 객체 생성시 자신이 입력하는 param의 정보가 생성 시점에서 표시되어 param에 대한 정보를 얻는데 큰 차이가 없고 오히려 빌더에선 param을 잊고 빠뜨리는 경우가 있을 수 있기에 빌더를 사용할 때의 단점도 있으므로 이에 대해선 스스로에겐 무엇이 맞을지 생각하는 게 나을 것 같습니다. 필자는 첫 실습에선 책 내용을 대부분 커스텀하지 않는 방향을 원하므로 내용은 유지했지만 빌더 패턴은 잘 쓰지 않습니다.

 

# PostsRepository

PostsRepository는 DB와 가장 근접한 클래스라고 생각하면 편하겠네요. 책에도 바로 다음에 자세히 소개되어있지만 좀 더 쉽게 설명하자면 개발자가 직접 DB를 쿼리로 다루기 너무 번거롭기에 이 책에서는 JPA를 사용하여 개발자는 객체를 다루는 것만으로 DB 조작이 가능합니다. 이 때 @Entity가 붙은 엔티티 클래스가 DB와 매핑되는 직접적인 Column이 되며 이 엔티티 클래스와 DB를 자바 코드만으로 의사소통시켜주는 것이 @Repository가 붙은 클래스입니다. 이처럼 너무나도 밀접한 관계기에 한 패키지 내에서 관리하는게 좋습니다. 전체적인 mvc 구조에 대한 설명은 다음 포스트에서 이어가겠습니다.

 

PostsRepository의 경우 JpaRepository를 상속하는 인터페이스지만 실제 개발에선 역할이 될 XXrepository 인터페이스를 만들고 이를 구현할 구현체 XXrepositotyImpl 등을 만듭니다. 따라서 책 내용에선 @Repository를 붙일 필요도, EntityManager 등을 주입받을 필요도 없지만 스프링을 이 책으로 처음 공부한다면 repository에 대한 코딩을 따로 찾아보는 것을 추천합니다.

// JpaRepository뒤에는 post와 id를 담기 위한 제네릭<>
public interface PostsRepository extends JpaRepository<Posts, Long> {

 

3.3 Spring DATA JPA 테스트코드 작성

 

# PostsRepositoryTest

PostsRepositoryTest에 작성된 .save나 .findAll 메소드는 전부 JpaRepository(+ 이것의 부모클래스)에서 정의된 메소드이고 실제 개발에서도 표준처럼 사용됩니다. 여기서 더 짚고 넘어가야할 것은 h2 DB에 대한 책의 내용인데 책에 적힌 해당 부분을 간단히 설명하면 다음과 같습니다. 테스트에서 진행된 과정에서 실제 쿼리를 콘솔로 확인하고 싶기에 1 show_sql을 true로 하여 콘솔에 sql을 출력하고 2 콘솔에 출력되는 문장이 h2의 쿼리 문법을 따르므로 이를 실제 sql 쿼리 문법으로 출력하게 하고자 dialect 설정을 변경합니다. 그런데 현재 시점에서 해당 코드는 1까지만 작동하고 2는 더이상 작동하지 않습니다. 이에 대한 설정은 약간 번거로우므로 1까지만 확인하고 넘어가는 것을 추천합니다. 정 자신이 끝까지 실습하고 싶다면 h2 접속 url에 Mode:sql을 붙이고 yml의 dialect 설정에서 sql의 최신버전으로 코드를 추가하면되는데 자주 변경되므로 그닥 추천하지는 않습니다.


여기까지 3장의 repository부분까지를 다루었고 포스트가 길어져 중요하다고 생각하는 API와 스프링 mvc의 구조에 대한 내용부터는 다음 포스트부터 다루겠습니다.

 

refer

이동욱님 블로그의 관련 포스트 : https://jojoldu.tistory.com/539?category=717427

개발바닥 유튜브 :https://www.youtube.com/channel/UCSEOUzkGNCT_29EU_vnBYjg

 

개발바닥

본격 세계최초 DEV 엔터테인먼트 토크쇼 두 스타트업 개발자의 요절복통 이야기 구독 안하면 장애남!!

www.youtube.com

이동욱님 github의 해당 repository : https://github.com/jojoldu/freelec-springboot2-webservice