[Spring Boot] 게시글 수정하기: Update
데이터 수정 과정
게시판에 작성한 글을 수정하려면 해당 글을 불러와 수정할 수 있는 상태로 만들고, 내용 입력 후 DB에 전송하면 최종적으로 수정되어야 한다.
- 수정 페이지 만들고 기존 데이터 불러오기
- 상세 페이지에서 수정 버튼 클릭
- 요청을 받은 컨트롤러가 해당 글의
id
로 Db에서 데이터를 찾아 가져옴 - 컨트롤러는 가져온 데이터를 뷰에서 사용할 수 있도록 모델에 등록
- 모델에 등록된 데이터를 수정 페이지에서 보여줌 > 사용자가 내용을 수정할 수 있는 상태
✏ 요청 > Controller > DB > Controller > Model > View
- 데이터를 수정해 DB에 반영한 후 결과를 볼 수 있게 상세 페이지로 리다이렉트 하기
- 폼 데이터를 DTO에 담아 컨트롤러에서 받음
- DTO를 엔티티로 번환
- DB에서 기존 데이터를 수정 데이터로 갱신
- 수정 데이터를 상세 페이지로 리다이렉트
✏ View > Controller > DB > Controller > View
수정 페이지 만들기
상세 페이지에 Edit 버튼 만들기
Edit 버튼은 <a>
태그를 추가하고 href
속성값으로 연결하려는 URL을 추가한다.
1
<a href="/articles/{{article.id}}/edit" class="btn btn-primary">Edit</a>
어떤 글을 수정할 것인지에 대한 정보가 필요하기 때문에 id값을 URL에 넣어 기억해야 한다.
1번 글을 수정할 경우 /articles/1/edit, 2번 글을 수정할 경우 /articles/2/edit 페이지로 이동하게 된다.
Edit 요청을 받아 데이터 가져오기
이제 View에서 보낸 요청 /articles/{id}/edit을 Controller에서 받아주어야 한다. 이전과 동일한 방법으로 폼 데이터를 받아준다.
1
2
3
4
5
6
7
8
9
@GetMapping("/articles/{id}/edit")
public String edit(@PathVariable Long id, Model model) {
// 1. 수정할 데이터 가져오기
Article articleEntity = articleRepository.findById(id).orElse(null);
// 2. 모델에 데이터 등록하기
model.addAttribute("article", articleEntity);
// 3. 뷰 페이지 설정하기
return "articles/edit";
}
수정할 데이터를 id를 이용해 DB에서 가져오고, 모델에 등록한 후 뷰 페이지를 반환하도록 한다.
이제 데이터를 입력하고, 상세 페이지에 만들어진 Edit 버튼을 클릭하면!
위와 같은 페이지가 뜬다. 왜냐!
1
There was an unexpected error (type=Not Found, status=404).
위 문구를 살펴보면, status=404
임을 살펴볼 수 있다. HTTP 404 오류 코드는 서버에서 파일을 찾지 못했을 때 발생하는 에러다. 즉, articles/edit 파일이 존재하지 않아서 그렇다.
수정 폼 만들기
이제 edit 파일을 만들어 404 에러를 해결할 차례다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{{#article}}
<form class="container" action="" method="post">
<div class="mb-3">
<label class="form-label">제목</label>
<input type="text" name="title" class="form-control" value="{{title}}">
</div>
<div class="mb-3">
<label class="form-label">내용</label>
<textarea class="form-control" name="content" rows="3">{{content}}</textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<a href="/articles/{{id}}">Back</a>
</form>
{{/article}}
resources > templates > articles > edit.mustache 파일을 만들어 다음과 같이 적어주었다.
<input>
태그의 value
속성에 변수를 넣어주면 값을 설정할 수 있다.
Back을 눌렀을 때는 해당 게시글의 상세페이지로 돌아가야 하기 때문에 href
속성에 /articles/id를 넣어주었다.
이제 잘 나온다!
수정 데이터를 DB에 갱신하기
이제 수정한 데이터를 DB에 반영한 후 결과를 볼 수 있게 상세 페이지로 리다이렉트 해보자.
이렇게 리다이렉트하는 과정은 다음과 같다.
- 수정 페이지에서 HTTP 메서드를 통해 컨트롤러에 데이터 수정 요청
- 컨트롤러가 DTO를 엔티티로 변환해 리파지터리에 전달
- 리파지터리는 JPA를 이용해 DB 갱신 후 결과를 엔티티로 변환해 컨트롤러에 재전달
- 수정 페이지 출력
더미 데이터 설정하기
서버를 껐다 켤 때마다 매번 데이터를 입력해야 하는 번거로움을 해결하기 위해 sql 파일을 만들어 더미 데이터를 자동 생성할 수 있게 할 수 있다.
단, 스프링 부트 2.5 버전부터 권장되지 않는 방법이기 때문에 추가 설정이 필요하다.
application.properties
파일에 다음과 같이 입력한다.
1
spring.jpa.defer-datasource-initialization=true
그리고 resources 폴더에 data.sql파일을 생성한 후 다음과 같이 더미 데이터를 넣는다.
1
2
3
INSERT INTO article(id, title, content) VALUES(1, '가가가가', '1111');
INSERT INTO article(id, title, content) VALUES(2, '나나나나', '2222');
INSERT INTO article(id, title, content) VALUES(3, '다다다다', '3333');
이제 article 리스트 화면을 보면 더미 데이터가 정상적으로 들어가 있는 것을 볼 수 있다.
수정 페이지 변경
이제 수정 페이지를 변경해야 한다. <form>
데이터를 어디로 보내야 할지 설정해야 하기 때문이다.
1
<form class="container" action="/articles/update" method="post">
method
는 HTTP 프로토콜 규격에 따르면 PATCH에 해당하지만, <form>
태그는 PATCH를 지원하지 않기 때문에 POST 메서드를 통해 요청을 보낸다.
이때 서버로 id 데이터도 함께 보내야 하기 때문에 <input>
태그를 하나 만들어 id값을 보내도록 한다.
1
<input name="id" type="hidden" value="{{id}}"/>
위치는 <form>
태그 안이라면 어디든 상관 없다.
수정 데이터 받아오고 DB에 저장하기
이제 보낸 폼 데이터를 컨트롤러에서 받아오기 위해 컨트롤러를 수정한다.
1
2
3
4
@PostMapping("/articles/update")
public String update(ArticleForm form) {
return "";
}
POST 메소드를 통해 데이터를 보내고 있으므로 @PostMapping
어노테이션을 사용한다.
폼에서 전송한 데이터는 DTO로 받아오기 때문에 매개변수로 ArticleForm form
DTO를 추가해준다.
이제 다음과 같은 3단계를 거쳐 DB에 저장하고 상세 페이지를 리다이렉트 해줄수 있다.
- DTO를 엔티티로 변환하기
- 엔티티를 DB에 저장하기
- 수정 결과 페이지로 리다이렉트하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@PostMapping("/articles/update")
public String update(ArticleForm form) {
// 1. DTO를 엔티티로 변환하기
Article articleEntity = form.toEntity();
log.info(articleEntity.toString());
// 2. 엔티티를 DB에 저장하기
// 2-1. DB에서 기존 데이터 가져오기
Article target = articleRepository.findById(articleEntity.getId()).orElse(null);
// 2-2. 기존 데이터 값을 갱신하기
if (target != null) {
articleRepository.save(articleEntity);
}
// 3. 수정 결과 페이지로 리다이렉트하기
return "redirect:/articles/" + articleEntity.getId();
}
이제 수정 페이지를 통해 게시글 수정을 할 수 있게 됐다.
🔗 참고자료
📚 더 공부해야 할 것
- HTTP
- @PatchMapping은 어느 경우에 사용할 수 있을까?
- @PostMapping과 @PatchMapping을 사용한 각각의 경우 차이점이 뭘까?
- defer-datasource-initialization