7.1 데이터 수정 과정
게시판에 작성한 글을 수정하려면 해당 글을 불러와 수정할 수 있는 입력 상태로 만들어야 합니다. 그다음 내용을 입력하고 다시 전송하면 DB에 반영돼 최종적으로 수정됩니다. 데이터 수정 실습은 크게 2단계로 나누어집니다.
1. <수정 페이지> 만들고 기존 데이터 불러오기
2. 데이터를 수정해 DB에 반영한 후 결과를 볼 수 있게 <상세 페이지>로 리다이렉트하기
먼저 1단계가 어떻게 동작하는지 살펴보겠습니다.
(1) <상세 페이지>에서 [Edit] 버튼을 클릭합니다.
(2) 요청을 받은 컨트롤러는 해당 글의 id로 DB에서 데이터를 찾아 가져옵니다.
(3) 컨트롤러는 가져온 데이터를 뷰에서 사용할 수 있도록 모델에 등록합니다.
(4) 모델에 등록된 데이터를 <수정 페이지>에서 보여 줍니다. 그러면 사용자가 내용을 수정할 수 있는 상태가 됩니다.
2단계는 다음과 같이 동작합니다.
(1) 폼 데이터(수정 요청 데이터)를 DTO에 담아 컨트롤러에서 받습니다.
(2) DTO를 엔티티로 변환합니다.
(3) DB에서 기존 데이터를 수정 데이터로 갱신합니다.
(4) 수정 데이터를 <상세 페이지>로 리다이렉트합니다.
7.2 <수정 페이지> 만들기
7.2.1 <상세 페이지에>에 Edit 버튼 만들기
1. 상세 페이지인 show.mustache 파일을 엽니다. </table> 아래에 <a> 태그를 추가하고 href 속성 값으로 연결하려는 URL인 "/articles/{article.id}/edit"를 작성합니다. 1번글을 수정할 경우 /articles/1/edit 페이지로, 2번 글을 수정할 경우 /articles/2/edit 페이지로 이동하라는 의미입니다. 링크를 걸 텍스트는 Edit로 설정합니다.
</table>
<a href="articles/{{articles.id}}/edit">Edit</a>
<a href="/articles">Go to Article List</a>
href 속성 값의 URL을 보면 id가 article의 속성이므로 {{article.id}}로 표시했습니다. 보통 article의 사용 범위를 {{#article}}{{/article}} 형식으로 지정한 경우에는 {{id}}만 써도 되지만 범위를 따로 지정하지 않았다면 점(.)을 사용해 {{article.id}}라고 표시해야 합니다.
2. 링크가 잘 걸렸는지 확인해 보겠습니다. 서버를 실행하고 localhost:8080/articles/new에 접속해 제목은 가가가가, 내용은 1111을 입력하고 [Submit] 버튼을 클릭합니다. 목록 페이지를 보면 방금 입력한 데이터가 잘 들어 갔고 목록 아래 Edit 링크가 생긴 것을 확인할 수 있습니다.
3. 부트스트랩 CSS를 적용해 class="btn bnt-primary" 속성을 추가합니다.
4. 서버를 실행하고 목록 페이지를 새로 고침하면 [Edit] 버튼이 잘 나오는 것을 확인할 수 있습니다.
7.2.2 Edit 요청을 받아 데이터 가져오기
[Edit] 버튼을 클릭해 볼까요? 에러 페이지가 뜹니다. 아직 Edit 요청을 받을 컨트롤러를 만들지 않았기 때문입니다. 해당 컨트롤러를 만들어 봅시다.
- edit() 메서드 기본 틀 만들기
ArticleController.java 파일을 열고 index() 메서드 아래에 edit() 메서드를 추가합니다.
1. 수정 요청을 받아 처리할 edit() 메서드를 작성하고 반환할 수정 페이지를 articles 디렉터리 안에 edit.mustache 파일로 생성합니다.
2. URL 요청을 받은 @GetMapping()을 작성합니다. 괄호 안에는 show.mustache 파일에서 "/articles/{{article.id}}/edit" 주소로 연결 요청했으므로 이 URL인 "/articles/{id}/edit"를 작성합니다. 이때 변수 id는 {{id}}가 아니라 {id}라고 작성해야 합니다. 뷰 페이지에서 변수를 사용할 때는 중괄호를 두 개 ({{}}) 쓰지만 컨트롤러에서 URL 변수를 사용할 때는 하나({})만 씁니다.
@GetMapping("/articles/{id}/edit") //2.URL 요청 접수
public String edit(){ //1.메서드 생성 및 뷰 페이지 설정
return "articles/edit";
}
- 수정할 데이터 가져오기
다음으로 DB에 있는 기존 데이터를 불러오는 코드를 작성합니다.
1. DB에서 데이터를 가져올 때는 리파지터리를 이용합니다. 따라서 articleRepository의 findById(id) 메서드로 데이터를 찾아 가져옵니다. 만약 데이터를 찾지 못하면 null을 반환하고, 데이터를 찾았다면 Article 타입의 articleEntity로 저장합니다.
2. 코드를 작성하고 나면 findById(id)에서 괄호 안으 id가 빨간색으로 표시됩니다. 메서드에서 id라는 변수가 선언되지 않았기 때문입니다. id는 메서드의 매개변수로 받아 오고 자료형은 Long으로 작성합니다. 그리고 GetMapping() 어노테이션의 URL 주소에 있는 id를 받아 오는 것이므로 데이터 타입 앞에 @PathVariable 어노테이션을 추가합니다.
@GetMapping("/articles/{id}/edit")
public String edit(@PathVariable Long id){
//수정할 데이터 가져오기
Article articleEntity = articleRepository.findById(id).orElse(null);
//뷰 페이지 설정하기
return "articles/edit";
}
- 모델에 데이터 등록하기
DB에서 데이터를 가져왔으니 뷰 페이지에서 사용할 수 있도록 모델에 데이터를 등록하겠습니다.
1. 모델을 사용하기 위해 메서드의 매개변수로 model 객체를 받아 옵니다.
2. addAttribute() 메서드로 모델에 데이터를 등록합니다. article이라는 이름으로 앞에서 가져온 articleEntity를 등록합니다. 이렇게 하면 DB에서 가져온 데이터를 article이라는 이름으로 뷰 페이지에서 사용할 수 있습니다.
@GetMapping("/articles/{id}/edit")
public String edit(@PathVariable Long id, Model model){ //1.model 객체 받아 오기
//수정할 데이터 가져오기
Article articleEntity = articleRepository.findById(id).orElse(null);
//모델에 데이터 등록하기
model.addAttribute("article",articleEntity)//2.articleEntity를 article로 등록
//뷰 페이지 설정하기
return "articles/edit";
}
7.2.3 수정 폼 만들기
1. src > main > resources > template > articles에서 마우스 오른쪽 버튼을 누르고 New -> File을 선택합니다. 파일 이름은 edit.mustache라고 입력합니다. 새 편집기가 열리면 해더-푸터의 샌드위치 구조를 만듭니다.
{{>layouts/header}}
{{>layouts/footer}}
2. 여기서 데이터를 수정하는데, 수정 폼 글은 새로 작성하는 입력 폼과 유사합니다. 따라서 입력 페이지(new.mustache)의 코드를 변형해서 사용하겠습니다.
new.mustache 파일을 열어 <form class="container" ...>...</form> 부분을 복사합니다.
3. edit.mustache 파일로 돌아와 헤더-푸터 가운데 코드를 붙여 넣습니다. 그리고 두 군데를 다음과 같이 수정합니다.
(1) <form> 태그의 action 속성 값을 공백으로 만듭니다. 이 부분은 다음 절에서 채워 넣겠습니다.
(2) 수정 페이지에서 Back 링크를 누르면 상세 페이지로 돌아와야 합니다. 따라서 href 속성 값을 "/articles/{{articles.id}}"로 수정합니다. 앞에서 모델에 article을 등록했기 때문에 article에 점(.)을 찍고 id라고 써 주면 해당 id 값을 추출해 URL로 사용할 수 있습니다.
{{>layouts/header}}
<form class="container" action="" method="post"> <!-- 1.action 속성 값 삭제 -->
<div class="mb-3">
<label class="form-label">제목</label>
<input type="text" class="form-control" name="title">
</div>
<div class="mb-3">
<label class="form-label">내용</label>
<textarea class="form-control" rows="3" name="content"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<a href="/articles/{{article.id}}">Back</a> <!-- 2.링크 수정 -->
</form>
{{>layouts/footer}}
4. 중간 점검해 봅시다. 서버를 재시작하고 localhost:8080/articles(목록 페이지) 페이지에 접속하면 데이터가 아무것도 없습니다. New Article을 클릭해 입력 페이지로 가서 제목은 홍길동, 내용은 1111을 입력하고 [Submit] 버튼을 클릭합니다.
5. id가 1번인 데이터의 상세 페이지가 뜨면서 입력한 내용이 보입니다. 그 아래 [Edit] 버튼을 클릭하면 URL이 바뀌면서 수정 페이지가 뜹니다. 그런데 빈 페이지가 나옵니다. 제목에 홍길동, 내용에 1111이 나와야하는데 보이지 않습니다. 아직 데이터를 보여 주지 않았기 때문입니다.
6. 수정 페이지에 내용이 보일 수 있도록 edit.mustahce에 코드를 추가하겠습니다. 글의 제목은 <input> 태그의 value="{{article.title}}" 속성을 추가해 가져옵니다. 글의 내용은 <textarea> 태그의 콘텐트 영역에 {{article.content}}를 추가해 가져옵니다.
<input type="text" class="form-control" name="title" value="{{article.title}}">
<textarea class="form-control" rows="3" name="content">{{article.content}}</textarea>
<input> 태그로 생성한 입력 요소의 초깃값은 value 속성으로 정의하지만. <textarea> 태그로 생성한 여러 줄의 입력 요소는 콘텐트 영역에 초깃값을 정의합니다.
7. 코드를 보면 세 군데에 똑같이 article.xxx라는 표현을 썼습니다. 이렇게 반복되는 게 싫다면 범위를 지정할 수 있습니다.
(1) <form>...</form> 태그를 감싸는 형태로 위에는 {{#article}}, 아래는 {{/article}}을 추가해서 article의 사용 범위를 지정합니다.
(2) {{title}}, {{content}}, {{id}}로 수정합니다.
{{>layouts/header}}
{{#articles}}
<form class="container" action="" method="post"> <!-- 1.action 속성 값 삭제 -->
<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> <!-- 2.링크 수정 -->
</form>
{{/articles}}
{{>layouts/footer}}
8. 서버를 재시작하고 localhost:8080/articles에 접속한 후 New Article 링크를 클릭해 입력 페이지로 갑니다. 제목은 홍길동, 내용은 1111을 입력한 후 [Submit] 버튼을 클릭합니다. URL이 localhost:8080/articles/1로 바뀌면서 상세 페이지로 들어갑니다. 이 상태에서 [Edit] 버튼을 클릭합니다. 원하던 제목과 내용이 잘 출력되고 URL도 localhost:8080/1/edit로 나왔습니다.
7.3 수정 데이터를 DB에 갱신하기
데이터 수정 2단계는 데이터를 수정해 DB에 반영 후 결과를 볼 수 있게 상세 페이지로 리다이렉트하는 것입니다. 이 과정은 다음과 같이 이루어집니다.
클라이언트와 서버 간 흐름을 크게 4가지 기술로 나누어 보면 다음과 같습니다.
- MVC(Model-View-Controller) : 서버 역할을 분담해 처리하는 기법
- JPA(Java Persisitence API) : 서버와 DB 간 소통에 관여하는 기술
- SQL(Structured Query Language) : DB 데이터를 관리하는 언어
- HTTP(HyperText Transfer Protocol) : 데이터를 주고 받기 위한 통신 규약
이 중에서 HTTP는 조금 생소할 수 있습니다. 그러나 앞서 다룬 MVC, JPA, SQL이 유기적으로 동작하는 것은 사실 HTTP의 요청과 응답으로 시작되고 끝납니다. HTTP가 무엇이고 데이터를 수정할 때 왜 필요한지 알아봅시다.
7.3.1 HTTP 메서드
클라리언트와 서버 간에 데이터를 전송할 때는 다양한 통신 규약, 즉 프로토콜을 따릅니다. 프로토콜(protocol)은 컴퓨터 간에 원활하게 통신하기 위해 사용하는 전 세계 표준입니다. 기기 간에 각종 신호 처리 방법, 오류 처리, 암호, 인증 방식 등을 규정하고 있어 이를 따라야만 오류나 지연 없이 원활하게 통신할 수 있습니다.
프로토콜의 종류는 다양합니다. 파일 전송을 위한 FTP(File Transfer Protocol), 이메일 전송을 위한 SMTP(Simple Mail Transfer Protocol) 등 기기와 목적에 따라 구분해 사용합니다.
HTTP(HyperText Transfer Protocol)는 그중에서도 웹 서비스에 사용하는 프로토콜입니다. HTTP는 클라이언트의 다양한 요청을, 메서드를 통해 서버로 보내는 역할을 합니다. HTTP의 대표적인 메서드로는 POST, GET, PATCH(PUT), DELETE가 있습니다.
- POST : 데이터 생성 요청
- GET : 데이터 조회 요청
- PATCH(PUT) : 데이터 수정 요청
- DELETE : 데이터 삭제 요청
데이터의 생성, 조회, 수정, 삭제는 데이터 관리에서 가장 기본이 되는 동작입니다. 이를 간단히 CRUD(Create Reade Update Delete)라고도 합니다. 이러한 CRUD는 SQL문으로 적용할 수 있는데, 이 개념이 HTTP의 메서드에서도 그대로 적용됩니다.
데이터 관리 | SQL | HTTP |
데이터 생성(Create) | INSERT | POST |
데이터 조회(Read) | SELECT | GET |
데이터 수정(Update) | UPDATE | PATCH(PUT) |
데이터 삭제(Delete) | DELETE | DELETE |
그러면 HTTP 메서드로 데이터 수정을 요청하고 실제 DB에 반영하는 과정을 실습해 보겠습니다.
앞에서 구현한 수정 페이지에 다시 접속해 봅시다. 서버를 재시작하고 localhost:8080/articles로 접속하면 빈 목록 페이지가 나옵니다. New Article을 클릭해 제목은 가가가가, 내용은 1111을 입력하고 [Submit] 버튼을 클릭합니다.
1번 id의 상세 페이지가 나옵니다. [Edit] 버튼을 클릭해 수정 페이지에 들어갑니다. 앞에서 여기까지 구현했습니다. 이 상태에서 다음과 같이 제목과 내용을 수정한 후 [Submit] 버튼을 클릭해 볼까요? 에러 페이지가 나옵니다.
데이터를 수정하면 에러 페이지가 아니라 수정된 제목과 내용이 반영된 페이지가 나오도록 구현해 보겠습니다.
7.3.2 더미 데이터 설정하기
페이지를 구현하기 전에 한 가지 작업을 하겠습니다. 더미(dummy) 데이터를 자동 생성할 수 있게 하겠습니다.
1. src > main > resources 디렉터리에서 마우스 오른쪽 버튼을 누르고 New -> File을 선택한 후 파일명을 data.sql로 입력합니다.
2. 새 편집기가 열리면 SQL 문으로 데이터 3개를 넣겠습니다. 데이터를 삽입할 때 사용하는 SQL 문은 INSERT 문 이므로 다음과 같이 작성합니다.
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');
3. 서버를 재시작하면 오류가 납니다. 스프링 부트 2.5 버전부터 data.sql을 사용한 데이터 초기화를 권장하지 않기 때문에 추가 설정이 필요합니다. src > main > resources 디렉터리에 있는 application.properties 파일을 열고 spring.jpa.defer-datasource-initialization=true 옵션을 추가합니다.
spring.jpa.defer-datasource-initialization=true
4. 서버를 실행하고 localhost:8080/articles에 접속하면 데이터 3개가 추가된 것을 확인할 수 있습니다.
7.3.3 <수정 페이지> 변경하기
1. 수정 페이지의 코드는 edit.mustache 파일에 있습니다. 파일을 열면 <form> 태그가 있습니다. 여기서 눈여겨볼 것은 action과 method 속성입니다. action 속성은 폼 데이터를 어디로 보낼지 URL을 지정하고, method 속성은 어떻게 보낼지 방식을 지정합니다. 여기서는 action 속성 값으로 수정한 폼 데이터를 "/articles/update"로 보내고, method 속성 값은 "post" 그대로 두겠습니다.
<form class="container" action="/articles/update" method="post">
앞에서 HTTP 메서드의 종류와 역할을 배웠습니다. HTTP 메서드를 활용하면 데이터를 조회할지(GET), 새로 만들지(POST), 수정할지(PATCH), 삭제할지(DELETE) 등의 요청을 서버에 전송할 수 있다고 했습니다. 그런데 이번 실습에서는 데이터 수정 요청을 보내야 하는데도 PATCH가 아닌 POST를 사용했습니다. 왜 그럴까요?
그 이유는 <form> 태그가 옛날에 만들어진 규격이라 PATCH 메서드를 지원하지 않기 때문입니다. <form> 태그는 GET과 POST 메서드만 지원합니다. PATCH 메서드를 지정할 수 있는 다른 방법이 있긴 하지만 ,여기서는 POST 그대로 둔 채 데이터를 수정하겠습니다.
2. 수정 폼에서 서버로 보낼 데이터가 하나 더 있습니다. 바로 id입니다. id가 몇 번인 article을 수정하는지 알려 줘야 하므로 <input> 태그를만들어 value="{{id}}" 속성을 추가합니다. 이때 id는 화면에 표시할 필요가 없으므로 type="hidden" 속성을 추가해 보이지 않게 숨깁니다.
<form class="container" action="/articles/update" method="post">
<input name="id", type="hidden" value="{{id}}">
여기까지 하면 수정 폼으로 제목(title), 내용(content)과 히든 속성인 아이디(id)를 서버에 전송할 수 있게 됩니다.
7.3.4 수정 데이터 받아 오기
다음으로 수정 데이터를 받는 컨트롤러를 만들어 보겠습니다.
- update() 메서드 기본 틀 만들기
ArticleController.java 파일을 열고 edit() 메서드 아래에 데이터 수정 요청을 받는 메서드를 작성합니다.
1. 메서드의 이름은 update()로 하고 기본 틀을 작성합니다.
2. URL 요청을 접수합니다. 데이터 수정 요청을 처리하는 메서드이므로 @PatchMapping()을 사용해야 하지만, 여기서는 post 방식으로 요청을 받았기 때문에 @PostMapping()을 사용합니다. 괄호 안에는 수정 폼의 action 속성에서 정의한 "/articles/update"를 작성합니다.
@PostMapping("/articles/update") //2.URL 요청 접수
public String update(){ //1.메서드 생성
return "";
}
- 수정 데이터를 DTO에 담기
1. update() 메서드는 클라이언트의 데이터 수정 요청을 받아 수행합니다. 수정 폼에서 전송한 데이터는 DTO로 받는다고 배웠습니다. DTO는 메서드의 매개변수로 받아옵니다. 따라서 다음과 같이 매개변수를 추가합니다.
@PostMapping("/articles/update")
public String update(ArticleForm form){ //매개 변수로 DTO 받아오기
return "";
}
2. 여기서 고려할 점이 있습니다. 수정 폼에 <input> 태그로 id를 추가했으므로 DTO를 정의하는 ArticleForm에도 id를 추가해야 합니다. 탐색기에서 dto > ArticleForm을 찾아 엽니다.
(1) 파일이 열리면 id 필드를 추가합니다.
(2) 그 아래 toEntity() 메서드를 보면, 그 전에는 id 필드가 없었기 때문에 null 값으로 생성자를 호출했습니다. 이제 id 필드를 추가했기 때문에 생성자에도 id를 작성해 줍니다.
public class ArticleForm {
private Long id; //1.id 필드 추가
private String title; //제목을 받을 필드
private String content; //내용을 받을 필드
public Article toEntity() {
return new Article(id, title, content); //2.null->id로 수정
}
}
3. 다시 컨트롤러로 돌아와 수정 데이터를 잘 받았는지 로그를 찍어 확인하겠습니다.
@PostMapping("/articles/update")
public String update(ArticleForm form){ //매개 변수로 DTO 받아오기
log.info(form.toString());;
return "";
}
4. 서버를 재시작 하고 localhost:8080/articles/1 페이지로 접속합니다. id가 1번인 글의 상세 페이지가 뜹니다. [Edit] 버튼을 클릭해 수정 페이지로 들어가서 다음과 같이 제목과 내용을 변경한 후 [Submit] 버튼을 클릭해 봅시다. 인텔리제이의 실행창을 보면 컨트롤러에서 수정된 데이터를 받은 것을 확인할 수 있습니다.
7.3.5 DB에 저장하고 결과 페이지로 리다이렉트하기
데이터를 DTO에 담았다면 최종적으로 DB에 저장해야 합니다. 이를 위해 다음 3단계를 거칩니다.
1. DTO를 엔티티로 변환하기
2. 엔티티를 DB에 저장하기
3. 수정 결과 페이지로 리다이렉트 하기
public String update(ArticleForm form){ //매개 변수로 DTO 받아오기
log.info(form.toString());;
//1. DTO를 엔티티로 변환하기
//2. 엔티티를 DB에 저장하기
//3. 수정 결과 페이지로 리다이렉트 하기
return "";
}
- DTO를 엔티티로 변환하기
먼저 DTO를 엔티티로 변환해 봅시다.
1. ArticleForm 클래스에서 이미 DTO를 엔티티로 변환하는 toEntity() 메서드를 만들었습니다. 따라서 form.toEntity() 메서드를 호출해 그 반환값을 Article 타입의 articleEntiy라는 이름으로 받습니다.
2. DTO가 엔티티로 잘 변환됐는지 확인하는 로그도 찍어 봅니다.
//1. DTO를 엔티티로 변환하기
Article articleEntity = form.toEntity(); //1.DTO(form)을 엔티티(articleEntity)로 변환하기
log.info(articleEntity.toString()); //2.엔티티로 잘 변환됐는지 로그 찍기
- 엔티티를 DB에 저장하기
다음으로 엔티티를 DB에 저장해야 합니다. 이 과정은 2단계로 나누어 진행하겠습니다.
1. 데이터를 새로 생성하는게 아니라 수정하려고 합니다. 기존 데이터를 바꾼다는 말이죠. 따라서 DB에서 기존 데이터를 가져와야 합니다. 이때는 리파지터리를 이용해 articleRepository.findById() 메서드를 호출합니다.
(1) findById() 메서드는 리파지터리가 자동으로 제공하는 메서드로, 괄호 안에는 찾는 id값을 작성합니다. 여기서는 앞에서 가져온 articleEntity에 getId() 메서드를 호출 해 id 값을 집어넣습니다. 즉, id가 1번인 경우 findById(1), 2번인 경우 findById(2)가 될 수 있도록 findById(articleEntity.getId())로 작성합니다.
(2) findById(articleEntity.getId()) 메서드를 호출해 반환받은 데이터를 Article 타입의 target 변수에 저장합니다.
(3) 데이터가 없다면 null을 반환합니다.
//2. 엔티티를 DB에 저장하기
//2-1. DB에서 기존 데이터 가져오기
Article target = articleRepository.findById(articleEntity.getId()).orElse(null);
2. DB에서 기존 데이터를 가져오고 나면 기존 데이터의 값을 갱신하는 코드를 작성합니다.
//2-2. 기존 데이터 값을 갱신하기
if(target != null){
articleRepository.save(articleEntity); //엔티티를 DB에 저장(갱신)
}
코드의 if() 문을 볼까요? target이 null이 아니면, 즉 기존 데이터가 있다면 articleRepository의 save() 메서드를 호출해 articleEntity에 저장된 내용을 DB로 갱신합니다.
3. 게시글을 수정하면 DB에 반영되는지 확인해 보겠습니다. 서버를 재시작하고 localhost:8080/articles 페이지에 접속합니다. 가가가가를 클릭해 상세 페이지로 이동한 후 [Edit] 버튼을 클릭해 수정 페이지로 들어갑니다. 다음과 같이 제목을 수정한 후 [Submit] 버튼을 클릭합니다.
4. 수정 데이터가 DB에 반영됐는지 확인하기 위해 http://localhost:8080/h2-console로 접속합니다. JDBC URL을 입력해야 하므로 인텔리제이 실행창에서 검색한 후 결과를 복사해 붙여 넣고 Connect 버튼을 클릭합니다.
5. ARTICLE 테이블을 선택하고 [Run]을 클릭하면 1번 id의 제목과 내용이 바뀐 것을 확인할 수 있습니다.
- 결과 페이지로 리다이렉트하기
1. localhost:8080/articles 페이지에 다시 접속합니다. 이번에는 나나나나를 클릭해 상세 페이지로 이동한 후 [Edit] 버튼을 클릭해 수정 페이지로 들어 갑니다. 2번 id의 제목과 내용을 다음과 같이 수정한 후 [Submit] 버튼을 클릭해 볼까요? 결과 화면에 에러 페이지가 뜹니다.
데이터를 수정하면 수정된 내용이 반영된 상세 페이지로 이동할 수 있도록 리다이렉트해 주겠습니다.
2. 컨트롤러 마지막 return 값으로 해당 id의 상세 페이지로 이동할 수 있는 URL을 써 줍니다. URL의 id 부분은 엔티티에 따라 매번 바뀌어야 하므로 articleEntity의 getId() 메서드를 호출해 얻고 앞의 URL과 + 연산자로 연결합니다.
//3. 수정 결과 페이지로 리다이렉트 하기
return "redirect:/articles/" + articleEntity.getId();
3. 서버를 재시작하고 localhost:8080/articles 페이지로 갑니다. 더미 데이터 3개가 보이면 가가가가를 클릭해 상세 페이지로 이동한 후 [Edit] 버튼을 클릭합니다. 다음과 같이 제목과 내용을 수정한 후 [Submit] 버튼을 클릭해 봅시다. 결과를 보면 리다이렉트 페이지인 /articles/1 페이지로 이동한 것을 확인할 수 있습니다. 제목과 내용도 수정한 대로 잘바뀌었습니다.
7.3.6 SQL 문으로 직접 DB 갱신하기
앞서 실습한 데이터 수정 과정에서 실제 DB에서는 어떤 일이 일어났을까요? 이번에는 SQL 문으로 직접 데이터를 수정해 봅시다.
1. localhost:8080/h2-console 페이지로 접속해 인텔리제이의 실행창에서 검색한 JDBC UR을 넣고 [Connect] 버튼을 클릭합니다.
2. ARTICLES에서 [Run]을 클릭하면 현재 저장된 데이터를 확인할 수 있습니다. 이 상태에서 SQL 문을 사용해 바로 데이터를 수정해 보겠습니다.
3. 데이터를 수정할 때 사용하는 SQL 문은 UPDATE 문입니다. 형식은 다음과 같습니다.
형식) UPDATE 테이블명 SET 속성명=변경할_값 WHERE 조건;
article 테이블의 모든 제목(title)을 'KKKK'로, 모든 내용(content)을 'AAAA'로 변경해 보겠습니다. 입력창에 다음과 같이 작성하고 [Run]을 클릭합니다.
4. UPDATE 문을 실행한 후 결과를 확인하려면 다시 SELECT 문으로 조회해야 합니다. 다음과 같이 SELECT 문을 작성한 후 [Run]을 클릭합니다.
SELECT * FROM article;
5. 결과를 보면 모든 제목과 내용이 수정한 값으로 바뀐 것을 확인할 수 있습니다.
6. 이번에는 모든 제목과 내용을 수정하지 않고 특정 글만 바꾸고 싶습니다. 어떻게 해야 할까요? UPDATE 문에 WHERE 조건절을 추가하면 됩니다. id가 2번인 글의 제목을 가나다라로, 내용은 1111로 바꾸고 싶다면 다음과 같이 작성하면 됩니다.
UPDATE article SET title = '가나다라', content = '1111' WHERE id = 2;
7. [Run]을 클릭해 UPDATE 문을 실행한 후 SELECT 문으로 조회해 봅니다.
SELECT * FROM article;
8. 결과를 보면 2번 데이터의 값이 바뀐 것을 확인할 수 있습니다.
7.3.7 최종 정리
지금까지 게시글을 수정하고 DB에 반영하는 예제를 실습해 봤습니다. 수정 폼에 작성된 데이터를 서버로 보내는 과정인데, 아쉽게도 <form> 태그는 PATCH 메서드를 제공하지 않아 POST 메서드를 임시로 사용했습니다.
수정 데이터는 ArticleController의 update() 메서드가 ArticleForm이라는 DTO로 받은 다음 엔티티로 변환했습니다. 그리고 이 엔티티를 가지고 DB에서 해당 데이터를 찾아 수정 내용으로 갱신한 후, 마지막으로 바뀐 페이지로 리다이렉트하는 것까지 연습해 봤습니다.
'스프링부트' 카테고리의 다른 글
9장 CRUD와 SQL 쿼리 종합 (2) | 2025.01.23 |
---|---|
8장 게시글 삭제하기: Delete (0) | 2025.01.23 |
6장 게시판 내 페이지 이동하기 (2) | 2025.01.20 |
5장 게시글 읽기: Read (1) | 2025.01.20 |
4장 롬복과 리팩터링 (2) | 2025.01.15 |