2차 공부/TIL

24.06.19 할 일 목록 만들기 코드 리팩토링

공대탈출 2024. 6. 19. 14:53
<script>
        let todoArr = ['밥 먹고 가볍게 산책하기', '자바스크립트 책 읽기'];
        function completeTodoHandler(id) {
            let targetTodo = document.getElementById(id);
            targetTodo.style.textDecoration = 'line-through';
        }
        function deleteTodoHandler(id) {
            let targetTodo = document.getElementById(id);
            let parent = targetTodo.parentElement;
            parent.removeChild(targetTodo);
        }
        function addTodoHandler() {
            let todo = document.getElementById('todoInput').value;
            todoArr.push(todo);
            document.getElementById('todoList').innerHTML += `<p id='${todoArr.length}'>
                                <span>${todo}</span>
                                <button class="completeBtn" onClick='completeTodoHandler(${todoArr.length})'>완료</button>
                                <button class="deleteBtn" onClick='deleteTodoHandler(${todoArr.length})'>삭제</button>
                            </p>`;
        }
</script>

해당 부분에서 todoArr.length로 만들어지는 id를 리팩토링 해보고자한다.

코드의 변경이유는 다음과 같다.

현재는 페이지에서 todoArr하나의 배열만 가지고 id를 관리하지만, 만약 두가지 이상의 배열을 가지고 각기 다른 리스트를 만들어 보여주어야 할 때에는 태그의 단순히 배열의 길이를 id로 가지는 태그가 겹칠 것이므로, id값을 생성하는 방식을 바꾸어야했다.

 

튜터님의 crypto.randomUUID 메서드 사용추천

 

슬랙을 통해 튜터님께 질문드린 결과 crypto.randomUUID를 사용해보라고 추천해주셨다.

따라서 해당 기능의 공식문서를 찾아 사용방법을 알아내, 리팩토링을 진행하였다.

변수에 self.crypto.randomUUID()로 만들어낸 값을 담아 해당 변수를 사용하면 되는 것 이었다.

function addTodoHandler() {
            let todoInput = document.getElementById('todoInput');
            let todo = todoInput.value;
            todoArr.push(todo);
            let id = self.crypto.randomUUID();
            document.getElementById('todoList').innerHTML += `
                <p id='${id}'>
                    <span>${todo}</span>
                    <button class="completeBtn" onClick='completeTodoHandler('${id}')'>완료</button>
                    <button class="deleteBtn" onClick='deleteTodoHandler('${id}')'>삭제</button>
                </p>`;
            todoInput.value = '';
        }
    </script>

id라는 변수에 만들어낸 UUID값을 담고, 해당 id변수를 id값으로 넘기고, 함수에도 인자로 넘겨주었다.

오류발생

하지만 오류가 발생하였다.

Uncaught SyntaxError: Unexpected end of input에러는 괄호를 닫지 않거나 따옴표를 제대로 닫지 않아 오류가 발생하는 것 이었다.

 

문제는 이곳이었다.

onClick='completeTodoHandler('${id}')'
onClick='deleteTodoHandler('${id}')'

템플릿 리터럴(``백틱)안에 들어가있는 onClick의 두 함수가 함수 자체와 인자 둘 다 작은 따옴표로 감싸져있는데,

자바스크립트가 코드를 읽어들일 때 위에서 아래로, 왼쪽에서 오른쪽으로 코드를 읽어 따옴표의 사용이 적절하지 못했던 것이다.

deleteTodoHandler를 기준으로 살펴보자면,

onClick= 'deleteTodoHandler(' 이렇게 올바르지 않은 함수가 들어가 있는 것으로 해석할 것이고

${id}         ')'            이렇게 두가지의 의미없는 코드를 읽어들일 것이다.

따라서 큰 따옴표와 작은따옴표 둘 다 사용하여 따옴표의 시작과 맺음을 구분해주어야 한다.

function addTodoHandler() {
            let todoInput = document.getElementById('todoInput');
            let todo = todoInput.value;
            todoArr.push(todo);
            let id = self.crypto.randomUUID();
            document.getElementById('todoList').innerHTML += `
                <p id='${id}'>
                    <span>${todo}</span>
                    <button class="completeBtn" onClick='completeTodoHandler("${id}")'>완료</button>
                    <button class="deleteBtn" onClick='deleteTodoHandler("${id}")'>삭제</button>
                </p>`;
            todoInput.value = '';
        }

이렇게 ${id}를 큰 따옴표로 감싸주어 자바스크립트가 onClick에 전달된 함수를 'deleteTodoHandler("${id}")'로 완성되어 받을 수 있게 해야한다.


추가 및 완료, 삭제 기능도 잘 작동하고 id값도 UUID값이 잘 들어가있는 것을 볼 수 있다.


사실 대부분의 따옴표를 사용하기 편한 작은 따옴표만 사용해왔었다. 하지만 템플릿 리터럴 속에서의 사용이나 혼동오류가 있을것으로 예상되는 곳에서는 따옴표를 잘 구분지어주어야 한다는 것을 알게 되었다.