HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
👻
개발 기록
/
📑
강의 정리
/
📑
To do App 만들기
📑

To do App 만들기

Created
Aug 24, 2021 04:59 AM
Type
VanillaJS기본역량강화
Mento
로토
Created By

요구사항

  • users api를 통해 사용자 목록을 그리고, 클릭하면 해당 사용자의 todo 목록을 가져옴.
  • 할 일을 추가하면 화면에 추가되고, API 호출을 통해 서버에도 추가됨.
  • TODO를 추가하고 삭제하는 동안 낙관적 업데이트를 사용함.
  • 서버와 통신하는 동안 서버와 통신 중임을 알리는 UI적 처리.

요점 정리

이벤트 위임(event delegation)

  • closest(selector)는 elem의 상위 요소 중 selector와 일치하는 가장 근접한 조상 요소를 반환함.
  • 버블링 활용.
$todo.innerHTML = ` <li data-id="${_id}" class="todo-item"> ${isCompleted ? `<s>${content}</s>` : content} <button class="remove">X</button> </li> ` $todo.addEventListener("click", (e) => { const $li = e.target.closest(".todo-item"); if ($li) { const { id } = $li.dataset; const { className } = e.target; if (className === "remove") { onRemove(id); } else { onToggle(id); } } });

낙관적 업데이트

  • api 등 서버와의 통신이 될 것이라 생각하고 통신 전에 브라우저에 요소를 추가하는 것.
  • 실제로 서버로부터 확인을 받기 전에 변경이 성공적으로 완료된 것처럼 작동함.
new TodoForm({ $target, onSubmit: async (content) => { //낙관적 업데이트///// const todo = { content, isCompleted: false, }; ////////////////////// this.setState({ ...this.state, todos: [...this.state.todos, todo], }); await request(`/${this.state.username}`, { method: "POST", //보통 api의 body 형식은 백엔드와 협의된 내용으로 진행됨. body: JSON.stringify(todo), }); await fetchTodos(); }, });

local storage getItem안전하게 사용하기

export const getItem = (key, defaultValue) => { try { const storedValue = storage.getItem(key); if (!storedValue) { return defaultValue; } const parsedValue = JSON.parse(storedValue); return parsedValue; } catch (error) { console.log(error); } };

local storage를 이용해 input value 저장하기

  • 사용자 경험을 높이기 위해 todo를 제출하기 전 새로 고침할 경우, 입력 중인 텍스트를 저장함.
  • input을 querySelector 로 선택하여 keyup 이벤트가 발생할 때마다 setItem 에 key, value값 저장. 그 후 getItem 으로 key에 해당하는 값을 가져옴.
  • storgae.js에 removeItem 함수를 만들어 제출 시 저장했던 텍스트를 지움.

URL 커스텀하기

  • history.pushState() 는 브라우저의 세션 기록 스텍에 상태를 추가함.
  • 매개변수
    • state : 새로운 세션 기록 항목에 연결할 상태 객체.
    • title : 현재는 적용되지 않는 브라우저가 많지만 미래에 쓰일 걸 염두하여 빈 문자열을 넣어놓는 것이 좋음.
    • url(optional) : 새로운 세션 기록 항목의 URL.
history.pushState(null, null, `/todos${username}`);
  • url에 특정 사용자를 나타내는 값이 있을 경우.
    • location.pathname으로 url 값을 가져옴.
    • location.search 로 쿼리스트링 값을 가져올 수도 있음.
    • 특정 path 값을 만들 땐 substring()을 사용하면 /같은 부호를 제외할 수 있음.
⚠️
url 지정 후 이동할 때 vscode live server 와 npx serve에서 동작 결과가 다른 이유 SPA 에서는 웹서버 설정으로 404 발생시 루트에 있는 index.html을 부르게 하도록 설정되어 있음. 따라서 npx serve -s를 실행하거나 vscode live server 익스텐션 세팅값을 수정하면 됨.
aws의 cloudfront + s3 로 배포를 할 경우, 추가 작업 필요
notion image

URL 커스텀하기2

  • 쿼리스트링을 불러오기 위한 script 파일을 만듦.
export const parse = (querystring) => // '?name=hyosung&position=bassist' querystring.split("&").reduce((acc, keyAndValue) => { const [key, value] = keyAndValue.split("="); if (key && value) { acc[key] = value; } return acc; }, {});
💡
항상 일정한 규칙으로 동작하는 코드를 여러 번 사용할 땐 별도의 script 파일로 동작시키기.

소소한 팁

  • <s></s> 로 삭선 처리 가능.
  • api 주소는 상단에 상수로 처리하는 것이 좋음. 추후 주소만 교체하면 되기 때문.
  • 파라미터에 값이 안들어올 경우 처리하는 기본 값을 지정할 수 있음 → (options = {})
  • api 호출 시 request에서 res.ok 체크하는 거 잊지 말기.
  • 문자열 변수를 상단에 정의하고 하단에서 사용하는 것이 오타를 방지할 수 있음.
  • 마지막 호출 시 init 함수를 만들어 하단에서 부를 함수들을 한 번에 불러주는 것이 좋음.

마치며

api로 todolist를 불러오니 재밌군! 만들면서 한 가지 아이디어가 떠올랐다.
바로 비밀편지함 서비스이다. User는 username, contents를 작성할 수 있게 하고, 관리자는 userList를 갖고 있어 username을 클릭하면 해당 콘텐츠를 볼 수 있도록 하는 것이다. 이때 관리자는 콘텐츠를 보고 해당 user에게 비밀의 메시지를 남길 수 있게 한다! User는 자신의 고민을 털어놓고 관리자로부터 메시지를 받아 상담받을 수 있다. 일종의 비밀 친구랄까... 후후

별로라고?

아니다. 재밌을 것 같다. 왜냐하면 todolist에서 userList api를 받아오기 전(userList가 안보이는 상태)에 내 이름만 api에 등록해놓은 상태였는데, userList를 받은 누군가가 나에게 메시지를 써서 깜짝 놀랐다. 엄청 신기했고 비밀스러워서(?) 좋았다.
다음 날 켜본 todolist. 누군가로부터의 메시지를 받았다. 누구신가요!!!
다음 날 켜본 todolist. 누군가로부터의 메시지를 받았다. 누구신가요!!!