1. JPA
자바 표준 ORM(Object Relational Mapping: 객체 관계 매핑). 관계형 데이터베이스와 객체지향 프로그래밍 언어간의 패러다임 불일치를 해소해준다. 실제 동작하는 SQL은 JPA가 작성해주기 때문에 개발자는 객체지향적으로 데이터베이스를 다룰 수 있다.
2. Spring Data JPA
JPA는 인터페이스이며, Hibernate와 같은 별도의 구현체가 필요하다. Spring에서는 이 구현체를 한 번 더 감싼 Spring Data JPA를 사용한다(JPA ← Hibernate ← SpringDataJPA).
이렇게 구성하게 되면 구현체, 데이터베이스와의 결합도가 낮아지게 되어 추후 구현체 교체와 저장소 교체가 수월해진다.
3. Spring 웹 계층
- Web Layer: 외부 요청과 응답 관련 영역
- Service Layer: 트랜잭션, 도메인 간 순서보장 관련 영역
- Repository Layer: 데이터 저장소에 접근하는 영역
- DTOs: 계층 간 데이터 교환을 위한 객체 영역
- Domain Model: 개발 대상(도메인)을 모든 사람이 동일한 관점에서 이해하고 공유할 수 있도록 단순화 시킨 것
*Service 영역에서 @Transactional 어노테이션을 사용한다.
*비즈니스 처리는 Domain 영역에서 담당한다(Service 영역이 아님).
4. 게시판 개발
모든 웹 애플리케이션의 가장 기본 기능인 CRUD(Create, Read, Update, Delete)를 구현한다.
A. Springboot 의존성
Spring Data JPA와 H2를 의존성에 추가해준다. H2는 메모리상에서 동작하는 데이터베이스이며, 애플리케이션 재구동 시 초기화 된다. 테스트용으로 자주 사용된다.
build.gradle 파일 dependencies에 아래 문장을 추가한다.
...
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('com.h2database:h2')
...
i) H2-Console
H2 DB는 인메모리 데이터베이스이다.
http://localhost:8080/h2-console 접속 후 아래 정보를 입력하고 접속한다. Password는 없다.
C. domain 패키지
도메인 게시글, 회원, 정산 등 소프트웨어의 요구사항? 문제영역? 이라고 생각하면 된다고 한다.
> 자세한 내용은 추후 검색해볼 것
i) Entity
실제 데이터베이스 테이블과 매칭될 클래스이다. DTO/VO와 비슷하게 보이지만 용도나 기능 측면에서 확연히 다르다.
단적인 예로 Entity 객체를 수정 할 경우 실제 DB 데이터가 수정된다.
*영속성 컨텍스트: Entity를 영구 저장하는 환경. 트랜잭션 안에서 DB에서 가져온 데이터 객체를 수정하면 트랜잭션이 끝나는 시점에 변경분을 반영한다. 이를 더티 체킹(dirty checking)이라고 한다.
*주의사항:
Entity 클래스에는 절대로 Setter를 만들지 않는다.
값 변경이 필요할 경우 아래와 같이 목적/의도를 나타낼 수 있는 메소드를 추가하여 사용한다.
@Entity
public class Order {
...
public void cancelOrder() {
this.status = false;
}
}
public void 주문서비스의_취소이벤트() {
order.cancelOrder();
}
[주요 어노테이션]
Annotation | Description |
@Entity | 테이블과 링크될 클래스임을 나타낸다. 카멜(MyClass) ↔ 언더스코어(MY_CLASS) 규칙으로 테이블과 매핑된다. |
@Id | PK 필드임을 나타낸다. |
@GeneratedValue | PK 생성규칙을 나타낸다. |
@Column | 칼럼임을 나타내며 생략 가능하다. 타입이나 길이와 같은 옵션 변경이 필요할 경우 사용한다. 참고로 문자열 기본 값은 VARCHAR(255)이다. |
일반적으로 Entity의 PK는 Long타입의 Auto Increment가 권장된다.
> 자세한 내용은 식별자 전략, 복합키 매핑 등 추후 검색해볼 것
ii) Entity Repository
Dao와 유사한 데이터베이스 접근자이다. 인터페이스 생성 후 JpaRepository<Entity클래스, PK타입>을 상속받으면 기본적인 CRUD 메소드가 자동으로 생성된다. Entity 클래스와 같은 경로에 함께 위치해야 한다.
public interface PostsRepository extends JpaRepository<Posts, Long> {
@Query("SELECT p FROM Posts p ORDER BY p.id DESC")
List<Posts> findAllDesc();
}
+ repository의 save(...) 메소드는 파라미터 객체에 id값이 있으면 update, 없으면 insert를 수행한다.
+ @Query 어노테이션을 활용하여 실행 쿼리를 직접 지정할수도 있다.
C. Controller, Service, Dto
아래 두 가지 내용을 참고하여 일반적인 방식으로 생성해준다.
- Bean 주입 시 생성자로 주입받는 방식을 권장한다. @RequiredArgsConstructor를 활용하자
- Entity 클래스를 절대로 Dto로 사용해서는 안된다. Entity 클래스는 DB 테이블, 스키마와 연관 된 클래스로 쉽게 변경할 수 없다. Dto는 요구사항에 따라 언제나 쉽게 변경될 수 있기 때문에 Dto와 Entity는 기능과 용도면에서 명확히 분리해야 한다.
D. JPA Auditing
JPA Auditing을 사용하여 생성시간/수정시간 저장 로직을 자동화할 수 있다. 날짜 지정에는 Java8의 LocalDate, LocalDateTime을 활용하자(Date와 Calendar 클래스는 일부 문제가 있음).
Entity 클래스가 아래 클래스를 상속받으면 생성/수정시간 Auditing이 적용 된다
...
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseTimeEntity {
@CreatedDate
private LocalDateTime createDate;
@LastModifiedDate
private LocalDateTime modifiedDate;
}
[주요 어노테이션]
Annotation | Description |
@MappedSuperclass | 자식 Entity가 본 클래스의 필드를 칼럼으로 인식 |
@EntityListeners(AuditingEntityListener.class) | 클래스에 Auditing 기능을 포함시킴 |
@CreatedDate | Entity가 저장 될 때 시간을 자동 저장 |
@LastModifiedDate | Entity가 수정 될 때 시간을 자동 저장 |
@EnableJpaAuditing | JPA Auditing을 활성화 한다. 메인 클래스에 적용 |
일반적으로 Entity의 PK는 Long타입의 Auto Increment가 권장된다.
5. 기타
[기타 어노테이션]
Annotation | Description |
@PathVariable | {변수명} 표현식과 함께 사용하여 URL 경로에 변수를 넣어준다. |
@Transactional(readOnly = true) | 클래스/메소드에 지정하여 기능의 원자성을 보장해준다 readOnly 옵션으로 조회만 하는 트랜잭션임을 명시하여 조회 속도를 개선할수 있다. |
JUnit / @After | JUnit에서 단위 테스트가 끝날 때 수행되는 메소드 지정 |
Lombok / @NoArgsConstructor | 기본 생성자 자동 추가 |
Lombok / @Getter | 모든 필드의 Getter 생성 |
Lombok / @Builder | 해당 클래스의 빌더 클래스 생성. 생성자 대신 빌더를 사용함으로써 객체 생성 시 명시적으로 필드를 입력할 수 있다. |
[application.properties]
Option | Description |
spring.jpa.show_sql=true | 콘솔 로그에 쿼리 출력 활성화 |
spring.h2.console.enabled=true | h2 콘솔 화면 활성화 → http://localhost:8080/h2-console |
[인텔리제이 단축키]
기능 | 단축키 |
툴팁보기(Quick Documentation) | Ctrl + Q |
이름 바꾸기(Rename) | Shift + F6 |
라인 복제 | Ctrl + D |
라인 삭제 | Ctrl + Y |
라인 이동 | Alt + Shift + ↑↓ |
전체 검색 | Ctrl + Shift + F |
코드 자동 정렬 | Ctrl + Alt + L |
파라미터 보기 | Ctrl + P |
창 닫기 | Ctrl + F4 |
*기타 참고
- DDD Start!(최범균 저)
- 자바 ORM 표준 JPA 프로그래밍(김영한 저)
'Backend' 카테고리의 다른 글
iBatis 쿼리 가져오기 (0) | 2020.05.07 |
---|---|
Springboot (4) 웹 애플리케이션 - 2 (0) | 2020.04.29 |
Springboot (2) 단위 테스트 (0) | 2020.04.18 |
Springboot (1) 개발환경 설정 (0) | 2020.04.17 |
Spring Batch + MyBatis 연결방법 (0) | 2020.03.18 |