[Spring Boot] Day7 - Update

Sarah·2025년 12월 1일

Spring Boot

목록 보기
8/17

오늘의 목표

<상세 페이지> 에서 Edit 버튼을 만들고, Edit 버튼을 통해 <수정 페이지>에서 내용을 편집하고, 해당 게시물의 데이터를 수정한다!


<상세 페이지>에 Edit 버튼 추가

<a href="/articles/{{article.id}}/edit" class="btn btn-primary">Edit</a>

<상세 페이지>에 해당하는 show.mustache 파일에서 맨 끝에 버튼을 넣는 코드를 추가하였다.
/articles/1/edit 이라면 id가 1인 게시물의 edit 페이지로 이동하는 href도 추가하였다.

해당 show.mustache 뷰 페이지는 ArticleController에서 show() 메서드와 연결되어 있다. show() 메서드 내에서 "article"이라는 이름으로 articleEntity를 모델에 등록하였다.
따라서 show.mustache 뷰 페이지 파일에서
{{article.id}} 로 엔티티의 id에 접근할 수 있다.

<ArticleController의 show() 메서드>

    @GetMapping("/articles/{id}")
    public String show(@PathVariable Long id, Model model) {
        log.info("id = " + id); 
        Article articleEntity = articleRepository.findById(id).orElse(null);
        model.addAttribute("article", articleEntity);
        return "articles/show";
    }

Edit() 메서드 만들기

/articles/{id}/edit 이라는 URL이 요청되면 실행되는 edit() 메서드를 만든다.

    @GetMapping("/articles/{id}/edit")
    public String edit(@PathVariable Long id, Model model) {
        Article articleEntity = articleRepository.findById(id).orElse(null);
        model.addAttribute("article", articleEntity);
        return"articles/edit";
    }

@GetMapping("/articles/{id}/edit")
/articles/{id}/edit 이라는 URL이 요청되면 해당 메소드를 실행한다는 의미

@PathVariable : GetMapping에 있는 id를 그대로 매개변수로 가져오는 어노테이션.

Article articleEntity = articleRepository.findById(id).orElse(null);
리파지터리로 findById(id) 메서드를 호출하여 해당 id의 데이터를 가져와서 articleEntity 라는 엔티티에 저장한다.

model.addAttribute("article", articleEntity);
Model의 addAttribute 메서드를 사용해서 뷰 페이지에서 데이터를 넣을 수 있도록 한다. article 이라는 이름으로 articleEntity 엔티티 데이터를 등록한다.


Edit <수정 페이지> 만들기

edit 뷰 페이지는 우선 articles/new 뷰 페이지의 코드를 복붙해온다.

{{>layouts/header}}

{{#article}}
<form class="container" action="/articles/update" method="post">
    <input name="id" type="hidden" value="{{id}}">
    <div class="mb-3">
        <label class="form-label">제목</label>
        <input type="text" class="form-control" name="title" value="{{title}}">
    </div>
    <div class="mb-3">
        <label class="form-label">내용</label>
        <textarea class="form-control" rows="3" name="content">{{content}}</textarea>
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
    <a href="/articles/{{id}}">Back</a>
</form>
{{/article}}

{{>layouts/footer}}
  1. edit 페이지의 폼에서는 폼 제출을 하고 나면 /articles/update로 보낼 것이기 때문에 action부분을 수정해준다.

  2. 바로 아래 input을 추가해준다.
    글을 업데이트할 때 서버가 어떤 글인지 알아야하기 때문에 이 글의 식별자 (id)를 추가해줘야 한다.

  3. Controller의 edit() 메서드에서 article 이라는 이름으로 엔티티를 만들었으니, form 전체는 {{#article}} {{/article}} 로 묶어준다.

  4. title/content의 기본 값이 해당 aritcle의 title/content 값이 들어가 있을 수 있도록 value={{title}} value={{content}} 추가.

  5. Back 버튼을 눌렀을 때는 이전 페이지인 해당 id의 게시글을 보여주는 페이지로 돌아가야하기 때문에 <a href="/articles/{{id}}">Back</a>로 변경


수정된 데이터 받아오기

앞에서 edit.mustache에서 폼 데이터를 "/articles/update"로 post 형식으로 보냈다. 따라서, 컨트롤러에서 @PostMapping("/articles/update")가 달린 update() 메서드를 만들어야 한다.

    @PostMapping("/articles/update")
    public String update(ArticleForm form) {
        log.info(form.toString());
        Article articleEntity = form.toEntity();
        log.info(articleEntity.toString());
        Article target = articleRepository.findById(articleEntity.getId()).orElse(null);
        if(target != null) {
            articleRepository.save(articleEntity);
        }
        return "redirect:/articles/" + articleEntity.getId();
    }

@PostMapping("/articles/update")
/articles/update로 폼 데이터가 전송되면 해당 메소드가 실행된다는 의미.

public String update(ArticleForm form)
edit 페이지에서 폼 데이터를 전송했다. 폼 데이터는 꼭 DTO로 받아와야 하기 때문에 매개변수에 DTO인 ArticleForm 타입을 넣어준다.

Article articleEntity = form.toEntity();
DB에 접근해서 입력/수정/삭제하려면 Entity를 통해서 접근해야 하기 때문에 toEntity() 메서드를 호출하여 articleEntity 객체에 엔티티를 저장한다.

Article target = articleRepository.findById(articleEntity.getId()).orElse(null);
앞서 저장된 articleEntity는 "수정 페이지에서 전달된 폼 데이터"를 가지고 있다. 하지만 여기 target이라는 객체는 "수정 페이지에서 전달된 폼 데이터"의 고유값인 Id에 해당하는 데이터를 의미한다. 즉!!!!! 그 id로 이미!!저장된 데이터!
따라서

if(target != null) { articleRepository.save(articleEntity); }
그 id로 이미 저장된 데이터가 있다면?
리파지터리를 사용하여 "수정 페이지에서 전달된 폼 데이터"를 save 한다.
여기서 save를 하게 되면 데이터는 덮어쓰기 되어 데이터 수정이 된다.

return "redirect:/articles/" + articleEntity.getId(); : return 값으로는 해당 id의 상세 페이지로 이동할 수 있도록 해야 한다. id 부분은 엔티티에 따라 매번 바뀌기 때문에 articleEntity.getId()로 id를 가져오고 리다이렉트를 사용한 /articles/와 + 연산자로 연결시켜준다.


처음에는 하나도 이해가 안됐는데 복습하다보니 점점 감이 잡히고 어떻게 돌아가는건지 이해가 되기 시작했다. 하지만 아직 설명하는 건 참 힘든 것 같다.... 주절 주저리

profile
헤맨 만큼 내 땅

0개의 댓글