Post

[Spring Boot] 게시글 수정하기: Update

데이터 수정 과정

게시판에 작성한 글을 수정하려면 해당 글을 불러와 수정할 수 있는 상태로 만들고, 내용 입력 후 DB에 전송하면 최종적으로 수정되어야 한다.

  1. 수정 페이지 만들고 기존 데이터 불러오기
    • 상세 페이지에서 수정 버튼 클릭
    • 요청을 받은 컨트롤러가 해당 글의 id로 Db에서 데이터를 찾아 가져옴
    • 컨트롤러는 가져온 데이터를 뷰에서 사용할 수 있도록 모델에 등록
    • 모델에 등록된 데이터를 수정 페이지에서 보여줌 > 사용자가 내용을 수정할 수 있는 상태

요청 > Controller > DB > Controller > Model > View

  1. 데이터를 수정해 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 버튼을 클릭하면!

404 Error

위와 같은 페이지가 뜬다. 왜냐!

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를 넣어주었다.

Article List

Edit Page

이제 잘 나온다!

수정 데이터를 DB에 갱신하기

이제 수정한 데이터를 DB에 반영한 후 결과를 볼 수 있게 상세 페이지로 리다이렉트 해보자.

이렇게 리다이렉트하는 과정은 다음과 같다.

  1. 수정 페이지에서 HTTP 메서드를 통해 컨트롤러에 데이터 수정 요청
  2. 컨트롤러가 DTO를 엔티티로 변환해 리파지터리에 전달
  3. 리파지터리는 JPA를 이용해 DB 갱신 후 결과를 엔티티로 변환해 컨트롤러에 재전달
  4. 수정 페이지 출력

더미 데이터 설정하기

서버를 껐다 켤 때마다 매번 데이터를 입력해야 하는 번거로움을 해결하기 위해 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 List - Dummy Data

이제 article 리스트 화면을 보면 더미 데이터가 정상적으로 들어가 있는 것을 볼 수 있다.

수정 페이지 변경

이제 수정 페이지를 변경해야 한다. <form> 데이터를 어디로 보내야 할지 설정해야 하기 때문이다.

1
<form class="container" action="/articles/update" method="post">

methodHTTP 프로토콜 규격에 따르면 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에 저장하고 상세 페이지를 리다이렉트 해줄수 있다.

  1. DTO를 엔티티로 변환하기
  2. 엔티티를 DB에 저장하기
  3. 수정 결과 페이지로 리다이렉트하기
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
This post is licensed under CC BY 4.0 by the author.