스프링 부트와 AWS로 혼자 구현하는 웹 서비스
: 인텔리제이, JPA, JUnit 테스트, 그레이들, 소셜 로그인, AWS 인프라로 무중단 배포까지
이동욱 저
Table of Content
게시글 수정(UPDATE) 화면 구성하기
posts-update.mustache
{{>layout/header}}
<h1>게시글 수정</h1>
<div class="col-md-12">
<div class="col-md-4">
<form>
<div class="form-group">
<label for="title">글 번호</label>
<input type="text" class="form-control" id="id" value="{{post.id}}" readonly>
</div>
<div class="form-group">
<label for="title">제목</label>
<input type="text" class="form-control" id="title" value="{{post.title}}">
</div>
<div class="form-group">
<label for="author"> 작성자 </label>
<input type="text" class="form-control" id="author" value="{{post.author}}" readonly>
</div>
<div class="form-group">
<label for="content"> 내용 </label>
<textarea class="form-control" id="content">{{post.content}}</textarea>
</div>
</form>
<a href="/" role="button" class="btn btn-secondary">취소</a>
<button type="button" class="btn btn-primary" id="btn-update">수정 완료</button>
<button type="button" class="btn btn-danger" id="btn-delete">삭제</button>
</div>
</div>
{{>layout/footer}}
HTML
복사
{{post.id}}
•
머스테치는 객체의 필드 접근 시 점(도트 구분자)로 구분
•
Post 클래스의 id 필드에 대한 접근은 post.id로 접근
readonly
•
input 태그에 읽기만 가능한 속성
•
id, author 처럼 수정할 수 없는 값을 받도록 하기 위함
◦
경우에 따라 hidden field 속성으로 어떤 임시, 고정값들은 노출하지 않도록 하기도 할 수 있음
index.js
var main = {
init : function () {
var _this = this;
...
$('#btn-update').on('click', function () {
_this.update();
});
},
save : function () {
var data = {
...
});
},
update : function () {
var data = {
title: $('#title').val(),
content: $('#content').val()
};
var id = $('#id').val();
$.ajax({
type: 'PUT',
url: '/api/v1/posts/'+id,
dataType: 'json',
contentType:'application/json; charset=utf-8',
data: JSON.stringify(data)
}).done(function() {
alert('글이 수정되었습니다.');
window.location.href = '/';
}).fail(function (error) {
alert(JSON.stringify(error));
});
}
};
main.init();
JavaScript
복사
$('#btn-update').on('click', function () { … }
•
btn-update id(#, 클래스는 .)를 가진 요소를 클릭(온클릭 이벤트) 했을때 update 함수를 실행하도록 설정
type : ‘PUT’
•
HTTP 메소드 중 PUT메소드로 REST규약에 따라 설정한것 (API 컨트롤러도 @PutMapping으로 선언되어 있음)
◦
생성(Create) - POST
◦
조회(Read) - GET
◦
수정(Update) - PUT
◦
삭제(Delete) - DELETE
IndexController.java
package com.citefred.ldwspring.web;
import com.citefred.ldwspring.service.PostsService;
import com.citefred.ldwspring.web.dto.PostsResponseDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
@RequiredArgsConstructor
@Controller
public class IndexController {
private final PostsService postsService;
...
@PutMapping("/posts/update/{id}")
public String postsUpdate(@PathVariable Long id,
Model model){
PostsResponseDto dto = postsService.findById(id);
model.addAttribute("posts", dto);
return "posts-update";
}
}
Java
복사
@RequestParam과 @PathVariable
•
Controller 단에서 위 두 어노테이션은 uri를 통해 전달된 값을 파라미터로 받아오는 역할
◦
@RequestParam는 Query String으로부터 값을 얻는다. key=value 형식, 여러개 사용 가능
▪
http://localhost:8000/board?page=1&listSize=10
◦
@PathVariable은 URL 자체에서 일부(단일) 값을 얻는 데 사용, 특정 게시글을 지정하는 등 목적
▪
http://localhost:8000/board/1
•
필요에 따라서는 두 방법을 혼합해서 사용
글 수정 뷰 페이지+API 작동 테스트
•
where id = 1 을 통해서 1번 글의 게시글 수정 폼이 조회 된 것을 확인 할 수 있다.
•
수정 폼에 수정된 값들을 입력하고 버튼을 누르면
•
js에 작성된 버튼의 온클릭 이벤트에서 update요청인 PUT 메소드 방식의 API요청이 진행되고
•
DB의 게시글이 수정되는 것을 확인 할 수 있다.
게시글 삭제(DELETE) 화면 구성하기
posts-update.mustache
{{>layout/header}}
<h1>게시글 수정</h1>
<div class="col-md-12">
<div class="col-md-4">
<form>
<div class="form-group">
<label for="title">글 번호</label>
<input type="text" class="form-control" id="id" value="{{post.id}}" readonly>
...
</form>
<a href="/" role="button" class="btn btn-secondary">취소</a>
<button type="button" class="btn btn-danger" id="btn-delete">삭제</button>
</div>
</div>
{{>layout/footer}}
HTML
복사
•
삭제는 게시글을 확인하는 상태로 하는 경우가 많기 때문에 수정 폼에서 삭제 버튼을 추가하여 구현했다.
index.js
var main = {
init : function () {
var _this = this;
...
$('#btn-delete').on('click', function () {
_this.delete();
});
},
save : function () {
var data = {
...
});
},
update : function () {
...
});
},
delete : function () {
var id = $('#id').val();
$.ajax({
type: 'DELETE',
url: '/api/v1/posts/'+id,
dataType: 'json',
contentType:'application/json; charset=utf-8'
}).done(function() {
alert('글이 삭제되었습니다.');
window.location.href = '/';
}).fail(function (error) {
alert(JSON.stringify(error));
});
}
};
main.init();
JavaScript
복사
•
삭제 기능의 ajax 요청 함수를 작성한다. 동일하게 버튼에 온클릭 이벤트로 DELETE 방식 요청을 API 주소로 요청한다.
PostsService.java
package com.citefred.ldwspring.service;
import com.citefred.ldwspring.domain.posts.Posts;
import com.citefred.ldwspring.domain.posts.PostsRepository;
import com.citefred.ldwspring.web.dto.PostsListResponseDto;
import com.citefred.ldwspring.web.dto.PostsResponseDto;
import com.citefred.ldwspring.web.dto.PostsSaveRequestDto;
import com.citefred.ldwspring.web.dto.PostsUpdateRequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
@RequiredArgsConstructor
@Service
public class PostsService {
private final PostsRepository postsRepository;
...
@Transactional
public void delete(Long id){
Posts posts = postsRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("해당 게시글이 없습니다. id=" + id));
postsRepository.delete(posts);
}
}
Java
복사
postsRepository.delete(posts);
•
JpaRepository에서 delete메소드를 지원하고 있다.
•
존재하는 게시글인지 확인 후 해당 게시글 조회 후 그 게시글을 삭제
PostsApiController.java
package com.citefred.ldwspring.web;
import com.citefred.ldwspring.service.PostsService;
import com.citefred.ldwspring.web.dto.PostsResponseDto;
import com.citefred.ldwspring.web.dto.PostsSaveRequestDto;
import com.citefred.ldwspring.web.dto.PostsUpdateRequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@RequiredArgsConstructor
@RestController
public class PostsApiController {
private final PostsService postsService;
...
@DeleteMapping("/api/v1/posts/{id}")
public Long delete(@PathVariable Long id){
postsService.delete(id);
return id;
}
}
Java
복사
@DeleteMapping("/api/v1/posts/{id}")
•
삭제 기능 API 기능 추가
글 삭제 뷰 페이지+API 작동 테스트
게시글을 삭제할 수 있도록 테스트 글 작성
2번 게시글을 대상으로 삭제 요청
2번 테스트 글이 삭제된 갱신된 글 목록
Related Posts
Search