스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - 예스24
가장 빠르고 쉽게 웹 서비스의 모든 과정을 경험한다. 경험이 실력이 되는 순간!이 책은 제목 그대로 스프링 부트와 AWS로 웹 서비스를 구현한다. JPA와 JUnit 테스트, 그레이들, 머스테치, 스프링
www.yes24.com
*위의 책을 따라 학습한 것을 정리한 내용입니다
JPA를 사용하는 이유?
이전 회사(SI회사)에서 기존 솔루션을 컨버팅하는 과정에서 MyBatis + SQL Mapper를 통해 db를 다뤘었다.
쿼리문이 엄청 방대해서 단순 반복 작업을 반복하게 되는데 현타가 왔다. 이렇게 해야하나.. ?
그리고 '객체지향'과도 약간 거리가 있는 느낌이다.
JPA는 이런 SQL에 종속적인 개발을 피하기 위해 나온 것으로, Springboot + JPA 조합을 사용하는 기업들이 늘고 있다.
JPA란?
: 자바 쪽에서 ORM(Object-Relational Mapping)기술 표준으로 사용되는 인터페이스 모음
- 실제적으로 구현된것이 아니라 구현된 클래스와 매핑을 해주기 위해 사용되는 프레임워크이다.
ORM : 우리가 일반 적으로 알고 있는 애플리케이션 Class와 RDB(Relational DataBase)의 테이블을 매핑(연결)한다는 뜻이며, 기술적으로는 어플리케이션의 객체를 RDB 테이블에 자동으로 영속화 해주는 것이라고 보면된다.
- 인터페이스인 JPA 사용을 위해 구현체가 필요한데 Hibernate, Eclipse Link 등이 있으나 Spring에서는 이를 직접 다루진 않는다. 구현체들을 좀 더 쉽게 사용하고자 추상화시킨 Spring Data JPA를 이용하는데, JPA<-Hibernate<-Spring Data JPA 순으로 접근된다. Spring Data JPA는 사용하는데 Hibernate와 큰 차이가 없지만, Hibernate 외 다른 구현체로 쉽게 교체할 수 있고, 관계형 데이터베이스 외의 다른 저장소로도 쉽게 교체할 수 있다.
- 단점: 러닝 커브가 높다.
( JPA 사용을 위해선 객체지향 프로그래밍과 관계형 데이터베이스를 둘 다 이해해야 하기 때문에)
JPA 적용하기
1) dependencies 추가하기
build.gradle의 dependencies에 db와 jpa 추가
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('com.h2database:h2')
h2는 별도 설치 없이 의존성 만으로 db 관리가 가능해 추가해두었다.
이 프로젝트에선 간단한 수준만 다루므로 사용했다.
2) Entity 클래스 생성
Controller를 저장했던 web 폴더와 같은 위치에 domain 폴더를 생성한다.
기존 MyBatis에서 사용했던 dao 패키지와 유사하다.
xml에 쿼리를 담고, 클래스는 오로지 쿼리의 결과만 담던 일들이 모두 도메인 클래스에서 해결된다.
경로/domain/posts/Posts.java를 생성한다.
@Getter
@NoArgsConstructor
@Entity
public class Posts {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 500, nullable =false)
private String title;
@Column(columnDefinition = "TEXT", nullable =false)
private String content;
private String author;
@Builder
public Posts(String title, String content, String author) {
this.title = title;
this.content = content;
this.author = author;
}
}
@Entity
- 테이블과 링크될 클래스
- 기본 값으로 클래스의 카멜케이스 이름을 언더스코어 네이밍으로 테이블 이름 매칭
@Id
- 해당 테이블의 PK 필드
@GeneratedValue
- PK 생성 규칙
- 스프링 부트 2.0에서는 GenerationType.IDENTITY 옵션 추가 해야만 auto_increment가 된다.
- 가능하면 PK는 auto_increment를 사용하는 것이 좋다.
주민번호 같은 비즈니스상 유니크 키나 복합키 등은 난감한 상황이 종종 발생
@Column
- 테이블의 컬럼
- 따로 선언하지 않아도 해당 클래스의 필드는 모두 컬럼.
디폴트 외에 추가로 변경이 필요한 옵션이 있을 경우에 사용
- 문자열: VARCHAR(255) 기본
Posts 클래스는 실제 DB의 테이블과 매칭될 클래스. ( Entity 클래스라고도 함 )
Entity 클래스에서는 Setter 메소드를 만들지 않는다.
해당 클래스의 인스턴스 값들이 언제 어디서 변해야하는지 코드상으로 명확히 구분할 수 없어 차후 기능 변경 시 문제점을 발생시킬 수 있다. 필드 값 변경이 필요하다면 목적과 의도를 나타낼 수 있는 메소드를 추가해야 한다.
기본적으로 생성자를 통해 값을 채우고 DB에 삽입한다.
값 변경이 필요한 경우 해당 이벤트에 맞는 public 메소드를 호출해 변경한다.
해당 프로젝트에서는 생성자 대신 빌더를 이용함으로써 어느 필드에 어느 값을 넣어야하는지 더 명확하게 만들었다.
예를 들어 아래 코드에서는 Example(a,b)와 Example(b, a)의 결과가 다를 것이다.
public Example(String a,String b) {
this.a=a; this.b=b;
}
하지만 빌더를 사용한다면 순서가 상관이 없게 된다.
Example.builder().a(a).b(b).build();
3) DB 계층 접근자 생성
Posts 클래스를 DB에 접근하게 해줄 PostsRepository.java를 생성한다.
반드시 Entity 클래스(Posts.java)와 함께 위치해야 하며, @Repository를 굳이 추가할 필요 없다.
public interface PostsRepository extends JpaRepository<Posts, Long> {}
Mybatis에서 Dao라고 불리는 DB Layer 접근자로, JPA에선 Repository라고 부르며 interface 형태로 생성한다.
JpaRepository<Entity클래스, PK타입>을 상속하면 기본적인 CRUD 메소드가 자동으로 생성된다.
4) 테스트 코드 작성하기
test 디렉토리에 domain/posts/PostsRepositoryTest.java를 생성한다.
@RunWith(SpringRunner.class)
@SpringBootTest
public class PostsRepositoryTest {
@Autowired
PostsRepository postsRepository;
@After
public void cleanup() {
postsRepository.deleteAll();
}
@Test
public void 게시글저장_불러오기() {
//given
String title = "테스트 게시글";
String content = "테스트 본문";
postsRepository.save(Posts.builder()
.title(title)
.content(content)
.author("jojoldu@gmail.com")
.build());
// when
List<Posts> postsList = postsRepository.findAll();
// then
Posts posts = postsList.get(0);
assertThat(posts.getTitle()).isEqualTo(title);
assertThat(posts.getContent()).isEqualTo(content);
}
}
@After
- 단위 테스트 끝날 때마다 수행되는 메소드
- 배포 전 전체 테스트 수행할 때 테스트간 데이터 침범을 막기 위해 사용
- 여러 테스트 동시 수행 시 테스트용 db에 데이터가 남아있어 다음 테스트에 영향 있을 수 있음
@postsRepostiroy.save
- 테이블 posts에 insert/update 쿼리 실행
- id 값이 있다면 update, 없다면 insert
@postsRepository.findAll
- posts 테이블의 모든 데이터 조회
그런데 실제로 쿼리가 실행된 형태가 테스트 결과에 보이지 않는다! 아래의 설정법을 알아보자.
src/main/resources/application.properties 파일을 생성한다.
spring.jpa.show_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.h2.console.enabled=true
다시 실행하면 sql문을 확인할 수 있다.
'WORK > STUDY' 카테고리의 다른 글
[Mustache] 화면 역할에 충실한 템플릿 엔진 (0) | 2023.10.26 |
---|---|
[Spring] JPA Auditing(생성/수정시간 자동화) (0) | 2023.10.26 |
[Spring] API 만들기(h2 웹 콘솔 이용하기) (0) | 2023.10.26 |
[Spring] Controller 작성 및 테스트 (0) | 2023.10.25 |
[Spring] Spring Boot Project로 변환하기 (0) | 2023.10.25 |