스프링 부트와 AWS로 혼자 구현하는 웹 서비스
: 인텔리제이, JPA, JUnit 테스트, 그레이들, 소셜 로그인, AWS 인프라로 무중단 배포까지
이동욱 저
Table of Content
게시글 조회(READ) 화면 구성하기
index.mustache
{{>layout/header}}
<h1>스프링부트로 시작하는 웹 서비스 Ver.2</h1>
<div class="col-md-12">
<div class="row">
<div class="col-md-6">
<a href="/posts/save" role="button" class="btn btn-primary">글 등록</a>
</div>
</div>
<br>
<!-- 목록 출력 영역 -->
<table class="table table-horizontal table-bordered">
<thead class="thead-strong">
<tr>
<th>게시글번호</th>
<th>제목</th>
<th>작성자</th>
<th>최종수정일</th>
</tr>
</thead>
<tbody id="tbody">
{{#posts}}
<tr>
<td>{{id}}</td>
<td><a href="/posts/update/{{id}}">{{title}}</a></td>
<td>{{author}}</td>
<td>{{modifiedDate}}</td>
</tr>
{{/posts}}
</tbody>
</table>
</div>
{{>layout/footer}}
HTML
복사
머스테치의 문법 {{#posts}}
•
posts라는 List를 순회
•
Java의 문과 동일하게 생각
{{id}}, {{title}} …
•
위 posts 리스트에서의 id, title등 객체의 필드를 사용
PostsRepository.java
package com.citefred.ldwspring.domain.posts;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface PostsRepository extends JpaRepository<Posts, Long> {
@Query("SELECT p FROM Posts p ORDER By p.id DESC")
List<Posts> findAllDesc();
}
Java
복사
@Query
•
@Query 어노테이션은 JPQL(Java Persistence Query Language) 또는 네이티브 쿼리를 사용하여 직접 쿼리를 작성할 수 있게 해준다.
◦
그 중에서도 JPQL은 엔터티 객체를 대상으로 하는 객체 지향 쿼리 언어
◦
네이티브 쿼리는 직접 SQL을 사용하는 방식
▪
JPQL은 엔터티 객체를 기반으로 쿼리하기 때문에 객체 그래프를 사용할 수 있고, 상속과 다형성을 지원한다는 장점이 있다.
▪
또한 JPQL은 데이터베이스 종속적이지 않아서 데이터베이스를 변경해도 쿼리를 수정할 필요가 없다는 장점도 있다.
PostsService.java
package com.citefred.ldwspring.service;
import com.citefred.ldwspring.domain.posts.Posts;
import com.citefred.ldwspring.domain.posts.PostsRepository;
import com.citefred.ldwspring.web.dto.PostsListResponseDto;
import com.citefred.ldwspring.web.dto.PostsResponseDto;
import com.citefred.ldwspring.web.dto.PostsSaveRequestDto;
import com.citefred.ldwspring.web.dto.PostsUpdateRequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
@RequiredArgsConstructor
@Service
public class PostsService {
private final PostsRepository postsRepository;
...
@Transactional(readOnly = true)
public List<PostsListResponseDto> findAllDesc(){
return postsRepository.findAllDesc().stream()
.map(PostsListResponseDto::new)
.collect(Collectors.toList());
}
}
Java
복사
.map(PostsListResponseDto::new)
•
== .map(posts -> new postsListResponseDto(posts))
•
postRepository 결과로 넘어온 Posts의 Stream을 map을 통해 PostListResponseDto로 변환 →List로 반환하는 메소드
PostsListResponseDto.java
package com.citefred.ldwspring.web.dto;
import com.citefred.ldwspring.domain.posts.Posts;
import lombok.Getter;
import java.time.LocalDateTime;
@Getter
public class PostsListResponseDto {
private Long id;
private String title;
private String author;
private LocalDateTime modifiedDate;
public PostsListResponseDto(Posts entity){
this.id = entity.getId();
this.title = entity.getTitle();
this.author = entity.getAuthor();
this.modifiedDate = entity.getModifiedDate();
}
}
Java
복사
게시글 목록 반환 Dto
IndexController.java
package com.citefred.ldwspring.web;
import com.citefred.ldwspring.service.PostsService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@RequiredArgsConstructor
@Controller
public class IndexController {
private final PostsService postsService;
@GetMapping("/")
public String index(Model model){
model.addAttribute("posts", postsService.findAllDesc());
return "index";
}
...
}
Java
복사
Model
•
Model은 HashMap 형태를 갖고 있으며, key, value값을 가지고 있다. 또한 addAttribute()와 같은 기능을 통해 모델에 원하는 속성과 그것에 대한 값을 주어 전달할 뷰에 데이터를 전달할 수 있다.
•
서버 템플릿 엔진에서 사용 할 수 있는 객체를 저장(뷰 페이지로 전달)
•
여기서는 postsService.findAllDesc()로 가져온 게시글 리스트 PostsResponseDto의 리스트(맵)을 “posts”라는 이름으로 index.mustache에 전달하게 됨
•
위 mustache 문법이었던 {{#posts}}라는 구문을 통해서 전달된 데이터를 사용 할 수 있음
글 조회 뷰 페이지+API 작동 테스트
Related Posts
Search