Vue + SpringBoot + Mysql 를 이용한 Todo 구현(1) - 프로젝트 구성하기
Vue + SpringBoot + Mysql 를 이용한 Todo 구현(2) - 프로젝트 환경 설정하기
Vue + SpringBoot + Mysql 를 이용한 Todo 구현(3) - Todo API 개발하기(1)
Vue + SpringBoot + Mysql 를 이용한 Todo 구현(5) - Todo 화면 개발하기(1) - 컴포넌트 구성
Vue + SpringBoot + Mysql 를 이용한 Todo 구현(6) - Todo 화면 개발하기(2) - Vuex 적용
(끝) Vue + SpringBoot + Mysql 를 이용한 Todo 구현(7) - Todo 화면 개발하기(3) - 화면 개발
이전 글에 이어서 service와 controller를 개발하고 postman 을 통해서 확인해보도록 하겠습니다.
3. Service 개발하기
- Service 폴더를 생성 후 아래에 TodoService.class 를 생성합니다.
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class TodoService {
private final TodoRepository todoRepository;
// Todo 작성
@Transactional
public Long save(Todo todo){
todoRepository.save(todo);
return todo.getId();
}
// Todo 전체 조회
public List<Todo> findTodos(boolean orderState){
return todoRepository.findAll(orderState);
}
// Todo 단건 조회
public Todo findOne(Long todoId){
return todoRepository.findOne(todoId);
}
// Todo 완료 상태 수정
@Transactional
public void updateTodoComplted(Long id, boolean completed) {
Todo todo = todoRepository.findOne(id);
todo.setCompleted(completed);
}
// Todo 삭제(DB 업데이트)
@Transactional
public void updateTodoUseYn(Long id) {
Todo todo = todoRepository.findOne(id);
todo.setUseYn("N");
}
// Todo 전체 삭제(DB 업데이트)
@Transactional
public int updateTodoAllClear() {
return todoRepository.updateTodoAllClear();
}
}
- 기본적으로 해당 클레스에 @Transactional 어노테이션을 걸어두고, readonly=true 로 기본적으로 설정합니다.(기본적으로 읽기만 가능하게 설정하여 무분별한 insert,update,delete를 막는다)
- 영속성 컨텍스트 전략을 통해서, 단건 업데이트의 경우에는 단건 조회하여 해당 데이터를 조회 후에 해당 값을 변경하여 관리합니다.
스프링 컨테이너는 트랜잭션 범위의 영속성 컨텍스트 전략을 기본으로 사용한다.
서비스 클래스에서 @Transactional을 사용할 경우, 해당 코드 내의 메서드를 호출할 때 영속성 컨텍스트가 생긴다는 뜻이다.
영속성 컨텍스트는 트랜잭션 AOP가 트랜잭션을 시작할 때 생겨나고, 메서드가 종료되어 트랜잭션 AOP가 트랜잭션을 커밋할 경우 영속성 컨텍스트가 flush되면서 해당 내용이 반영되고, 이후 영속성 컨텍스트 역시 종료된다.
4. Controller 개발하기
- controller 폴더를 생성 후 아래에 TodoForm.class 를 생성합니다.
@Getter
@Setter
public class TodoForm {
@NotEmpty(message = "내용은 필수입니다.")
private String item;
private String date;
private boolean completed;
private String time;
}
- TodoForm 은 Request(요청)시에 전달받은 파라미터를 관리하는 클래스입니다.
- 따로 Model에 있는 파일과 구분한 이유는 추후 API 스펙이 변경될 시 해당 파일만 변경하고, Model은 그대로 사용이 가능하여 유지보수 측면에서 좋기 때문입니다.(자세한 내용은 김영한님의 강의 참고)
- 다음은, TodoController.class 를 생성합니다.
@RestController
@RequiredArgsConstructor
@Slf4j
public class TodoController {
private final TodoService todoService;
// Todo 등록
@PostMapping("/todos/save")
public String createJsonTodo(@RequestBody @Valid TodoForm form, BindingResult bindingResult){
log.info("Post : Todo Save");
return validation(form, bindingResult);
}
// Todo 목록
@GetMapping("/todos/{orderState}")
public List<Todo> list(@PathVariable("orderState") Boolean orderState){
log.info("Get : Todos List");
return todoService.findTodos(orderState);
}
// Todo 완료 상태 업데이트
@PutMapping("/todos/{id}")
public String updateTodo(
@PathVariable("id") Long id,
@RequestBody UpdateTodoRequest request
){
log.info("Put : Todo update");
todoService.updateTodoComplted(id, request.isCompleted());
Todo findTodo = todoService.findOne(id);
if(request.isCompleted() == findTodo.isCompleted()){
return "ok";
} else {
return "fail";
}
}
// Todo 삭제(DB 업데이트)
@PutMapping("/todos/delete/{id}")
public String deleteTodo(
@PathVariable("id") Long id
){
log.info("Delete : Todo Delete");
todoService.updateTodoUseYn(id);
Todo findTodo = todoService.findOne(id);
if(findTodo.getUseYn().equals("N")){
return "ok";
} else {
return "fail";
}
}
@PutMapping("/todos/clear")
public String clearAllTodo(){
log.info("Clear : Todo All Clear");
int result = todoService.updateTodoAllClear();
if(result > 0){
return "ok";
} else {
return "fail";
}
}
// 요청 파라미터 validation 체크
private String validation(@Valid @RequestBody TodoForm form, BindingResult bindingResult) {
if(bindingResult.hasErrors()){
return "todo error";
}
Todo todo = new Todo();
todo.setItem(form.getItem());
todo.setCompleted(form.isCompleted());
todo.setDate(form.getDate());
todo.setTime(form.getTime());
todo.setWriteDate(LocalDateTime.now());
todo.setUpdateDate(LocalDateTime.now());
todoService.save(todo);
return "ok";
}
@Data
static class UpdateTodoRequest{
private Long id;
@NotEmpty
private boolean completed;
}
}
- Restful API 형식으로 개발을 해보았습니다.
- PostMapping
- Insert(저장) 시 사용.
- @RequestBody를 TodoForm으로 받아 Todo에 다시 세팅하여 저장. - GetMapping : Select(조회) 시 사용
- @PathVariable를 사용하여 조회 ID를 전달받아 조회. - PutMapping : Update(수정) 시 사용
- @PathVariable를 사용하여 조회 ID를 전달받아 조회 후 수정.
5. PostMan을 통해 검증하기
- API 개발이 완료되었으니, PostMan을 통해서 검증을 해보도록 하겠습니다.
- 저장(localhost:8787/todos/save)
- 목록 조회(localhost:8787/todos/true or localhost:8787/todos/false)
- 수정(localhost:8787/todos/2)
- API 개발이 완료되었습니다. 다음 글에서는 FrontEnd(Vue) 프로젝트 개발을 해보도록 하겠습니다.
참고