우당탕탕

[무작정 따라하기 1탄] Spring Boot로 나만의 TODO 리스트 만들기 4편 - 수정 삭제 기능 구현 본문

여러내용들/무작정 따라하기

[무작정 따라하기 1탄] Spring Boot로 나만의 TODO 리스트 만들기 4편 - 수정 삭제 기능 구현

모찌모찝 2024. 9. 22. 13:14
무작정 따라 하기 1탄 나만의 TODO리스트 만들기 4편👩‍💻

안녕하세요!

이전 3편에서는 CRUD 기능 중 Create, Read를 구현을 진행하였습니다. 이번 편에서는 CRUD 기능중 Update, Delete를 구현해 보겠습니다.
이전에 작성했던 코드에서 일부 수정을 진행하면서 작업해 보겠습니다.

4편 예시 완성본

TODO 리스트 만들기 4편

이번 편에서는 JavaScriptController 코드 수정만으로 진행됩니다.

1. JavaScript 코드 수정하기 

완성본 사진에서 나온 것처럼 왼쪽에 TODO 리스트의 완료, 미완료 여부를 체크하는 체크박스와 오른쪽에는 TODO리스트를 삭제하는 버튼이 존재합니다.
서버에서 TODO 리스트를 불러올 때 해당 화면이 업데이트되도록 변경해 줍시다.

document.addEventListener("DOMContentLoaded", function() {
    fetchTodos(); // 페이지가 로드될 때 TODO 목록을 가져옵니다.

    document.getElementById("todoForm").addEventListener("submit", function(event) {
        event.preventDefault(); // 기본 폼 제출 동작을 막습니다.
        addTodo(); // 새로운 할 일을 추가합니다.
    });
});

function fetchTodos() {
    fetch('/todos') // 서버에서 TODO 목록을 가져옵니다.
        .then(response => response.json()) // 서버 응답을 JSON 형식으로 변환합니다.
        .then(data => {
            const todoList = document.getElementById('todoList');
            todoList.innerHTML = ''; // 목록을 초기화합니다.
            data.forEach(todo => {
                const li = document.createElement('li'); // 새로운 리스트 아이템을 만듭니다.
                li.className = "list-group-item d-flex justify-content-between align-items-center"; // 부트스트랩 스타일을 적용

                // 체크박스
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkbox.checked = todo.completed; // 완료 상태에 따라 체크 여부 설정
                checkbox.onclick = () => toggleTodoCompletion(todo); // 체크박스를 클릭할 때 상태 변경

                // 할 일 텍스트
                const taskText = document.createElement('span');
                taskText.textContent = todo.task + (todo.completed ? ' (완료)' : ' (미완료)'); // 할 일을 표시

                // 삭제 버튼
                const deleteButton = document.createElement('button');
                deleteButton.textContent = '삭제';
                deleteButton.className = "btn btn-danger btn-sm ml-2"; // 오른쪽 여백 추가
                deleteButton.onclick = () => deleteTodo(todo.id); // 삭제 함수 호출

                li.appendChild(checkbox); // 체크박스를 리스트 아이템에 추가
                li.appendChild(taskText); // 할 일 텍스트를 리스트 아이템에 추가
                li.appendChild(deleteButton); // 삭제 버튼을 리스트 아이템에 추가
                todoList.appendChild(li); // 목록에 추가합니다.
            });
        });
}

function addTodo() {
    const taskInput = document.getElementById("task"); // 입력 필드를 가져옵니다.
    const task = taskInput.value; // 입력된 값을 가져옵니다.

    fetch('/add', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded', // 데이터 형식 설정
        },
        body: new URLSearchParams({ task }) // 입력된 값을 URL 형식으로 변환합니다.
    })
    .then(response => response.json()) // 서버 응답을 JSON 형식으로 변환합니다.
    .then(todo => {
        fetchTodos(); // TODO 목록을 새로 고칩니다.
        taskInput.value = ''; // 입력 필드를 초기화합니다.
    });
}

// 할 일의 완료 상태를 토글하는 함수
function toggleTodoCompletion(todo) {
    fetch(`/update/${todo.id}`, {
        method: 'PUT',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: new URLSearchParams({ completed: !todo.completed }) // 현재 상태의 반대로 전송
    })
    .then(() => {
        fetchTodos(); // 수정 후 TODO 목록을 새로 고칩니다.
    });
}

function deleteTodo(id) {
    if (confirm("정말로 삭제하시겠습니까?")) { // 삭제 확인 메시지
        fetch(`/delete/${id}`, {
            method: 'DELETE'
        })
        .then(() => {
            fetchTodos(); // 삭제 후 TODO 목록을 새로 고칩니다.
        });
    }
}

변경된 사항으로는 deleteTodo() 함수와 toogleTodoCompletion() 코드가 추가되었으며, fetchTodos()에 수정 체크박스 로직과 삭제버튼 로직이 추가되었습니다.

  1. toggleTodoCompletion(todo):
    • 사용자가 체크박스를 클릭하면 호출되는 함수입니다.
    • 체크박스의 상태에 따라 할 일의 완료 상태를 업데이트합니다. 완료 상태를 반전시켜 서버에 PUT 요청을 보냅니다. ( TODO 리스트 프로젝트뿐 아닌 게시판 프로젝트를 진행하실 때도 비슷하게 적용시켜 볼 수 있습니다 )
  2. deleteTodo(id):
    • 삭제 버튼을 클릭하면 호출되는 함수입니다.
    • 삭제 확인 메시지를 띄운 후, 사용자가 확인하면 서버에 DELETE 요청을 보내 해당 항목을 삭제합니다.

2. Controller 수정하기

컨트롤러로 이동하여 이번엔 삭제 메서드와 수정 메서드를 작성해 보겠습니다.

2.1 삭제 메서드

@DeleteMapping("/delete/{id}")
public void deleteTodo(@PathVariable Long id) {
    todoRepository.deleteById(id);
}
  • @DeleteMapping("/delete/{id}"): 클라이언트가 /delete/{id} 경로로 DELETE 요청을 보낼 때 이 메서드가 호출됩니다.
  • @PathVariable Long id: URL 경로에서 ID 값을 가져옵니다.
  • todoRepository.deleteById(id);: 해당 ID의 TODO 항목을 JPA를 활용하여 데이터베이스에서 삭제합니다.

2.2 수정 메서드

@PutMapping("/update/{id}")
public Todo updateTodo(@PathVariable Long id, @RequestParam(required = false) Boolean completed) {
    Todo todo = todoRepository.findById(id).orElseThrow();
    if (completed != null) {
        todo.setCompleted(completed);
    }
    todoRepository.save(todo);
    return todo;
}
  • @PutMapping("/update/{id}"): 클라이언트가 /update/{id} 경로로 PUT 요청을 보낼 때 이 메서드가 호출됩니다. {id}는 수정할 TODO 항목의 ID입니다.
  • @PathVariable Long id: URL 경로에서 ID 값을 가져옵니다.
  • @RequestParam(required = false) Boolean completed: 클라이언트가 전송한 completed 파라미터를 받아옵니다. 
  • todoRepository.findById(id): ID에 해당하는 TODO 항목을 데이터베이스에서 찾습니다. 항목이 없으면 예외를 발생시킵니다.
  • if (completed != null): completed 파라미터가 제공된 경우, 해당 TODO 항목의 완료 상태를 업데이트합니다.
  • 수정된 TODO 항목을 데이터베이스에 저장합니다.

코드를 작성한 후 서버를 실행시켜 보면 TODO리스트가 완성되어 있는 것을 확인할 수 있습니다.
완성된 코드의 프로젝트 구조도는 아래와 같습니다

todo-app/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           └── todo/
│   │   │               ├── Todo.java             // 할 일 모델 클래스
│   │   │               ├── TodoController.java   // REST API 컨트롤러
│   │   │               └── TodoRepository.java    // 데이터베이스 인터페이스
│   │   └── resources/
│   │       ├── static/
│   │       │   └── style.css                     // 사용자 정의 스타일
│   │       │   └── script.js                     // JavaScript 파일
│   │       │   └── index.html                     // 기본 index.html
│   │       ├── templates/
│   │       │   └── index.html                    // HTML 템플릿 파일
│   │       └── application.properties             // 애플리케이션 설정 파일
│   └── test/                                      // 테스트 코드 (옵션)
└── README.md                                       // 프로젝트 설명 파일

 

이로써 "1탄: TODO 리스트 만들기" 프로젝트가 완료되었습니다!
이번 과정에서는 기본적인 CRUD 기능을 갖춘 TODO 리스트 애플리케이션을 구현해 보았습니다.
사용자가 할 일을 추가하고, 완료 상태를 체크하며, 삭제할 수 있는 기능을 통해 실제로 유용한 애플리케이션을 만들어 보았습니다.

이 프로젝트를 통해 간단한 웹 애플리케이션 개발을 진행해 보고, Spring Boot와 JavaScript를 활용한 프런트엔드와 백엔드의 연동 방법을 익힐 수 있었습니다. 앞으로 더 많은 기능을 추가하거나, 디자인을 더 이쁘게 개선하는 등 여러 시도로 발전시켜 보시는 것도 좋을 것 같습니다.

질문이나 궁금한 점이 있다면 언제든지 문의해 주세요! 감사합니다! 😊

Comments