4장 : Spring MVC/JPA/Thymeleaf 연습
프로젝트 구조 만들기
Todo
프로젝트의 계층별 구조와 객체들의 구성
Querydsl을 이용해서 동적으로 검색 조건을 처리하는 방법
Entity 객체와 DTO의 구분
화면에서의 페이징 처리
4.1 프로젝트의 와이어 프레임
4.1.1 프로젝트의 화면 구성
목록 화면 : 전체 목록을 페이징 처리해서 조회할 수 있고, 제목/내용/작성자 항목으로 검색과 페이징 처리를 가능하게 함
등록 화면 : 새로운 글을 등록할 수 있고, 등록 처리 후 다시 목록 화면으로 이동 함
조회 화면 : 목록 화면에서 특정한 글을 선택하면 자동으로 조회 화면으로 이동함. 조회화면에서는 수정/삭제가 가능한 화면으로 버튼을 클릭해서 이동
수정/삭제 화면 : 수정 화면에서 삭제가 가능하고 삭제 후에는 목록 페이지로 이동함. 글을 수정하는 경우에는 다시 조회 화면으로 이동해서 수정된 내용을 확인할 수 있음
4.1.2 프로젝트 생성
방명록 프로젝트
Spring Data JPA를 활용해서 계층을 처리하고 Thymeleaf를 이용하는 화면을 처리
Spring Initializer
Gradle
Java
Spring Boot : 2.6.5
Group : com.springweb
Artifact : guestbook
build.gradle
application.properties
4.1.3 컨트롤러/화면 관련 준비
GuestbookController
화면 → 생략 (앞장에 있음)
4.2 자동으로 처리되는 날짜/시간 설정
BaseEntity
@MappedsuperClass
JPA
JPA는 JPA만의 고유한 메모리 공간(이하 Context)을 이용해서 엔티티 객체들을 관리
MyBatis를 이용하는 경우에는 SQL을 위해서 전달되는 객체는 모두 SQL처리가 끝난 후에는 어떻게 되든 상관이 없는 객체들인 반면 JPA에서 사용하는 엔티티 객체들을 영속 콘텍스트라는 곳에서 관리되는 객체.
이 객체들이 변경되면 결과적으로 데이터베이스에 이를 반영하는 방식.
GuestbookApplication
@EnableJpaAuditing
4.3 엔티티 클래스와 Querydsl 설정
GuestbookApplication
GuestbookRepository 인터페이스
4.3.1 동적 쿼리 처리를 위한 Querydsl 설정
Querydsl
복잡한 조함을 이용하는 경우의 수가 많은 상황에서느 동적으로 쿼리를 생성해서 처리할 수 있는 기능이 필요할 때 이를 처리할 수 있는 기술
build.gradle은 위에와 동일 (위에서 이미 querydsl 설정하고 올림)
추가적으로
compileQuerydsl 오류
https://www.inflearn.com/questions/355723
ㅅㅂ ㅠㅜ
단계들은 차례로
plugins 항목에 querydsl 관련 부분을 추가
dependencies 항목에 필요한 라이브러리 추가
Gradle에서 사용할 추가적인 task를 추가
GuestbookRepository 인터페이스에서 QuerydslPredicateExcutor 인터페이스 추가 상속
4.3.2 엔티티의 테스트
GuestbookRepositoryTests


요런식
엔티티 클래스는 가능하면 setter 관련 기능을 만들지 않는 것이 권장 사항이지만, 필요에 따라서 수정 기능을 만들기도
(하지만 엔티티 객체가 애플리케이션 내부에서 변경되면 JPA를 관리하는 쪽이 복잡해질 우려가 있기 때문에 가능하면 최소한의 수정이 가능하도록 하는 것을 권장)
Guestbook
GuestBookRepositoryTest


update 시 moddate도 잘 업데이트 됨~
4.3.3 Querydsl 테스트
Querydsl 실습
‘제목/내용/작성자’와 같이 단 하나의 항목으로 검색하는 경우
‘제목 + 내용’ / ’내용 + 작성자’ / ‘제목 + 작성자’와 같이 2개의 항목으로 검색하는 경우
‘제목 + 내용 + 작성자’ 같이 3개의 항목으로 검색하는 경우
Querydsl의 사용법
BooleanBuilder 생성
조건에 맞는 구무은 Querydsl에서 사용하는 Predicate 타입의 함수를 생성
BooleanBuilder에 작성된 Predicate를 추가하고 실행
단일 항목 검색 테스트
‘제목(title)’에 ‘1’이라는 글자가 있는 엔티티들 검색
GuestbookRepositoryTest 중 일부
가장 먼저 동적으로 처리하기 위해서 Q도메인 클래스를 얻어옴. Q도메인 클래스를 이용하면 엔티티 클래스에 선언된 title, content같은 필드들을 변수로 활용할 수 있음
BooleanBuilder는 where문에 들어가는 조건들을 넣어주는 컨테이너
원하는 조건은 필드 값과 같이 결합해서 생성. BooleanBuilder 안에 들어가는 값은 com.querydsl.core.types.Predicate 타입이어야 함
만들어진 조건은 where문에 and나 or 같은 키워드와 결합
BooleanBuilder는 GuestbookRepository에 추가된 QueryPredicateExcutor 인터페이스의 findAll()을 사용할 수 있음ㅁ
이를 통해 페이지 처리와 동시에 검색 처리가 가능해짐

다중 항목 검색 테스트
복합 조건은 여러 조건이 결합된 형태로 예를 들면,
‘제목(title) 혹은 내용(content)’에 특정한 키워드가 있고 ‘gno가 0보다 크다'와 같은 조건 처리
GuestbookRepositoryTest 중 일부

4.4 서비스 계층과 DTO
JPA를 이용하게 되면 엔티티 객체는 단순히 데이터를 담는 객체가 아니라 실제 데이터베이스와 관련이 있고, 내부적으로 엔티티 매니저(entity manager)가 관리하는 객체이다.
DTO 가 일회성으로 데이터를 주고받는 용도로 사용되는 것과 달리 생명주기(life cycle)도 전혀 다르기 때문에 분리해서 처리하는 것을 권장한다.
! 웹 애플리케이션을 제작할 때는 HttpServletRequest나 HttpservletResponse를 서비스 계층으로 전달하지 않는 것을 원칙으로 한다. 유사하게 엔티티 객체가 JPA에서 사용하는 객체이므로 JPA 외에서 사용하지 않는 것을 권장한다.
GuestbookDTO
GuestbookService 인터페이스
GuestbookServiceImpl
4.4.1 등록과 DTO를 엔티티로 변환하기
서비스 계층에서는 파라미터를 DTO Type으로 받기 때문에 이를 JPA로 처리하기 위해서 Entity Type의 객체로 변환해야 하는 작업이 필요
ModelMapper
MapStruct
여기서는 직접
GuestbookService 인터페이스
GuestbookServiceImpl
GuestbookServiceTest

GuestbookServiceImpl
GuestbookServiceImpl 클래는 JPA 처리를 위해서 GuestbookRepository를 주입
클래스 선언 시에 @RequiredArgsConstructor를 이용해서 자동으로 주입
register()의 내부에서는 save()를 통해서 저장
저장된 후 해당 엔티티가 가지는 gno값을 반환
testRegister() ㄱ ㄱ


4.5 목록 처리
화면에서 필요한 목록 데이터에 대한 DTO 생성
DTO를 Pageable 타입으로 전환
Page<Entity>를 화면에서 사용하기 쉬운 DTO의 리스트 등으로 변환
화면에 필요한 페이지 번호 처리
4.5.1 목록 처리를 위한 DTO
페이지 요청 처리 DTO
PageRequestDTO
페이지 결과 처리 DTO
PageResultDTO
4.5.2 서비스 계층에서는 목록 처리
GuestbookService 인터페이스
GuestbookserviceImpl
목록 처리 테스트
GusetbookServiceTest

목록 데이터 페이지 처리
화면에서 시작 페이지 번호(start)
화며에서 끝 페이지 번호(end)
이전/다음 이동 링크 여부(prev, next)
현재 페이지 번호(page)
PageResultDTO
GuestbookServiceTest

4.6 컨트롤러와 화면에서의 목록 처리
GuestbookController
list.html

4.6.1 목록 페이지 처리
/guestbook/list 혹은 /guestbook/list?page=1의 경우 아래와 같이 1페이지 출력
list.html

페이지별 링크 처리
list.html

Last updated