[Spring Boot] 게시글 읽기: Read
데이터 조회 과정
웹 페이지에서 게시글을 등록하면 서버를 통해 DB에 저장된다. 이렇게 DB에 저장된 데이터를 웹 페이지에 출력하는 과정은 다음과 같다.
- 사용자가 데이터를 조회해 달라고 웹 페이지에서 URL 요청을 보낸다
- 서버의 컨트롤러가 요청을 받아 해당 URL에서 찾으려는 데이터 정보를 리파지터리에 전달한다.
- 리파지터리는 정보를 가지고 DB에 데이터 조회를 요청한다.
- DB는 해당 데이터를 찾아 이를 엔티티로 반환한다.
- 반환된 엔티티는 모델을 통해 뷰 템플릿으로 전달된다.
- 최종적으로 결과 뷰 페이지가 완성돼 사용자의 화면에 출력된다.
단일 데이터 조회하기
URL 요청받기
게시글 1번 id를 조회할 때 /articles/1, 2번 id를 조회할 때 /articles/2 형식으로 접속하도록 한다.
URL 요청을 받아줄 컨트롤러 만들기
1
2
3
4
@GetMapping("/articles/{id}")
public String show(@PathVariable Long id) {
return "";
}
URL 요청을 받아 수행할 메서드를 만든다. 메서드의 매개변수는 URL에 있는
id
를 가져오는데,id
앞에@PathVariable
어노테이션을 붙인다. URL 요청으로 들어온 전달값을 컨트롤러의 매개변수로 가져오는 어노테이션이다.로깅을 통해 컨트롤러가
id
를 잘 받아왔는지 확인한다.
1
log.info("id = " + id);
/articles/1000을 입력했을 때 id
값으로 1000을 잘 받아오고 있음을 확인할 수 있다.
데이터 조회해 출력하기
id를 조회해 데이터 가져오기
DB에서 데이터를 가져오는 주체인 리파지터리를 통해 데이터를 가져올 수 있다.
1
Article articleEntity = articleRepository.findById(id).orElse(null);
특별히 조회된 데이터가 없는 경우도 처리해주어야 하기 때문에 orElse(null)
을 사용한다. id
값으로 데이터를 찾을 때 해당 id
값이 없으면 null
을 반환한다.
자바 8 버전부터 사용할 수 있는 방법으로 다음과 같이 가져올 수도 있다.
1
Optional<Article> articleEntity = articleRepository.findById(id);
모델에 데이터 등록하기
MVC 패턴에 따라 조회한 데이터를 뷰 페이지에서 사용하기 위해 모델에 데이터를 등록해야 한다.
1
model.addAttribute("article", articleEntity);
모델에 데이터를 등록할 때는 model.addAddribute(String name, Object value)
형식으로 등록할 수 있다.
뷰 페이지 반환하기
컨트롤러에서 show 메서드의 반환값을 보여줄 페이지 경로로 수정한다.
1
return "articles/show";
이제 데이터를 보여줄 mustache 파일을 작성한다. 모델에 등록한 article 엔티티는 뷰 페이지에서 이중 중괄호를 이용해 출력할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<table class="table">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Title</th>
<th scope="col">Content</th>
</tr>
</thead>
<tbody>
{{#article}}
<tr>
<th scope="row">{{id}}</th>
<td colspan="2">{{title}}</td>
<td>{{content}}</td>
</tr>
{{/article}}
</tbody>
</table>
Article 엔티티에 기본 생성자 추가하기
엔티티에 기본 생성자가 존재하지 않으면 조회 시 오류가 발생한다. Article 엔티티에 @NoArgsConstructor
어노테이션을 이용해 매개변수가 없는 기본 생성자를 추가해준다.
서버를 재시작하고 글을 등록한 후 articles/1에 접속하면 방금 등록한 게시글을 조회할 수 있게 된다.
데이터 목록 조회하기
데이터 목록 조회는 단일 데이터를 조회할 때와 과정은 같지만 엔티티의 묶음인 리스트를 반환한다는 점이 다르다.
findAll()
메서드를 반환받는 세 가지 방법
findAll()
메서드는 Iterable 형식으로 결과를 반환하고 있다. 이 형식과 관련된 인터페이스/클래스는 다음과 같다.
ArrayList(Class) > List(Interface) > Collection(Interface) > Iterable(Interface)
따라서 다음과 같은 세 가지 방법으로 결과를 반환받을 수 있다.
Down Casting해서 List 사용하기
findAll()
메서드가 반환하는 데이터 타입 Iterable<Article>
을 List<Article>
로 다운캐스팅한다.
Up Casting해서 Iterable 사용하기
articleEntityList의 타입을 findAll()
메서드가 반환하는 타입으로 맞춘다.
1
Iterable<Article> articleEntityList = articleRepository.findAll();
ArrayList를 반환받도록 수정하기
CurdRepository를 상속받고 있는 ArticleRepository의 메서드를 오버라이딩해 findAll()
의 반환값을 ArrayList로 바꿔준다.
1
2
3
4
public interface ArticleRepository extends CrudRepository<Article, Long> {
@Override
ArrayList<Article> findAll();
}
1
ArrayList<Article> articleEntityList = articleRepository.findAll();
뷰 페이지 설정하기
뷰 페이지도 똑같이 설정해준다. 뷰 페이지에서 #articleList는 Entity가 존재하는 만큼 내부 코드를 반복하게 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<table class="table">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Title</th>
<th scope="col">Content</th>
</tr>
</thead>
<tbody>
{{#articleList}}
<tr>
<th scope="row">{{id}}</th>
<td colspan="2">{{title}}</td>
<td>{{content}}</td>
</tr>
{{/articleList}}
</tbody>
</table>
🔗 참고자료
📚 더 공부해야 할 것
- Optional
- Iterable, List, ArrayList > 업캐스트와 다운캐스팅 실습
- Generic
- @PathVariable
- CrudRepository