<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>BigTop_Log</title>
    <link>https://bigtop.tistory.com/</link>
    <description>프로그래밍, 일상 이야기</description>
    <language>ko</language>
    <pubDate>Sun, 14 Jun 2026 01:26:24 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>BigTop</managingEditor>
    <item>
      <title>[JavaScript] 투두리스트 만들기 - 생성한 아이템 업데이트하기 (2): 완료 상태 업데이트 기능</title>
      <link>https://bigtop.tistory.com/88</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNLEgi/btsF40xHlMP/XNSWTpSWK9GLdk8yirpNs0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNLEgi/btsF40xHlMP/XNSWTpSWK9GLdk8yirpNs0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNLEgi/btsF40xHlMP/XNSWTpSWK9GLdk8yirpNs0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNLEgi%2FbtsF40xHlMP%2FXNSWTpSWK9GLdk8yirpNs0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;424&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bigtop.tistory.com/87&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 글&lt;/a&gt;에서는 실제로 업데이트하기보다는 업데이트 준비를 했었는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 정말로 데이터 업데이트 로직을 작성해 봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 글에서 로컬스토리지에 저장할 때 수정했던 데이터 구조 기억하시나요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타이틀만 저장하던 객체에서 id와 isCompleted를 추가하는 작업까지 마쳤었는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 데이터 속성을 활용해서 체크박스 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;완료 상태 업데이트하는 기능&lt;/b&gt;&lt;/span&gt;을 만들어봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;체크박스(input type=&quot;checkbox&quot;)의 특징 알고 가기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본격적으로 기능을 만들기 전에 사실 지금까지 작성한 투두 리스트 화면을 보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이미 해보셨을 수도 있겠지만,) 새로 추가한 할 일의 체크박스를 클릭했을 때 딱히 이벤트를 등록하지 않았는데도 UI에서 체크 표시가 생겼다 사라졌다 하는 걸 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 체크박스 타입을 가진 인풋 태그의 고유한 특징인데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별다른 자바스크립트 코드 없이도 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;스스로 클릭을 감지하고 상태를 변경하는 능력&lt;/b&gt;&lt;/span&gt;을 가지고 있는 거죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사하게도 이 덕분에 우리가 자바스크립트로 해야 할 일은 더 간단한데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트로 클릭했을 때 체크박스 상태를 변하도록 하는 코드 보다,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;체크박스가 스스로 상태를 바꿀 때 그 상태를 감지해서 우리의 로컬스토리지 데이터에 저장&lt;/b&gt;&lt;/span&gt;하는 코드를 만들어야 해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;이벤트 위임(Event Delegation)으로 변화 감지하기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이제 체크박스의 상태가 변하는 걸 자바스크립트가 감지하도록 해야 하는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 한 가지 고민이 생기게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감지하는 그 이벤트를 어디에 붙여줄 것인가.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 직관적으로는 각 아이템에 이벤트를 붙여주는 아이디어가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 그렇게 하면 아이템을 생성할 때마다 이벤트를 등록해 주기 때문에 아이템을 생성할 때 필요한 동작이 하나 더 늘어나게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이템이 100개라면 이벤트 리스너가 100개가 생기게 되겠죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법이 절대 나쁘다거나 요즘은 성능상에 크게 문제가 있는 방법도 아니긴 하지만, 그래도 이것 보다 조금 더 괜찮은 방식으로 코드를 작성해보려고 하는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감지 이벤트를 &lt;b&gt;각각의 아이템에 아니라&lt;/b&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;리스트에 붙이는 방법이에요.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이템들의 부모인 ul 태그에 todo-list라는 id를 달고 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;todoList&lt;/b&gt;&lt;/span&gt;라는 변수에 담아뒀었죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;todoList에 이벤트를 달아두면 자식 요소들에게서 일어나는 이벤트를 확인할 수가 있는데 이 방식을 활용할 거예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식의 장점은 아이템이 100개 1,000개가 되더라도 리스트에 붙은 이벤트 리스너 1개로 모든 처리가 가능하다는 거예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 좀 더 궁금하시다면 &quot;이벤트 위임&quot;이라는 키워드로 한번 검색해 보시는 걸 추천드려요! 정말 모르겠다 하시면 '이벤트 버블링'이라는 개념도 같이 공부하시길 권장드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(언제가 될진 모르지만 나중에 저도 자바스크립트 이벤트와 관련해서 개념 정리글도 작성해 볼게요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 그럼 코드를 조금 작성해 봅시다!&lt;/p&gt;
&lt;pre id=&quot;code_1774095734973&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리스트 내부에서 일어나는 상태 변화 감지 (이벤트 위임)
todoList.addEventListener('change', (event) =&amp;gt; {
  // 이벤트가 발생한 대상이 체크박스인지 확인
  if (event.target.classList.contains('item-checkbox')) {
    const checkbox = event.target;
    
    // 클릭된 체크박스가 속한 최상위 todo-item(li 태그) 찾기
    const todoItem = checkbox.closest('.todo-item'); 
    
    // 아이템의 id 가져오기 
    const itemId = todoItem.getAttribute('id'); 
    
    // 업데이트 된 현재 체크박스의 상태 (true/false)
    const isChecked = checkbox.checked; 

    // ... 이제 이 데이터들을 활용해서 로컬스토리지를 업데이트해봅시다.
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서부터 주석을 기준으로 코드를 하나씩 보면&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;// 리스트 내부에서 일어나는 상태 변화 감지 (이벤트 위임)&lt;/span&gt;&lt;/b&gt;: &lt;br /&gt;체크박스에서 상태가 변하면 change이벤트가 발생하기 때문에 todoList에 change이벤트리스너를 만들어준 거예요.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;// 이벤트가 발생한 대상이 체크박스인지 확인&lt;/b&gt;&lt;/span&gt;:&lt;br /&gt;이벤트가 일어난 대상이 체크박스가 맞는지를 확인하고 체크박스 일 때만 로직을 실행하도록 조건문을 만든 거예요.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;// 클릭된 체크박스가 속한 최상위 todo-item(li 태그) 찾기&lt;/b&gt;&lt;/span&gt;:&lt;br /&gt;closest라는 메서드를 활용해서 체크박스를 감싸고 있는 가장 가까운 item을 찾는 거예요.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;// 아이템의 id 가져오기&lt;/b&gt;&lt;/span&gt;:&amp;nbsp;&lt;br /&gt;로컬스토리지의 데이터를 업데이트하려면 id를 가지고 와야겠죠? 업데이트를 위한 id를 찾는 과정입니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;// 업데이트된 현재 체크박스의 상태 (true/false)&lt;/b&gt;&lt;/span&gt;:&lt;br /&gt;체크박스가 체크가 된 상태라면 true, 빈칸이라면 false값을 가지게 됩니다. 이 데이터를 로컬스토리지에 업데이트하는 거죠.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;로컬스토리지 데이터 업데이트하기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 어떤 아이템의 체크박스가 눌렸는지도 알아냈고 체크박스의 상태도 알아낸 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 로컬 스토리지에 있는 데이터에 업데이트만 하면 되겠죠?&lt;/p&gt;
&lt;pre id=&quot;code_1774096567361&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;todoList.addEventListener('change', (event) =&amp;gt; {
  if (event.target.classList.contains('item-checkbox')) {
    const checkbox = event.target;
    const todoItem = checkbox.closest('.todo-item'); 
    
    const itemId = todoItem.getAttribute('id'); 
    const isChecked = checkbox.checked; 

    // 기존 데이터 불러오기
    const todos = getTodos(); 
    
    // 내가 클릭한 아이템이 배열에서 몇 번째(index) 방에 있는지 찾기
    const targetIndex = todos.findIndex(todo =&amp;gt; todo.id === itemId);
    // 만약 제대로 찾았다면 (-1이 아니라면) 
    if (targetIndex !== -1) {
      // 그 방에 있는 객체의 isCompleted 속성만 콕 집어서 isChecked 상태로 덮어쓰기!
      todos[targetIndex].isCompleted = isChecked;
      
      // 상태가 수정된 기존 배열을 그대로 다시 로컬스토리지에 밀어넣기
      localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
    }
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에도 주석을 기준으로 간단하게 설명해 보자면&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;// 기존 데이터 불러오기&lt;/b&gt;&lt;/span&gt;:&lt;br /&gt;로컬스토리지에 있는 원본 배열을 가져옵니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;// 내가 클릭한 아이템이 배열에서 몇 번째(index) 방에 있는지 찾기&lt;/b&gt;&lt;/span&gt;:&lt;br /&gt;업데이트하고자 하는 아이템이 배열의 어디에 있는지를 확인하는 과정입니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;// 만약 제대로 찾았다면 (-1이 아니라면)&lt;/b&gt;&lt;/span&gt;:&amp;nbsp;&lt;br /&gt;findIndex메서드는 index를 찾았다면 index를, 못 찾았다면 -1을 리턴하는데요. 이 특성을 활용했어요.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;// 그 방에 있는 객체의 isCompleted 속성만 콕 집어서 isChecked 상태로 덮어쓰기!&lt;/b&gt;&lt;/span&gt;:&lt;br /&gt;로컬스토리지에 있는 원본 배열에서 업데이트할 아이템의 상태를 업데이트해 주는 코드예요&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;// 상태가 수정된 기존 배열을 그대로 다시 로컬스토리지에 밀어 넣기:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;todos배열이 업데이트되긴 했지만 로컬스토리지에도 업데이트를 해줘야 업데이트가 완전히 끝이 나요!&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마무리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 js 코드를 한 번에 정리하면 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1774098178975&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const todoForm = document.getElementById('todo-form');
const todoInput = document.getElementById('todo-input');
const todoList = document.getElementById('todo-list');
const todoTemplate = document.getElementById('todo-template');

const STORAGE_KEY = 'todos';

const getTodos = () =&amp;gt; {
  return JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
};

const saveTodoItem = (todoItem) =&amp;gt; {
  const todoData = {
    id: todoItem.getAttribute('id'),
    title: todoItem.querySelector('.item-title').textContent,
    isCompleted: todoItem.querySelector('.item-checkbox').checked
  };
  const todos = getTodos().concat(todoData);

  localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
};

const createTodoItem = (todo) =&amp;gt; {
  const todoItem = todoTemplate.content
    .cloneNode(true)
    .querySelector('.todo-item');

  todoItem.querySelector('.item-title').textContent = todo.title;
  todoItem.querySelector('.item-checkbox').checked = todo.isCompleted;
  todoItem.setAttribute('id', todo.id);

  return todoItem;
};

const addTodoItem = (todo) =&amp;gt; {
  const todoItem = createTodoItem(todo);
  todoList.appendChild(todoItem);
  return todoItem;
};

const loadTodoItem = () =&amp;gt; {
  getTodos().forEach((todo) =&amp;gt; { addTodoItem(todo) });
};

const clearTodoInput = () =&amp;gt; {
  todoInput.value = '';
};

const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();

  const inputValue = todoInput.value.trim();

  if (inputValue === '') return;

  const newTodo = {
    id: Date.now(),
    title: inputValue,
    isCompleted: false,
  };

  saveTodoItem(addTodoItem(newTodo));
  clearTodoInput();
};

todoList.addEventListener('change', (event) =&amp;gt; {
  if (event.target.classList.contains('item-checkbox')) {
    const checkbox = event.target;
    const todoItem = checkbox.closest('.todo-item');

    const itemId = todoItem.getAttribute('id');
    const isChecked = checkbox.checked;

    const todos = getTodos();

    const targetIndex = todos.findIndex(todo =&amp;gt; todo.id === itemId);

    if (targetIndex !== -1) {
      todos[targetIndex].isCompleted = isChecked;
      localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
    }
  }
});

const initTodoApp = () =&amp;gt; {
  todoForm.addEventListener('submit', handleFormSubmit);
  loadTodoItem();
  clearTodoInput();
};

document.addEventListener('DOMContentLoaded', initTodoApp);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트를 등록하는 부분만 생긴거라 사실상 큰 코드변화는 없죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 코드를 실행하고 브라우저로 들어가서 체크박스를 눌러볼까요? 그리고 새로고침도 한번 해보세요!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-03-21 오후 10.05.39.png&quot; data-origin-width=&quot;1950&quot; data-origin-height=&quot;1274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DBn5N/dJMcagY8ASa/fTc3meKXMfr1hAcHpfc6xK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DBn5N/dJMcagY8ASa/fTc3meKXMfr1hAcHpfc6xK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DBn5N/dJMcagY8ASa/fTc3meKXMfr1hAcHpfc6xK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDBn5N%2FdJMcagY8ASa%2FfTc3meKXMfr1hAcHpfc6xK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;604&quot; height=&quot;395&quot; data-filename=&quot;스크린샷 2026-03-21 오후 10.05.39.png&quot; data-origin-width=&quot;1950&quot; data-origin-height=&quot;1274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;투두 아이템의 상태가 로컬스토리지와 잘 연동되어 있고, 새 로고침해도 상태가 그대로 유지되어 있는 모습을 확인하실 수 있을 거예요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 제 블로그에 정리되지 않은 이벤트 위임이나 findIndex 메서드 같은 개념이 등장하는 바람에 조금 내용이 어색하게 느껴질 수도 있을 것 같은데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 조금 개념이 너무 생소하셨다면 해당 키워드로 꼭 개념을 익혀보시는 걸 권장드려요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼, 여기까지 할 일 완료 상태 업데이트 기능을 구현해 봤는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글에서는 아이템 오른쪽에 붙은 Edit 버튼! 저 edit 버튼을 통해서 타이틀을 수정하는 기능을 완성해 봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;질문이나, 의문점이 드는 부분이라거나 제가 실수를 했다거나, 혹은 좀 더 좋은 방향이 있다면 댓글 부탁드립니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;더 좋은 글을 쓰고 제가 성장하는 데에도 큰 도움이 될 거예요! :)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>만학도 프로젝트/JavaScript TodoList</category>
      <category>checkbox</category>
      <category>findIndex</category>
      <category>Javascript</category>
      <category>javascript todo</category>
      <category>로컬스토리지</category>
      <category>배열 메서드</category>
      <category>이벤트 버블링</category>
      <category>이벤트 위임</category>
      <category>자바스크립트</category>
      <category>투두리스트</category>
      <author>BigTop</author>
      <guid isPermaLink="true">https://bigtop.tistory.com/88</guid>
      <comments>https://bigtop.tistory.com/88#entry88comment</comments>
      <pubDate>Sat, 21 Mar 2026 22:17:45 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 투두리스트 만들기 - 생성한 아이템 업데이트하기 (1): 데이터 구조 수정하기</title>
      <link>https://bigtop.tistory.com/87</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNLEgi/btsF40xHlMP/XNSWTpSWK9GLdk8yirpNs0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNLEgi/btsF40xHlMP/XNSWTpSWK9GLdk8yirpNs0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNLEgi/btsF40xHlMP/XNSWTpSWK9GLdk8yirpNs0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNLEgi%2FbtsF40xHlMP%2FXNSWTpSWK9GLdk8yirpNs0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;424&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;업데이트 기능 준비&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bigtop.tistory.com/86&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 글&lt;/a&gt;에서 로컬스토리지에 할 일들을 생성하고 불러오는 기능까지 완료했었습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;지금까지 완성한 코드를 실행해 보면 아이템들이 잘 생성되기도 하고 로컬스토리지에 저장도 되고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;페이지를 새로고침 해도 그대로 잘 남아있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그런데 아직 업데이트 기능이 없어서, 아이템 앞에 있는 체크박스를 클릭해도 새로고침 하면 금방 사라져 버리고, edit 버튼을 클릭해도 아무 일도 일어나질 않죠?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 이번에는 지난 시간에 예고했던 대로 CRUD 중에서 U, 아이템을 업데이트하는 기능을 만들어보려고 하는데요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;todo list에서 업데이트 기능은 방금 말한 것처럼 크게 두 가지가 있죠?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;첫 번째는 &lt;b&gt;완료 상태를 구분하는 체크박스 기능&lt;/b&gt;과&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;두 번째는 우리가 그동안 작성해온 &lt;b&gt;아이템의 타이틀을 수정하는 기능&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그런데 그 전에 한 가지 중요한 작업이 필요합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;데이터 구조 수정하기&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;업데이트를 위해 가장 먼저 해야 할 일은 우리의 데이터 구조를 수정하는 일입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;지금 기능에서 &quot;블로그 글쓰기&quot;와 &quot;운동하기&quot; 아이템을 생성했다면 로컬스토리지에 쌓인 데이터 구조는 다음과 같을 것입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1771239803547&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;[{&quot;title&quot;:&quot;블로그 글쓰기&quot;},{&quot;title&quot;:&quot;운동하기&quot;}]&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;당장은 타이틀 데이터만 필요했기 때문에 이걸로도 충분했지만, 업데이트는 상황이 조금 다릅니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;체크박스를 예로 들어보죠.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;만약 내가 오늘 운동하기를 완료했다면, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;title&lt;/b&gt;&lt;/span&gt;이 &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;&quot;운동하기&quot;&lt;/b&gt;&lt;/span&gt;인 아이템을 찾아서 업데이트해야 합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그런데 &lt;b&gt;만약 운동하기 아이템이 두 개라면&lt;/b&gt; 어떤 아이템의 상태를 완료로 처리하게 될까요?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;물론 하루에 운동을 두 번 하는 사람이 흔하진 않지만 어찌 됐든 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;지금 구조로는 타이틀이 중복된 경우에 업데이트해야 할 대상을 제대로 찾지 못해 의도치 않은 버그가 발생할 가능성&lt;/span&gt;&lt;/b&gt;이 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 업데이트를 하기 전에, &lt;b&gt;아이템을 생성할 때&lt;/b&gt; 해당 &lt;span style=&quot;color: #ef6f53;&quot;&gt;&lt;b&gt;아이템의 고유번호&lt;/b&gt;&lt;/span&gt;를 추가하려고 하는데요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;고유번호와 함께, &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;체크 상태를 관리할 속성&lt;/b&gt;&lt;/span&gt;도 함께 추가해 봅시다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;고유번호를 &lt;b&gt;id&lt;/b&gt;, 체크 상태를 &lt;b&gt;isCompleted&lt;/b&gt;로 해볼게요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;최종적으로 우리 할 일 아이템의 데이터 구조가 다음과 같이 되도록 해볼 겁니다.&lt;/p&gt;
&lt;pre id=&quot;code_1771242860429&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[
  { 
    id: 1234123412345,   // [NEW] 고유 식별자 (생성 날짜)
    title: &quot;블로그 쓰기&quot;,
    isCompleted: false   // [NEW] 완료 여부 (Boolean 타입)
  },
  { 
    id: 1234123412345,   
    title: &quot;운동하기&quot;,
    isCompleted: false
  }
]&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;함수 수정하기&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;데이터 구조는 우리가 생성할 때 만들어 봅시다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;처음부터 구조를 잡아둬야 데이터 흐름이 생성 로직에 일관되게 흐를 수 있을 것 같아요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그럼 &lt;b&gt;handleFormSubmit부터&lt;/b&gt; 수정해야 합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(나중에 이 데이터를 만드는 역할이 꼭 여기일 필요가 있는지는 마지막에 모든 기능을 만들고 나서 한번 더 점검해 보도록 해요!)&lt;/p&gt;
&lt;pre id=&quot;code_1771246444021&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();

  const inputValue = todoInput.value.trim();

  if (inputValue === '') return;

  // title만 추가하던 데이터를 이곳에서 미리 가공해서 전달해줍시다.
  const newTodo = {
    id: Date.now(),
    title: inputValue,
    isCompleted: false,
  };

  saveTodoItem(addTodoItem(newTodo)); // addTodoItem에 타이틀이 아닌 데이터 객체를 넘겨줍니다.
  clearTodoInput();
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 타이틀만 가지고서 todo 데이터를 관리하던 방식에서 이젠 필요한 데이터로 구조화된 todo 객체를 가지고 이후 로직들이 동작하게끔 해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;addTodoItem에 타이틀이 아닌 객체를 전달해 주는 형태로 코드가 변경됐으니, addTodoItem도 뭔가 수정을 해줘야겠죠?&lt;/p&gt;
&lt;pre id=&quot;code_1771246677160&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const addTodoItem = (todo) =&amp;gt; { //itemTitle을 todo로 변경
  const todoItem = createTodoItem(todo); // itemTitle을 todo로 변경
  todoList.appendChild(todoItem);
  return todoItem;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;근데 addTodoItem은 기존에도 파라미터 값을 받아서 뭔가를 하기보다는 사실상 화면에 todoItem을 그려주는 역할이 메인이었고, 파라미터로 전달받은 값은 그대로 createTodoItem에 전달만 해주고 있었으니, 사실상 파라미터 이름만 변경하면 됐었네요!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러면 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;createTodoItem&lt;/b&gt;&lt;/span&gt; 쪽에 로직 변경이 좀 더 필요하겠죠?&lt;/p&gt;
&lt;pre id=&quot;code_1771251883636&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const createTodoItem = (todo) =&amp;gt; { // itemTitle을 todo로 변경
  const todoItem = todoTemplate.content
    .cloneNode(true)
    .querySelector('.todo-item');

  todoItem.querySelector('.item-title').textContent = todo.title; // todo에서 title 추출
  todoItem.querySelector('.item-checkbox').checked = todo.isCompleted; // isCompleted 상태를 checkbox 요소에 반영
  todoItem.setAttribute('id', todo.id); // todo의 id 값을 요소의 id값으로 반영

  return todoItem;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 todo 객체의 각 속성들을 꺼내서 HTML요소에도 심어줘야 타이틀을 다룰 때처럼 이후에 로직들도 여기에 맞춰 대응할 수 있게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 마지막으로 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;saveTodoItem&lt;/b&gt;&lt;/span&gt; 로직을 수정해야 해요.&lt;/p&gt;
&lt;pre id=&quot;code_1771252305928&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const saveTodoItem = (todoItem) =&amp;gt; {
  const todoData = {
    id: todoItem.getAttribute('id'), // id값 추가
    title: todoItem.querySelector('.item-title').textContent,
    isCompleted: todoItem.querySelector('.item-checkbox').checked // isCompleted 추가
  };
  const todos = getTodos().concat(todoData);

  localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방금 전에 todoItem에 각 todo 객체의 속성 값들을 심어줬으니, 여기서 잘 꺼내서 todoData에 반영해 줘야 로컬스토리지에 잘 저장되겠죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자, 이제 데이터 구조 변화는 잘 마무리된 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각보다 바꿔야 될 게 많았죠? 진작에 잘 고민해서 설계했다면 좋았을걸 싶긴 하지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 다 배우고 성장해 나가는 과정 아니겠습니까..ㅎㅎㅎㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기까지 js 코드를 한 번에 정리하면 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1771239803550&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const todoForm = document.getElementById('todo-form');
const todoInput = document.getElementById('todo-input');
const todoList = document.getElementById('todo-list');
const todoTemplate = document.getElementById('todo-template');

const STORAGE_KEY = 'todos';

const getTodos = () =&amp;gt; {
  return JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
};

const saveTodoItem = (todoItem) =&amp;gt; {
  const todoData = {
    id: todoItem.getAttribute('id'),
    title: todoItem.querySelector('.item-title').textContent,
    isCompleted: todoItem.querySelector('.item-checkbox').checked
  };
  const todos = getTodos().concat(todoData);

  localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
};

const createTodoItem = (todo) =&amp;gt; {
  const todoItem = todoTemplate.content
    .cloneNode(true)
    .querySelector('.todo-item');

  todoItem.querySelector('.item-title').textContent = todo.title;
  todoItem.querySelector('.item-checkbox').checked = todo.isCompleted;
  todoItem.setAttribute('id', todo.id);

  return todoItem;
};

const addTodoItem = (todo) =&amp;gt; {
  const todoItem = createTodoItem(todo);
  todoList.appendChild(todoItem);
  return todoItem;
};

const loadTodoItem = () =&amp;gt; {
  getTodos().forEach((todo) =&amp;gt; { addTodoItem(todo) });
};

const clearTodoInput = () =&amp;gt; {
  todoInput.value = '';
};

const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();

  const inputValue = todoInput.value.trim();

  if (inputValue === '') return;

  const newTodo = {
    id: Date.now(),
    title: inputValue,
    isCompleted: false,
  };

  saveTodoItem(addTodoItem(newTodo));
  clearTodoInput();
};

const initTodoApp = () =&amp;gt; {
  todoForm.addEventListener('submit', handleFormSubmit);
  loadTodoItem();
  clearTodoInput();
};

document.addEventListener('DOMContentLoaded', initTodoApp);&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 로컬호스트를 한번 다 비우고 (&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;기존 데이터 삭제를 위해&lt;/b&gt;&lt;/span&gt;)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 코드를 실행해서 블로그 글쓰기와 운동하기를 추가해 보면,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-02-16 오후 11.38.39.png&quot; data-origin-width=&quot;2044&quot; data-origin-height=&quot;1278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ulfw8/dJMcaiCf90g/rHLQbnvK0E1SKPnIKsmKk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ulfw8/dJMcaiCf90g/rHLQbnvK0E1SKPnIKsmKk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ulfw8/dJMcaiCf90g/rHLQbnvK0E1SKPnIKsmKk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fulfw8%2FdJMcaiCf90g%2FrHLQbnvK0E1SKPnIKsmKk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;438&quot; data-filename=&quot;스크린샷 2026-02-16 오후 11.38.39.png&quot; data-origin-width=&quot;2044&quot; data-origin-height=&quot;1278&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제 기존에 저장된 데이터들이 처음에 의도했던 모양으로 잘 저장되는 모습을 확인할 수가 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기까지 데이터 구조 수정하기는 잘 마무리된 것 같아요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다음에는 본격적으로 업데이트 기능을 만들어 보도록 하겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;체크 박스부터 시작해 보죠!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;질문이나, 의문점이 드는 부분이라거나 제가 실수를 했다거나, 혹은 좀 더 좋은 방향이 있다면 댓글 부탁드립니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;더 좋은 글을 쓰고 제가 성장하는 데에도 큰 도움이 될 거예요! :)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>만학도 프로젝트/JavaScript TodoList</category>
      <category>javascript todo</category>
      <category>객체 다루기</category>
      <category>데이터 구조 수정하기</category>
      <category>자바스크립트 투두리스트 만들기</category>
      <category>함수 리팩터링하기</category>
      <author>BigTop</author>
      <guid isPermaLink="true">https://bigtop.tistory.com/87</guid>
      <comments>https://bigtop.tistory.com/87#entry87comment</comments>
      <pubDate>Mon, 16 Feb 2026 23:45:37 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 투두리스트 만들기 - 생성한 아이템 저장하고 불러오기 (2)</title>
      <link>https://bigtop.tistory.com/86</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNLEgi/btsF40xHlMP/XNSWTpSWK9GLdk8yirpNs0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNLEgi/btsF40xHlMP/XNSWTpSWK9GLdk8yirpNs0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNLEgi/btsF40xHlMP/XNSWTpSWK9GLdk8yirpNs0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNLEgi%2FbtsF40xHlMP%2FXNSWTpSWK9GLdk8yirpNs0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;424&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;지난 글 정리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bigtop.tistory.com/85&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 글&lt;/a&gt;에서 로컬스토리지에 할 일들을 저장하는 기능까지 완료했었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 완성한 코드를 실행해보면 아이템들이 잘 생성되기도 하고 로컬스토리지에 저장도 되지만, 막상&lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt; 페이지를 새로고침하면 모두 사라지는 상태&lt;/span&gt;&lt;/b&gt;인데요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심지어 그 상태에서&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt; 새로고침을 한 이후에 새로운 아이템들을 생성&lt;/b&gt;&lt;/span&gt;하게 되면 아래 이미지처럼 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;로컬 스토리지에 저장된 아이템과, 화면에 보이는 아이템들 간의 차이도 발생&lt;/b&gt;&lt;/span&gt;하게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3354&quot; data-origin-height=&quot;998&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3VxME/btsF094tE3n/2aXYIyoIHUdrjyHPVJo9S0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3VxME/btsF094tE3n/2aXYIyoIHUdrjyHPVJo9S0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3VxME/btsF094tE3n/2aXYIyoIHUdrjyHPVJo9S0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3VxME%2FbtsF094tE3n%2F2aXYIyoIHUdrjyHPVJo9S0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;208&quot; data-origin-width=&quot;3354&quot; data-origin-height=&quot;998&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 지금부터는 페이지를 새로고침했을 때 로컬스토리지에 저장된 값을 불러와서 화면에 그려주는 것까지 마무리해볼게요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;load 함수 만들기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 그럼 로컬스토리지에 있는 데이터를 가져와서 아이템을 추가해 주는 함수를 한번 만들어봅시다.&lt;/p&gt;
&lt;pre id=&quot;code_1711277713395&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ... addTodoItem ... 

const loadTodoItem = () =&amp;gt; {
  getTodos().forEach((todo) =&amp;gt; addTodoItem(todo.title));
};

// ... clearTodoInput ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미리 만들어둔 getTodos 함수와 addTodoItem 함수가 있어서 생각보다 간단하게 load 함수를 만들 수 있었는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위치는 addTodoItem 아래에 선언해 줬습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로직을 요약해 보면 &lt;b&gt;getTodos 함수로 저장된 아이템들을 불러오고, forEach 메서드를 이용해서 각 아이템들의 title로 addTodoItem 함수를 실행&lt;/b&gt;해 주는 내용입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;init 함수 만들기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 앞서 만든 load 함수를 이제 실행만 시켜주면 되는데, submit이벤트를 등록하는 부분 근처에서 실행시켜 줄 건데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그전에 한 가지 작업을 더 해보려고 합니다. 페이지가 로드되었을 때 일어나야 할 작업들을 한 군데 모아주는 작업을 해보려고 하는 건데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 작업한 내용으로 봤을 땐 처음 페이지에 접근했을 때 해야 할 일은 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;todoForm에 submit 이벤트를 등록해 주는 일&lt;/li&gt;
&lt;li&gt;loadTodoItem 함수를 실행시키는 일&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에 clearTodoInput 함수를 실행시키는 것까지 포함해서 총 3가지 일을 수행하는 init 함수를 다음과 같이 만들어봤어요.&lt;/p&gt;
&lt;pre id=&quot;code_1711283854037&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 기존의 &quot;todoForm.addEventListener('submit', handleFormSubmit);&quot; 코드는 삭제했어요.

const initTodoApp = () =&amp;gt; {
  todoForm.addEventListener('submit', handleFormSubmit);
  loadTodoItem();
  clearTodoInput();
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 함수를 페이지의 콘텐츠가 완전히 로드된 다음에 실행시키도록 해볼 건데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방법은 다음과 같이 document 객체에 DOMContentLoaded 이벤트 핸들러를 등록해 주면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1711284171800&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...

document.addEventListener('DOMContentLoaded', initTodoApp);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 코드를 구성한 이유는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;initTodoApp 함수로 &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;페이지가 완전히 로드된 다음에 반드시 필요한 행동들을 추상화&lt;/b&gt;&lt;/span&gt;하기 위함이고,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOMContentLoaded 이벤트의 핸들러로 등록함으로써 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;페이지가 완전히 로드된 다음이라는 &lt;span style=&quot;color: #ee2323;&quot;&gt;시점을 명확히&lt;/span&gt; 하기 위해서&lt;/b&gt;&lt;/span&gt;예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 js 코드를 한 번에 정리하면 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1711284624930&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const todoForm = document.getElementById('todo-form');
const todoInput = document.getElementById('todo-input');
const todoList = document.getElementById('todo-list');
const todoTemplate = document.getElementById('todo-template');

const STORAGE_KEY = 'todos';

const getTodos = () =&amp;gt; {
  return JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
};

const saveTodoItem = (todoItem) =&amp;gt; {
  const todoData = {
    title: todoItem.querySelector('.item-title').textContent,
  };
  const todos = getTodos().concat(todoData);

  localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
};

const createTodoItem = (itemTitle) =&amp;gt; {
  const todoItem = todoTemplate.content
    .cloneNode(true)
    .querySelector('.todo-item');

  todoItem.querySelector('.item-title').textContent = itemTitle;

  return todoItem;
};

const addTodoItem = (itemTitle) =&amp;gt; {
  const todoItem = createTodoItem(itemTitle);

  todoList.appendChild(todoItem);
  return todoItem;
};

const loadTodoItem = () =&amp;gt; {
  getTodos().forEach((todo) =&amp;gt; addTodoItem(todo.title));
};

const clearTodoInput = () =&amp;gt; {
  todoInput.value = '';
};

const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();

  const inputValue = todoInput.value.trim();

  if (inputValue === '') return;

  saveTodoItem(addTodoItem(inputValue));
  clearTodoInput();
};

const initTodoApp = () =&amp;gt; {
  todoForm.addEventListener('submit', handleFormSubmit);
  loadTodoItem();
  clearTodoInput();
};

document.addEventListener('DOMContentLoaded', initTodoApp);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 코드를 실행해 보면,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2676&quot; data-origin-height=&quot;1920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcd4ae/btsF1DjTVPs/eaYNix1W6XE1BLH77KUbvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcd4ae/btsF1DjTVPs/eaYNix1W6XE1BLH77KUbvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcd4ae/btsF1DjTVPs/eaYNix1W6XE1BLH77KUbvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbcd4ae%2FbtsF1DjTVPs%2FeaYNix1W6XE1BLH77KUbvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;502&quot; data-origin-width=&quot;2676&quot; data-origin-height=&quot;1920&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 기존에 저장된 데이터들로 아이템들을 잘 불러와서 그려주는 모습까지 확인할 수가 있네요! :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로고침해도 여전히 잘 남아있고요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 아이템을 생성하고 불러오는 기능은 잘 마무리된 것 같아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CRUD중 CR까진 한 것 같아요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 다음에는 U, 업데이트 기능을 만들어 보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문이나, 의문점이 드는 부분이라거나 제가 실수를 했다거나, 혹은 좀 더 좋은 방향이 있다면 댓글 부탁드립니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;더 좋은 글을 쓰고 제가 성장하는 데에도 큰 도움이 될 거예요! :)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>만학도 프로젝트/JavaScript TodoList</category>
      <category>DOMContentLoaded</category>
      <category>javascript todo</category>
      <category>js forEach</category>
      <category>js todolist</category>
      <category>localStorage</category>
      <category>todo item 불러오기</category>
      <category>todolist load</category>
      <category>불러오기 로직</category>
      <category>자바스크립트 todolist</category>
      <category>투두리스트 불러오기</category>
      <author>BigTop</author>
      <guid isPermaLink="true">https://bigtop.tistory.com/86</guid>
      <comments>https://bigtop.tistory.com/86#entry86comment</comments>
      <pubDate>Sun, 24 Mar 2024 22:00:29 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 투두리스트 만들기 - 생성한 아이템 저장하고 불러오기 (1)</title>
      <link>https://bigtop.tistory.com/85</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjmWYe/btsFt7dbut2/tTGJYyladtpiklwQuLxkg1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjmWYe/btsFt7dbut2/tTGJYyladtpiklwQuLxkg1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjmWYe/btsFt7dbut2/tTGJYyladtpiklwQuLxkg1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjmWYe%2FbtsFt7dbut2%2FtTGJYyladtpiklwQuLxkg1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;424&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bigtop.tistory.com/84&quot;&gt;지난 글&lt;/a&gt;에서 할 일을 생성하는 기능을 만들었었는데요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;생성하는 기능이 잘 동작하긴 하는데, 페이지를 새로고침 하면 아이템들이 모두 사라져 버립니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 localStorage를 활용해서 아이템을 생성할 때 그 정보를 저장해 두고,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;새로고침을 해서 페이지가 갱신될 때 localStorage에 저장된 정보를 가지고 와서 아이템들이 사라지지 않고 페이지가 갱신되기 직전의 모습을 유지할 수 있도록 해보려고 해요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;리팩터링&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일단은 지난번에 작성했던 코드를 조금 수정해 보겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;수정하는 이유는, 앞으로의 코드들이 &lt;b&gt;읽기, 수정, 삭제 기능들이 붙으면서 점점 더 복잡해질 예정&lt;/b&gt;이기 때문에 조금 더 의미를 명확하게 구분할 수 있도록 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;각 역할에 맞는 이름을 붙여주기 위해서&lt;/b&gt;&lt;/span&gt;예요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일단은 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;handleFormSubmit&lt;/b&gt;&lt;/span&gt; 함수 안에서 &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;과하다 싶을 정도&lt;/span&gt;&lt;/b&gt;(?)로 각각의 역할로 구분할 수 있는 로직들에 이름을 붙여주는 형태로 리팩터링 해보려고 합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;저는 크게 3가지로 나눴는데요.&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;첫 번째&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;는&lt;/span&gt; 템플릿 태그를 활용해서 가상의 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;.todo-item&lt;/b&gt;&lt;/span&gt;을 만드는 역할 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;(생성)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;두 번째&lt;/span&gt;&lt;/b&gt;는 만들어진 &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;.todo-item&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;을&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt; #todoList&lt;/b&gt;&lt;/span&gt;에 넣어주는 역할 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;(추가)&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;마지막&lt;/span&gt;&lt;/b&gt;은 .todo-item을 추가하고 나서 todoInput을 초기화해 주는 역할 &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;(인풋 초기화)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위 세 가지 역할을 각각 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;createTodoItem&lt;/span&gt;&lt;/b&gt;, &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;addTodoItem&lt;/span&gt;&lt;/b&gt;, &lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;clearTodoInput&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;으로&lt;/span&gt; 나눠줄게요.&lt;/p&gt;
&lt;pre id=&quot;code_1709292371510&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const todoForm = document.getElementById('todo-form');
const todoInput = document.getElementById('todo-input');
const todoList = document.getElementById('todo-list');
const todoTemplate = document.getElementById('todo-template');

// 생성
const createTodoItem = (itemTitle) =&amp;gt; {
  const todoItem = todoTemplate.content
    .cloneNode(true)
    .querySelector('.todo-item');

  todoItem.querySelector('.item-title').textContent = itemTitle;

  return todoItem;
};

// 추가
const addTodoItem = (itemTitle) =&amp;gt; {
  const todoItem = createTodoItem(itemTitle);
  
  todoList.appendChild(todoItem);
};

// 인풋 초기화
const clearTodoInput = () =&amp;gt; {
  todoInput.value = '';
};

const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();

  const inputValue = todoInput.value.trim();

  if (inputValue === '') return;

  addTodoItem(inputValue);
  clearTodoInput();
};

todoForm.addEventListener('submit', handleFormSubmit);&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;생성은 추가와 같이 이뤄지는 거니깐, &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;addTodoItem&lt;/span&gt;&lt;/b&gt;안에서 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;createTodoItem&lt;/span&gt;&lt;/b&gt;를 호출하도록 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;handleFormSubmit&lt;/span&gt;&amp;nbsp;&lt;/b&gt;함수를 수정했습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;저장 로직 만들기&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제 저장로직을 만들어 볼 텐데요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;로컬스토리지를 통해서 저장 로직을 만들 때 가장 먼저 할 것은 &lt;b&gt;불러오는 환경을 구축하기&lt;/b&gt;입니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;왜냐하면 저장할 때 어디에 저장할지를 분명히 해야 하기 때문이에요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;왠지 로컬스토리지를 전혀 모르시는 분들은 &lt;b&gt;'어디냐니? 로컬스토리지에다 하는 거 아니야?'&lt;/b&gt; 하실 수도 있을 것 같은데,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;로컬스토리지는 객체처럼 key:value 쌍으로 값을 저장하고 불러올 수가 있는 구조로 되어있어요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 어떤 키에다 값을 저장할지를 생각하고, 그 값을 불러오는 함수를 먼저 만들어 둘 거예요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래야 그 키 값에 새로운 값을 덮어쓸 수가 있거든요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;저는 여러 개의 &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;.todo-item&lt;/b&gt;&lt;/span&gt;들의 정보를 저장해야 하니깐 배열의 형태로 아이템들을 다룰 거고, 그 배열을 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;'todos'&lt;/span&gt;&lt;/b&gt;라는 키로 관리해보려고 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1709293804019&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...

const STORAGE_KEY = 'todos';

const getTodos = () =&amp;gt; {
  return JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
};

...&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 이렇게 로컬스토리지의 todos 값을 가져오는 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;getTodos&lt;/b&gt;&lt;/span&gt;함수를 만들어봤는데요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;로컬스토리지의 getItem 메서드로 'todos'에 접근해서 값이 있으면 JSON으로 파싱 해서 리턴해주고, 없으면 빈배열을 리턴해주는 함수입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;로컬스토리지의 키 값은 불러올 때도, 저장할 때도, 삭제할 때도 써야 하니깐 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;STORAGE_KEY&lt;/b&gt;&lt;/span&gt;로 따로 선언해 뒀어요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;자, 그러면 이제는 진짜 저장하는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;saveTodoItem&lt;/b&gt;&lt;/span&gt;함수를 아래와 같이 만들어 주겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1709294561092&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...

const STORAGE_KEY = 'todos';

const getTodos = () =&amp;gt; {
  return JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
};

const saveTodoItem = (todoItem) =&amp;gt; {
  const todoData = {
    title: todoItem.querySelector('.item-title').textContent,
  };
  const todos = getTodos().concat(todoData);
  localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
};

// ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;createTodoItem&lt;/span&gt;&lt;/b&gt;으로 만든 &lt;b&gt;todoItem&lt;/b&gt;을 아규먼트로 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;saveTodoItem&lt;/b&gt;&lt;/span&gt;에 전달해 주면 다음과 같은 동작이 수행되는 건데요.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;title 값을 찾아서 todoData 객체를 완성합니다.&lt;/li&gt;
&lt;li&gt;앞서 만든 getTodos를 활용해서 로컬스토리지에 저장된 값을 불러오고, 그 뒤에 todoData를 concat 메서드로 붙여서 todos 배열을 완성합니다.&lt;/li&gt;
&lt;li&gt;새로운 아이템이 추가된 todos를 로컬스토리지에 저장합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 제가 단순히 todoItem들의 title만 감싸는 배열을 만들지 않은 이유는, 투두 아이템에 체크 상태도 함께 관리하기 위해서예요. 다음에 체크상태를 관리할 때 todoData에 프로퍼티를 더 추가할 예정입니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;자, 그럼 이제 이 저장 로직을 아이템이 추가될 때 잘 실행시켜주기만 하면 될 것 같은데요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;addTodoItem 코드를 조금만 수정하고, handleFormSubmit 에서 실행하는 걸로 해보겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러면 다음과 같은 코드가 완성이 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1709295924526&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const todoForm = document.getElementById('todo-form');
const todoInput = document.getElementById('todo-input');
const todoList = document.getElementById('todo-list');
const todoTemplate = document.getElementById('todo-template');

const STORAGE_KEY = 'todos';

const getTodos = () =&amp;gt; {
  return JSON.parse(localStorage.getItem(STORAGE_KEY)) || [];
};

const saveTodoItem = (todoItem) =&amp;gt; {
  const todoData = {
    title: todoItem.querySelector('.item-title').textContent,
  };
  const todos = getTodos().concat(todoData);
  
  localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
};

const createTodoItem = (itemTitle) =&amp;gt; {
  const todoItem = todoTemplate.content
    .cloneNode(true)
    .querySelector('.todo-item');

  todoItem.querySelector('.item-title').textContent = itemTitle;

  return todoItem;
};

const addTodoItem = (itemTitle) =&amp;gt; {
  const todoItem = createTodoItem(itemTitle);

  todoList.appendChild(todoItem);
  return todoItem; // &amp;lt;- 여기서 생성한 아이템을 리턴!
};

const clearTodoInput = () =&amp;gt; {
  todoInput.value = '';
};

const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();

  const inputValue = todoInput.value.trim();

  if (inputValue === '') return;

  saveTodoItem(addTodoItem(inputValue)); // &amp;lt;- 여기서 실행!
  clearTodoInput();
};

todoForm.addEventListener('submit', handleFormSubmit);&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 수정하면, addTodoItem 에서 추가된 아이템이 그대로 saveTodoItem 의 아규먼트로 전달되면서 화면에 아이템을 추가하고 저장하는 순서로 코드가 동작하겠죠?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;단순히 저장하나 넣었는데도 코드가 이렇게나 많아지다니.. 그래도 각 동작들에 이름 붙이기를 잘해둬서 크게 어지럽진 않은 것 같아요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아무튼 여기까지 코드를 실행해 보면, 투두 아이템이 새로 추가될 때마다 아이템들이 로컬스토리지에 잘 저장되는 걸 볼 수 있습니다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2166&quot; data-origin-height=&quot;1312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HxrQ4/btsFoEwrm5y/5Kh6lz9AfrkvuEBkAckvj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HxrQ4/btsFoEwrm5y/5Kh6lz9AfrkvuEBkAckvj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HxrQ4/btsFoEwrm5y/5Kh6lz9AfrkvuEBkAckvj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHxrQ4%2FbtsFoEwrm5y%2F5Kh6lz9AfrkvuEBkAckvj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;424&quot; data-origin-width=&quot;2166&quot; data-origin-height=&quot;1312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 저장은 잘 되는 것 같죠?&lt;/p&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;급 마무리&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;사실 이번 포스트에서 저장하고 불러오는 것까지 하려고 했는데, 생각보다 글 쓰는 게 시간이 너무 오래 걸리기도 했고 쓰고 나니 저장만 하는데도 양이 꽤 되는 것 같아서 불러오기는 다음에 이어서 작성해 보도록 할게요!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아직도 새로고침 하면 다 사라지긴 하지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;저장 기능은 완성&lt;/b&gt;&lt;/span&gt;이에요!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다음에는 저렇게 로컬스토리지에 저장된 정보를 불러와서 아이템들을 그려주는 기능을 완성해 보도록 하겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;당연히 질문이나, 의문점이 드는 부분이라거나 제가 실수를 했다거나, 혹은 좀 더 좋은 방향이 있다면 댓글 부탁드립니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;더 좋은 글을 쓰고 제가 성장하는 데에도 큰 도움이 될 거예요! :)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>만학도 프로젝트/JavaScript TodoList</category>
      <category>javascript todo</category>
      <category>js todolist</category>
      <category>localStorage</category>
      <category>todo item save</category>
      <category>todo item 저장</category>
      <category>todolist save</category>
      <category>리팩터링</category>
      <category>자바스크립트 todolist</category>
      <category>저장로직</category>
      <category>투두리스트 저장</category>
      <author>BigTop</author>
      <guid isPermaLink="true">https://bigtop.tistory.com/85</guid>
      <comments>https://bigtop.tistory.com/85#entry85comment</comments>
      <pubDate>Fri, 1 Mar 2024 21:36:09 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 투두리스트 만들기 - 할 일 생성 기능</title>
      <link>https://bigtop.tistory.com/84</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TWtIX/btsFiNTDtux/Wkh91d1qKOiXgZlhtf6Ak0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TWtIX/btsFiNTDtux/Wkh91d1qKOiXgZlhtf6Ak0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TWtIX/btsFiNTDtux/Wkh91d1qKOiXgZlhtf6Ak0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTWtIX%2FbtsFiNTDtux%2FWkh91d1qKOiXgZlhtf6Ak0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;424&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bigtop.tistory.com/83&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 글&lt;/a&gt;에서 HTML 구조를 잡았었는데요.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결과물은 아래 이미지처럼 예쁘진 않지만 일단 필요한 모양들은 다 갖춰진 모습을 하고 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-02-18 오전 1.43.49.png&quot; data-origin-width=&quot;2028&quot; data-origin-height=&quot;1306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5Zm19/btsFeC0C5tB/1ALb4ygS5wX7RieHpKzVU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5Zm19/btsFeC0C5tB/1ALb4ygS5wX7RieHpKzVU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5Zm19/btsFeC0C5tB/1ALb4ygS5wX7RieHpKzVU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5Zm19%2FbtsFeC0C5tB%2F1ALb4ygS5wX7RieHpKzVU0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;451&quot; data-filename=&quot;스크린샷 2024-02-18 오전 1.43.49.png&quot; data-origin-width=&quot;2028&quot; data-origin-height=&quot;1306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;너무 보기 힘든 수준이면 예쁘게 다듬는 작업부터 하려고 했었는데, 기능적은 부분을 만드는데 크게 불편함은 없는 수준이라 투두리스트의 기능부터 만들어보려고 해요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;가장 먼저 해야 할 일은 생성 기능이라 생각해서, 생성 기능부터 한번 만들어 보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;input#todo-input&lt;/b&gt;&lt;/span&gt;에 텍스트를 입력하고&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;button#submit-btn&lt;/span&gt;&lt;/b&gt;을 클릭하면&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;ul#todo-list&lt;/span&gt;&lt;/b&gt;에 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;li.todo-item&lt;/b&gt;&lt;/span&gt;이 추가되도록 해볼거예요.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;HTML 수정&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일단은 HTML 수정을 먼저 해보겠습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;li.todo-item&lt;/b&gt;이 계속 반복될 거라서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;li 부분을 template 태그로&lt;/b&gt;&lt;/span&gt; 빼볼 건데요. 달라지는 부분은 &lt;b&gt;span.item-title&lt;/b&gt;이니깐 그 부분을 비워주고 template을 만들어 줄 겁니다.&lt;/li&gt;
&lt;li&gt;그리고 자바스크립트 코드를 따로 js 파일로 빼서 작성할 거니깐 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;index.js 파일을 불러오는 script 태그도 작성&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;해 줄게요.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러면 다음과 같은 HTML 코드가 나오게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1708745815963&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;en&quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot; /&amp;gt;
    &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&amp;gt;
    &amp;lt;title&amp;gt;MHD To Do List&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div class=&quot;todo-container&quot;&amp;gt;
      &amp;lt;h1 class=&quot;title&quot;&amp;gt;To Do List&amp;lt;/h1&amp;gt;
      &amp;lt;form id=&quot;todo-form&quot;&amp;gt;
        &amp;lt;input type=&quot;text&quot; id=&quot;todo-input&quot; placeholder=&quot;어떤 계획이 있나요?&quot; /&amp;gt;
        &amp;lt;button type=&quot;submit&quot; id=&quot;submit-btn&quot;&amp;gt;Add&amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
      &amp;lt;ul id=&quot;todo-list&quot;&amp;gt;&amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;!-- li.todo-item 부분 template 태그로 옮기기 --&amp;gt;
    &amp;lt;template id=&quot;todo-template&quot;&amp;gt;
      &amp;lt;li class=&quot;todo-item&quot;&amp;gt;
        &amp;lt;input type=&quot;checkbox&quot; class=&quot;item-checkbox&quot; /&amp;gt;
        &amp;lt;span class=&quot;item-title&quot;&amp;gt;&amp;lt;/span&amp;gt;
        &amp;lt;button class=&quot;edit-btn&quot;&amp;gt;Edit&amp;lt;/button&amp;gt;
        &amp;lt;button class=&quot;delete-btn&quot;&amp;gt;Delete&amp;lt;/button&amp;gt;
      &amp;lt;/li&amp;gt;
    &amp;lt;/template&amp;gt;
    &amp;lt;!-- index.js 파일 불러오는 script 태그 작성 --&amp;gt;
    &amp;lt;script src=&quot;index.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;template 태그 관련해서는 제가 따로 블로그에 정리해 둔 게 없긴 한데요, 이 프로젝트 끝난 다음에 따로 한번 정리해 볼게요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;간단하게 설명하면, &lt;b&gt;템플릿 태그는 이름에서도 느낄 수 있듯이 &lt;span style=&quot;color: #006dd7;&quot;&gt;미리 틀을 잡아두고 자바스크립트로 동적으로 그 모양의 요소를 편하게 생성할 수 있게 도와주는 태그&lt;/span&gt;&lt;/b&gt;입니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 실제로 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;템플릿 태그를 작성하면, 브라우저에 노출되지도 않아요&lt;/b&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2030&quot; data-origin-height=&quot;1300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmr4Kb/btsFf2YJ7Ap/LwR5lgg36AeHoiyJH0w0Y1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmr4Kb/btsFf2YJ7Ap/LwR5lgg36AeHoiyJH0w0Y1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmr4Kb/btsFf2YJ7Ap/LwR5lgg36AeHoiyJH0w0Y1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcmr4Kb%2FbtsFf2YJ7Ap%2FLwR5lgg36AeHoiyJH0w0Y1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;448&quot; data-origin-width=&quot;2030&quot; data-origin-height=&quot;1300&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;코드를 실행해 보면, 이렇게 아이템이 사라진 걸 확인할 수 있죠?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그럼 이제 같은 html 파일과 같은 위계에 index.js 파일을 만들고 자바스크립트 코드를 작성하러 가봅시다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;할 일 생성 코드 작성 준비하기&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일단 먼저 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;필요한 요소들을 변수로 선언&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;해 볼게요.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1708754273139&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const todoForm = document.getElementById('todo-form');
const todoInput = document.getElementById('todo-input');
const todoList = document.getElementById('todo-list');
const todoTemplate = document.getElementById('todo-template');&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;할 일 생성을 하기 위해 필요한 요소는 이 4가지입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러고 나서 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;form 태그에 'submit' 이벤트를 하나 추가&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;해 줄 건데요.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1708754847897&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;todoForm.addEventListener('submit', (event) =&amp;gt; {});&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;저는 개인적으로 이벤트를 등록할 때 미리 만들어둔 함수를 등록하는 쪽이 좀 더 가독성이 좋게 느껴져서 &lt;b&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;이벤트 핸들러를 handleFormSubmit이라는 함수를 따로 만들어서 전달&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;해 볼게요.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1708755036099&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const todoForm = document.getElementById('todo-form');
const todoInput = document.getElementById('todo-input');
const todoList = document.getElementById('todo-list');
const todoTemplate = document.getElementById('todo-template');

const handleFormSubmit = (event) =&amp;gt; {
  
};

todoForm.addEventListener('submit', handleFormSubmit);&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;할 일 생성 이벤트 핸들러 작성하기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 할 일은 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;form 태그의 기본 동작을 막아주는 거&lt;/b&gt;&lt;/span&gt;예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;form 태그는 기본적으로 submit 이벤트에 form 태그 안의 다양한 양식의 데이터들을 요리조리 다루고서 필요한 action을 취한 다음 페이지를 갱신하는 동작이 갖춰져 있어서 그런 기본 동작을 막아줘야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방법은 이벤트 핸들러 첫 번째 파라미터로 넘어오는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;event 객체의 preventDefault 메서드를 콜&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 해주는 거예요.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1708756066894&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//...

const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();
};

//...&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그다음은 &lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;인풋 태그에 값이 작성되어 있는지 확인&lt;/b&gt;&lt;/span&gt;합시다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;값이 없으면 굳이 아이템을 추가할 필요가 없으니깐&lt;/b&gt;요. &lt;b&gt;값이 없는 아이템이 생성되는 게 오히려 더 이상한 UX겠죠?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;input요소의 값이 없으면 함수를 빨리 리턴&lt;/b&gt;&lt;/span&gt;해서 이후 로직들이 동작하지 않도록 해줍시다.&lt;/p&gt;
&lt;pre id=&quot;code_1708761973581&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...

const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();
  // todoInput의 값 추출
  const inputValue = todoInput.value.trim();
  // 값 없으면 빨리 return 하기
  if (inputValue === '') return;
};

// ...&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 이제 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;template 태그를 활용해서 가상의 아이템 요소를 생성&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;해 볼 건데요.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;방법은 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;template 요소의 content 프로퍼티에 접근하고, cloneNode 메서드를 호출할 때 첫 번째 아규먼트로 true 값을 전달해서 호출&lt;/b&gt;&lt;/span&gt;하면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1708762726766&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...

const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();
  // todoInput의 값 추출
  const inputValue = todoInput.value.trim();
  // 값 없으면 빨리 return 하기
  if (inputValue === '') return;
  const todoItem = todoTemplate.content.cloneNode(true);
};

// ...&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그런데 이렇게 하면, &lt;b&gt;todoItem이 정확히 li 태그가 아니라, DocumentFragment라는 객체&lt;/b&gt;가 되는데요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이대로 사용해도 특정 요소에 appenChild를 하면 큰 문제없이 li 태그가 추가되긴 하지만, 그래도 조금 더 명확하게 해주고 싶어서 querySelector 메서드로 정확히 li.todo-item 요소를 잡아주도록 할게요.&lt;/p&gt;
&lt;pre id=&quot;code_1708762972819&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...

const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();
  const inputValue = todoInput.value.trim();
  if (inputValue === '') return;
  
  // 템플릿으로 .todo-item 구조를 복사하고 정확하게 .todo-item 요소 선택하기
  const todoItem = todoTemplate.content.cloneNode(true).querySelector('.todo-item');
};

// ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제 거의 다 완성된 것 같아요!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;잡아둔 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;todoItem에서 title이 들어갈 자리(span.item-title)에 접근해서 타이틀을 할당&lt;/b&gt;&lt;/span&gt;하고,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그렇게 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;구성된 아이템을 todoList에 추가&lt;/b&gt;&lt;/span&gt;해 주면 생성기능이 완성이 돼.. 겠지만!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;마지막으로 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;input의 값을 초기화&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;해줘야 해요!&lt;/span&gt; &lt;/span&gt; 생성했으면 인풋은 다시 비워줘야겠죠? ㅎㅎ&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러면 진짜 완성이 됩니다!!&lt;/p&gt;
&lt;pre id=&quot;code_1708763952349&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// ...

const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();
  const inputValue = todoInput.value.trim();
  if (inputValue === '') return;

  const todoItem = todoTemplate.content.cloneNode(true).querySelector('.todo-item');
  // .item-title에 inputValue를 추가
  todoItem.querySelector('.item-title').textContent = inputValue;
  // title이 추가된 todoItem을 todoList에 추가
  todoList.appendChild(todoItem);

  // input 초기화
  todoInput.value = '';
};

// ...&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;마무리: Index.js&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1708763759511&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const todoForm = document.getElementById('todo-form');
const todoInput = document.getElementById('todo-input');
const todoList = document.getElementById('todo-list');
const todoTemplate = document.getElementById('todo-template');

const handleFormSubmit = (event) =&amp;gt; {
  event.preventDefault();
  const inputValue = todoInput.value.trim();
  if (inputValue === '') return;

  const todoItem = todoTemplate.content.cloneNode(true).querySelector('.todo-item');
  todoItem.querySelector('.item-title').textContent = inputValue;
  todoList.appendChild(todoItem);

  todoInput.value = '';
};

todoForm.addEventListener('submit', handleFormSubmit);&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 코드를 완성하고 나면,&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1804&quot; data-origin-height=&quot;1414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FzEu4/btsFfXDe9iy/wPYAxl1k4B9EUibEuNfuiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FzEu4/btsFfXDe9iy/wPYAxl1k4B9EUibEuNfuiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FzEu4/btsFfXDe9iy/wPYAxl1k4B9EUibEuNfuiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFzEu4%2FbtsFfXDe9iy%2FwPYAxl1k4B9EUibEuNfuiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;549&quot; data-origin-width=&quot;1804&quot; data-origin-height=&quot;1414&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아직 수정이나 삭제도 안되고, 새로고침 하면 다 사라지긴 하지만, &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;생성 기능은 완성&lt;/b&gt;&lt;/span&gt;이에요!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;당연히 질문이나, 의문점이 드는 부분이라거나 제가 실수를 했다거나, 혹은 좀 더 좋은 방향이 있다면 댓글 부탁드립니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;더 좋은 글을 쓰고 제가 성장하는 데에도 큰 도움이 될 거예요! :)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>만학도 프로젝트/JavaScript TodoList</category>
      <category>cloneNode</category>
      <category>DocumentFragment</category>
      <category>javascript todo</category>
      <category>javascript todolist</category>
      <category>template tag</category>
      <category>todo item create</category>
      <category>todo item 생성</category>
      <category>자바스크립트 todolist</category>
      <category>자바스크립트 todolist 만들기</category>
      <category>자바스크립트 투두리스트 만들기</category>
      <author>BigTop</author>
      <guid isPermaLink="true">https://bigtop.tistory.com/84</guid>
      <comments>https://bigtop.tistory.com/84#entry84comment</comments>
      <pubDate>Sat, 24 Feb 2024 17:48:34 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 투두리스트 만들기 - HTML 뼈대 잡기</title>
      <link>https://bigtop.tistory.com/83</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUuRkE/btsEYQc3LWx/aZs0eCoxsY9sBWvanV3Yak/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUuRkE/btsEYQc3LWx/aZs0eCoxsY9sBWvanV3Yak/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUuRkE/btsEYQc3LWx/aZs0eCoxsY9sBWvanV3Yak/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUuRkE%2FbtsEYQc3LWx%2FaZs0eCoxsY9sBWvanV3Yak%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;424&quot; data-filename=&quot;pexels-breakingpic-3243.jpg&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 프로젝트가 2020년에 완성됐는데, 2024년에 세 번째 프로젝트를 시작하네요. ㅎㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째는 투두리스트를 만들어보려 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 프로젝트와 연계해서 날짜별로 투두리스트를 관리하는 큰 그림을 그려볼까 하는데, 일단은 투두리스트에만 집중해서 프로젝트를 완성시켜 볼게요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;&lt;b&gt;기획&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_KakaoTalk_Photo_2024-02-18-00-37-30.jpeg&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;668&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s6kK8/btsEYWj0Bcg/ZnBqDU6njtj9XZANKlKvA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s6kK8/btsEYWj0Bcg/ZnBqDU6njtj9XZANKlKvA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s6kK8/btsEYWj0Bcg/ZnBqDU6njtj9XZANKlKvA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs6kK8%2FbtsEYWj0Bcg%2FZnBqDU6njtj9XZANKlKvA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;429&quot; height=&quot;668&quot; data-filename=&quot;edited_KakaoTalk_Photo_2024-02-18-00-37-30.jpeg&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;668&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에도 손그림으로 간단하게 프로젝트를 그려봤습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;투두리스트 하면 제 머릿속에 떠오르는 세로로 긴 사각 박스를 그렸고, 손으로는 이렇게 그렸지만 가로 세로 1:1.61804 황금비로 만들어 보겠습니다.&lt;/li&gt;
&lt;li&gt;상단에는 가운데 정렬로 Todo-list라는 타이틀이 들어가고,&lt;/li&gt;
&lt;li&gt;그 아래는 input 태그랑 add 버튼으로 아이템을 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;생성(Create)&lt;/b&gt;&lt;/span&gt;하는 기능을 갖추고&lt;/li&gt;
&lt;li&gt;그 아래는 생성된 아이템들을 &lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;나열(Read)&lt;/b&gt;&lt;/span&gt;하고, 각 아이템들 안에는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;체크(Update)&lt;/b&gt;&lt;/span&gt; 기능과 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;타이틀 수정(Update)&lt;/span&gt;&lt;/b&gt;, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;제거(Delete)&lt;/b&gt;&lt;/span&gt; 기능을 갖추도록 해보려고 해요.&lt;/li&gt;
&lt;li&gt;그리고 아이템들을 다룰 때(&lt;b&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;C&lt;/span&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;R&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;D&lt;/span&gt;&lt;/b&gt;) LocalStorage를 활용해서 브라우저를 새로고침해도 잘 유지되도록 해보겠습니다.&lt;br /&gt;(혹시 LocalStorage를 처음 들으신다면 &lt;a href=&quot;https://bigtop.tistory.com/82&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[JavaScript] 자바스크립트 localStorage 가볍게 이해하기&lt;/a&gt;가 도움이 되길 바라요)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;HTML 뼈대 잡기&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1708186623410&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;en&quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot; /&amp;gt;
    &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&amp;gt;
    &amp;lt;title&amp;gt;MHD To Do List&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div class=&quot;todo-container&quot;&amp;gt;
      &amp;lt;h1 class=&quot;title&quot;&amp;gt;To Do List&amp;lt;/h1&amp;gt;
      &amp;lt;form id=&quot;todo-form&quot;&amp;gt;
        &amp;lt;input type=&quot;text&quot; id=&quot;todo-input&quot; placeholder=&quot;어떤 계획이 있나요?&quot; /&amp;gt;
        &amp;lt;button type=&quot;submit&quot; id=&quot;submit-btn&quot;&amp;gt;Add&amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
      &amp;lt;ul id=&quot;todo-list&quot;&amp;gt;
        &amp;lt;li class=&quot;todo-item&quot;&amp;gt;
          &amp;lt;input type=&quot;checkbox&quot; class=&quot;item-checkbox&quot;/&amp;gt;
          &amp;lt;span class=&quot;item-title&quot;&amp;gt;HTML 뼈대 잡기&amp;lt;/span&amp;gt;
          &amp;lt;button class=&quot;edit-btn&quot;&amp;gt;Edit&amp;lt;/button&amp;gt;
          &amp;lt;button class=&quot;delete-btn&quot;&amp;gt;Delete&amp;lt;/button&amp;gt;
        &amp;lt;/li&amp;gt;
      &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 HTML 구조는 이전 프로젝트들과 크게 다르지 않습니다. (에디터에서 추천해 주는 html:5 템플릿 그대로 사용)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러고 나서&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;황금비율을 갖출 &lt;b&gt;div.todo-container&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;타이틀을 가질 &lt;b&gt;h1.title&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;생성기능을 담당해 줄 &lt;b&gt;form#todo-form&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;새로운 아이템 입력을 받을 &lt;b&gt;input#todo-input&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;아이템 생성버튼 &lt;b&gt;button#submit-btn&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;생성된 아이템들을 나열해 줄 &lt;b&gt;ul#todo-list&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 큰 구조를 갖추고서 생성될 아이템을 미리 만들었는데,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;생성된 아이템 자체가 될 &lt;b&gt;li.todo-item&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;체크 상태를 반영해 줄 &lt;b&gt;input.item-checkbox&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;아이템 타이틀을 담는 &lt;b&gt;span.item-title&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;수정을 담당해 줄 &lt;b&gt;button.edit-btn&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;삭제를 담당해 줄 &amp;nbsp;&lt;b&gt;button.delete-btn &lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 아이템을 구성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-02-18 오전 1.43.49.png&quot; data-origin-width=&quot;2028&quot; data-origin-height=&quot;1306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzx4EK/btsEXtvVO6m/yGpTmUfHP67rTS0HcML5DK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzx4EK/btsEXtvVO6m/yGpTmUfHP67rTS0HcML5DK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzx4EK/btsEXtvVO6m/yGpTmUfHP67rTS0HcML5DK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbzx4EK%2FbtsEXtvVO6m%2FyGpTmUfHP67rTS0HcML5DK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;451&quot; data-filename=&quot;스크린샷 2024-02-18 오전 1.43.49.png&quot; data-origin-width=&quot;2028&quot; data-origin-height=&quot;1306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 실행한 코드가 위와 같은 모습인데 일단은 따로 스타일링은 한 게 없어서 예쁘진 않지만, 얼추 기획에 맞게 필요한 구조들은 나온 것 같죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스타일링은 가장 마지막에 하는 걸로 하고, 다음에는 input 창에 타이틀을 입력하고 add 버튼을 누르면 &lt;b&gt;ul#todo-list에&lt;/b&gt; 아이템이 추가되도록 해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연히 질문이나, 의문점이 드는 부분이라거나 제가 실수를 했다거나, 혹은 좀 더 좋은 방향이 있다면 댓글 부탁드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 좋은 글을 쓰고 제가 성장하는 데에도 큰 도움이 될 거예요! :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>만학도 프로젝트/JavaScript TodoList</category>
      <category>javascript todo</category>
      <category>javascript todolist</category>
      <category>javascript todolist local storage</category>
      <category>simple todo list javascript</category>
      <category>to do list</category>
      <category>todo</category>
      <category>TODOlist</category>
      <category>자바스크립트 todolist</category>
      <category>자바스크립트 todolist 만들기</category>
      <category>자바스크립트 투두리스트 만들기</category>
      <author>BigTop</author>
      <guid isPermaLink="true">https://bigtop.tistory.com/83</guid>
      <comments>https://bigtop.tistory.com/83#entry83comment</comments>
      <pubDate>Sun, 18 Feb 2024 01:55:17 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 자바스크립트 localStorage 가볍게 이해하기</title>
      <link>https://bigtop.tistory.com/82</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfqnJC/btsC7qmp5QJ/EuvgOMWXRIGz3nNPOFCAwK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfqnJC/btsC7qmp5QJ/EuvgOMWXRIGz3nNPOFCAwK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfqnJC/btsC7qmp5QJ/EuvgOMWXRIGz3nNPOFCAwK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfqnJC%2FbtsC7qmp5QJ%2FEuvgOMWXRIGz3nNPOFCAwK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;427&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;LocalStorage란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;LocalStorage&lt;/code&gt;는 웹 브라우저에서 클라이언트 측에서 데이터를 저장할 수 있는 여러 메커니즘 중 하나로, 특정 네트워크 요청을 통해 값을 저장하고 불러오는 것이 아니라 키-값 쌍을 사용하여 온전히 브라우저의 리소스만을 사용해서 데이터를 저장하고 불러올 수 있다는 특징이 있다. 심지어 브라우저를 종료하고 다시 열어도 유지된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;LocalStorage 다루기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬스토리지(LocalStorage)를 다루는 방법은 간단하다. localStorage라는 객체를 그냥 사용하면 된다.&lt;br /&gt;localStorage의 각 메서드를 활용하면 손쉽게 저장하고 불러오고 삭제하고 초기화 할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;저장하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장은 &lt;code&gt;setItem&lt;/code&gt; 이라는 메서드를 활용한다.&lt;br /&gt;두 개의 파라미터를 가지는데, 키-값 순서대로 아규먼트를 넘겨주면 된다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// setItem 메서드를 활용해 데이터 저장하기
localStorage.setItem('myName', 'bigtop');&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;불러오기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불러오기는 &lt;code&gt;getItem이다.&lt;/code&gt;&lt;br /&gt;로컬스토리지에서 찾고자 하는 키값을 아규먼트로 하나만 넘겨주면 된다.&lt;br /&gt;그럼 해당 값이 반환되는데, 그 값을 변수에 담아 사용하면 되는 것이다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// getItem 메서드를 활용해 데이터 불러오기
const myName = localStorage.getItem('myName');
console.log(myName) // bigtop&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고하면 좋을 부분은, 만약 값이 있다면 String 타입의 값이 반환되고 값이 없다면 null을 반환한다.&lt;br /&gt;undefined가 아님에 주의하자!&lt;br /&gt;아래 코드를 실행한 결과도 함께 확인해 보자&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// setItem 메서드를 활용해 데이터 저장하기
localStorage.setItem('myName', 'bigtop');

// getItem 메서드를 활용해 데이터 불러오기
const myName = localStorage.getItem('myName');
console.log(myName) // ?
console.log(typeof myName) // ?
const yourName = localStorage.getItem('yourName');
console.log(yourName) // ?
console.log(typeof yourName) // ?&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1774&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vZ27l/btsC2C9AzMd/XBjlKeWMkl4973xCC5Kz3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vZ27l/btsC2C9AzMd/XBjlKeWMkl4973xCC5Kz3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vZ27l/btsC2C9AzMd/XBjlKeWMkl4973xCC5Kz3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvZ27l%2FbtsC2C9AzMd%2FXBjlKeWMkl4973xCC5Kz3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1774&quot; height=&quot;182&quot; data-origin-width=&quot;1774&quot; data-origin-height=&quot;182&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;제거하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제거하기는 &lt;code&gt;removeItem이다.&lt;/code&gt; 메서드 이름들이 직관적이라서 좋다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// removeItem 메서드를 활용해 데이터 제거하기
localStorage.removeItem('myName');

const myName = localStorage.getItem('myName');
console.log(myName) // null
console.log(typeof myName) // object&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;초기화(전체 제거하기)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;removeItem&lt;/code&gt;을 통해 키-값 데이터를 하나씩 지울 수도 있지만,&lt;br /&gt;&lt;code&gt;clear&lt;/code&gt;라는 메서드를 사용하면 로컬스토리지 데이터를 한 번에 다 지울 수도 있다.&lt;br /&gt;&lt;code&gt;clear&lt;/code&gt;메서드는 그냥 호출만 하면 된다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;// clear 메서드를 활용해 데이터 제거하기
localStorage.clear();&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;LocalStorage는 개발자 도구에서도 다룰 수 있다.&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2040&quot; data-origin-height=&quot;1384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8kMWK/btsC9x6nzge/mRpiyOeIJx3kDTqM9SX5iK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8kMWK/btsC9x6nzge/mRpiyOeIJx3kDTqM9SX5iK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8kMWK/btsC9x6nzge/mRpiyOeIJx3kDTqM9SX5iK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8kMWK%2FbtsC9x6nzge%2FmRpiyOeIJx3kDTqM9SX5iK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2040&quot; height=&quot;1384&quot; data-origin-width=&quot;2040&quot; data-origin-height=&quot;1384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크롬을 기준으로 설명하면 개발자도구 상단 여러 탭 중에 &lt;code&gt;애플리케이션&lt;/code&gt;이라는 탭에 들어가면 왼쪽 사이드바에 여러 메뉴들이 있는데 그중에 로컬 스토리지라는 메뉴도 있는 걸 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;들어가 보면 방금 저장한 값이 있는 걸 확인할 수 있는데, 키-값의 각 테이블 빈 공간을 더블클릭하면 값을 저장할 수 있다.(setItem)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 키-값이 있는 테이블 위쪽으로 조금만 시선을 이동하면 필터라는 placeholder가 있는 인풋에 값을 입력해 데이터를 검색할 수도 있으니 참고하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 값을 선택하고 필터 인풋 바로 우측에 있는 두 개의 버튼 중 x 버튼을 누르면 데이터를 제거할 수도 있는데, 값을 선택하고 백스페이스 키를 눌러서 제거할 수도 있다. (removeItem)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x 버튼 바로 왼쪽에 있는 동그라미 안에 사선이 있는 버튼은 로컬스토리지 전체를 비우는 clear 메서드와 같은 역할을 한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주의사항!&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 간단하게 백엔드 엔지니어 도움 없이 프런트엔드 엔지니어가 브라우저의 리소스만으로 가볍게 데이터를 다룰 수 있도록 도와주는 로컬스토리지인 만큼, 주의해야 할 사항들이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;용량 제한&lt;/b&gt;: &lt;code&gt;LocalStorage&lt;/code&gt;는 브라우저마다 저장 용량 제한이 다를 수 있다. 대체로 최소 5MB 이상 지원되지만, 브라우저별로 확인이 필요하다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;민감정보 다루지 않기&lt;/b&gt;: &lt;code&gt;LocalStorage&lt;/code&gt;는 브라우저의 리소스를 사용해서 굉장히 쉽게 데이터를 저장하고 활용할 수 있는 만큼, 민감한 정보를 로컬스토리지를 통해 다루는 일은 지양해야 한다. 비밀번호와 같은 중요한 정보를 다룰 때는 로컬스토리지가 아닌 다른 안전한 방법을 사용하는 것이 적절하다.&lt;/p&gt;</description>
      <category>프로그래밍 이야기/JavaScript 공부</category>
      <category>Javascript</category>
      <category>localStorage</category>
      <category>데이터 저장</category>
      <category>로컬스토리지</category>
      <category>로컬스토리지 개발자도구로 확인하는 방법</category>
      <category>로컬스토리지 주의사항</category>
      <category>브라우저에 데이터 저장하는 방법</category>
      <category>웹개발</category>
      <category>자바스크립트</category>
      <category>프론트엔드</category>
      <author>BigTop</author>
      <guid isPermaLink="true">https://bigtop.tistory.com/82</guid>
      <comments>https://bigtop.tistory.com/82#entry82comment</comments>
      <pubDate>Fri, 5 Jan 2024 20:52:58 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 자바스크립트 includes 메서드 이해하기</title>
      <link>https://bigtop.tistory.com/81</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QpGKn/btsv9Nbyd11/1cQV8c8YnTZKiZJkMsnRT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QpGKn/btsv9Nbyd11/1cQV8c8YnTZKiZJkMsnRT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QpGKn/btsv9Nbyd11/1cQV8c8YnTZKiZJkMsnRT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQpGKn%2Fbtsv9Nbyd11%2F1cQV8c8YnTZKiZJkMsnRT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;427&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;includes 메서드란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;includes 메서드는 &lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;배열이나 문자열&lt;/span&gt;&lt;/b&gt;에 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;특정한 값을 포함하는지&lt;/b&gt;&lt;/span&gt; 여부를 확인하는 메서드다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정한 값을 포함하는지에서 유추할 수 있듯이, includes 메서드는 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;boolean 타입의 값을 리턴&lt;/b&gt;&lt;/span&gt;한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문법&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문법은 생각보다 간단한 형태로 사용되는데, 배열이나 문자열 뒤에 includes 메서드를 실행시키고 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;첫 번째 파라미터에 확인하고 싶은 특정한 값을 아규먼트로 전달해 주면&lt;/span&gt;&lt;/b&gt; 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1696151341586&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 1. 배열에서 includes() 메서드 사용 예시:
const array = ['제우스', '카나비', '쵸비', '룰러', '케리아'];

console.log('1. 배열에서 includes() 메서드 사용 예시:');
console.log(array.includes('쵸비')); // ?
console.log(array.includes('페이커')); // ?

// 2. 문자열에서 includes() 메서드 사용 예시:
const string = 'Javascript';

console.log('2. 문자열에서 includes() 메서드 사용 예시:');
console.log(string.includes('a')) // ?
console.log(string.includes('b')) // ?&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위의 코드를 실행시켰을 때 결과는 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1794&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/leOur/btsv9NP8GfR/v8hUCLB4txXVzLtOPH0tmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/leOur/btsv9NP8GfR/v8hUCLB4txXVzLtOPH0tmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/leOur/btsv9NP8GfR/v8hUCLB4txXVzLtOPH0tmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FleOur%2Fbtsv9NP8GfR%2Fv8hUCLB4txXVzLtOPH0tmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1794&quot; height=&quot;232&quot; data-origin-width=&quot;1794&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 배열 예제부터 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;array에서 includes 메서드를 사용하여 특정 값의 존재 여부를 확인했을 때, 첫 번째는 &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;'쵸비'&lt;/b&gt;&lt;/span&gt;가 array에 포함되어 있으므로 &lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;true&lt;/b&gt;&lt;/span&gt;를 반환하고. 두번째 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;'페이커'&lt;/b&gt;&lt;/span&gt;는 array에 포함되지 않았으므로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;false&lt;/b&gt;&lt;/span&gt;를 반환한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 문자열 예제에서는 문자열 string에서 includes를 사용했는데, 여기도 배열과 크게 다르지 않게 Javascript라는 문자열에 a는 있지만 b는 없기 때문에 각각 true와 false 가 출력된 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문자열 메서드로 활용할 때 주의점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;includes 메서드를 활용할 땐 몇 가지 주의해야할 사항이 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1696152954332&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const string = 'Javascript';

console.log('문자열에서 includes() 메서드 사용 예시:');
console.log('J: ', string.includes('J')) // ?
console.log('j: ', string.includes('j')) // ?
console.log('as: ', string.includes('as')) // ?
console.log('Java: ', string.includes('Java')) // ?
console.log('script: ', string.includes('script')) // ?&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 실행하면 다음과 같은 결과가 나온다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1788&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PCu17/btsv8fTQ8S7/aeDer9D4QZX0GWzkH91yJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PCu17/btsv8fTQ8S7/aeDer9D4QZX0GWzkH91yJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PCu17/btsv8fTQ8S7/aeDer9D4QZX0GWzkH91yJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPCu17%2Fbtsv8fTQ8S7%2FaeDer9D4QZX0GWzkH91yJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1788&quot; height=&quot;284&quot; data-origin-width=&quot;1788&quot; data-origin-height=&quot;284&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 포인트는 대소문자 구분이다. 처음 두 결과를 보면 Javascript 에서 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;J(대문자)&lt;/b&gt;&lt;/span&gt;는 있지만 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;j(소문자)&lt;/b&gt;&lt;/span&gt; 는 없기 때문에 각각 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;true&lt;/span&gt;&lt;/b&gt;, &lt;b&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;false&lt;/span&gt;&lt;/b&gt; 가 출력되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너무 당연한 게 아닌가 싶긴 하지만 실제로 코드를 작성할 때는 직접 값을 전달하는 게 아니라 변수에 담긴 값을 활용하다 보니 그 의외로 대소문자가 구분되지 않고 값이 전달되어 의도치 않게 코드가 동작하는 경우를 심심찮게 만나볼 수도 있으니 주의해야 할 필요가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;두 번째 포인트는 사실 이 상황을 어떻게 표현해야할지 모르겠지만, 문자열에서 이 includes 메서드를 활용했을 때 첫 번째 파라미터로 전달한 값이 이 &lt;b&gt;문자열 전체의 부분&lt;/b&gt;(?)으로 문자열 포함 여부를 확인하기 때문에 발생하는 현상이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 사실상 너무 당연한 느낌이긴 하지만, includes 메서드는 문자열의 일치를 확인하는 것이 아니기 때문에 Javascript라는 문자열에 includes 메서드의 아규먼트로 as, Java, script 같은 문자열을 전달하면 모두 true 값을 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정한 음절단위의 문자가 아니라, 독립적으로 의미를 가지는 단어나 문장들이 들어가서 의도치 않은 true 값이 반환되면서 의도치 않게 코드가 동작하는 경우가 생각보다 은근히 발생할 수 있을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>프로그래밍 이야기/JavaScript 공부</category>
      <category>INCLUDES</category>
      <category>includes method</category>
      <category>Javascript</category>
      <category>javascript includes</category>
      <category>js includes</category>
      <category>메서드</category>
      <category>문자열 메서드</category>
      <category>배열 메서드</category>
      <category>자바스크립트</category>
      <category>포함여부 확인하기</category>
      <author>BigTop</author>
      <guid isPermaLink="true">https://bigtop.tistory.com/81</guid>
      <comments>https://bigtop.tistory.com/81#entry81comment</comments>
      <pubDate>Sun, 1 Oct 2023 18:55:24 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 자바스크립트 every 메서드 이해하기</title>
      <link>https://bigtop.tistory.com/80</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;458&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czarcj/btss3KVlRxb/9lQIvOdDMEzLYJcCu0Slz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czarcj/btss3KVlRxb/9lQIvOdDMEzLYJcCu0Slz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czarcj/btss3KVlRxb/9lQIvOdDMEzLYJcCu0Slz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fczarcj%2Fbtss3KVlRxb%2F9lQIvOdDMEzLYJcCu0Slz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;458&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;458&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Every 메서드란?&lt;/b&gt;&lt;/h3&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;every 메서드는 배열의 요소들이 특정 조건을&lt;span&gt; &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;모두 만족하는지&lt;/span&gt;&lt;/b&gt;를 확인하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;배열(Array)의 메서드&lt;/b&gt;&lt;/span&gt;다.&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;문법 역시 some과 마찬가지로 &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://bigtop.tistory.com/58&quot;&gt;forEach&lt;/a&gt;&lt;span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://bigtop.tistory.com/57&quot;&gt;map&lt;/a&gt;&lt;span&gt;&lt;span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://bigtop.tistory.com/74&quot;&gt;filter&lt;/a&gt;&lt;/span&gt;와 거의 비슷하게 첫 번째 파라미터가 콜백 함수를 전달받지만, 앞의 메서드들과는 다르게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;boolean 타입의 값을 리턴&lt;/b&gt;&lt;/span&gt;한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문법&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1693755505289&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const values = [1, 2, 3, 4, 5, 6];

const isPositive = values.every((currentElement, index, currentArray) =&amp;gt; {
    console.log(`요소: ${currentElement}`);
    console.log(`index: ${index}`);
    console.log(currentArray);
      
    return currentElement &amp;gt; 0;
});

console.log('isPositive');
console.log(isPositive); // ?&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문법도&lt;span&gt; &lt;/span&gt;&lt;b&gt;some 메서드와 거의 똑같다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;every 메서드 또한 some 메서드와 같이 첫 번째 파라미터로 전달되는 함수의 리턴 값이 중요한데, some 메서드와 마찬가지로 &amp;nbsp;마지막 리턴 값을 boolean 타입으로 평가한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다만, 한가지 다른 점은 이 평가를 토대로 true, 혹은 false를 리턴한다는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;874&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boadXq/btssQbAOko2/76GlOkj419ckd4QdS9x3MK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boadXq/btssQbAOko2/76GlOkj419ckd4QdS9x3MK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boadXq/btssQbAOko2/76GlOkj419ckd4QdS9x3MK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboadXq%2FbtssQbAOko2%2F76GlOkj419ckd4QdS9x3MK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;575&quot; height=&quot;442&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;874&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;Some과 반대로 활용할 수 있다!&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;some과 독특한 점 역시 비슷하다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote style=&quot;color: #333333; text-align: center;&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;some 메서드는 배열의 요소들 중&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;특정 조건을 만족하는 요소가&amp;nbsp;&lt;/span&gt;&lt;b&gt;하나 이상 있는지&lt;/b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;를 확인&lt;/span&gt;&lt;/span&gt;하는&amp;nbsp;&lt;br /&gt;배열(Array)의 메서드다.&lt;br /&gt;every 메서드는 배열의 요소들이&lt;br /&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;특정 조건을 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;모두 만족하는지&lt;/span&gt;&lt;/b&gt; 확인하는&lt;/span&gt;&lt;br /&gt;배열(Array)의 메서드다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;조금만 디테일하면서도 약간 복잡하게 말하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;배열의 각 요소를 반복하면서 콜백 함수의 첫 번째 아규먼트(currentElement)로 배열의 요소를 넘겨줬을 때, 콜백 함수가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;truthy&lt;/span&gt;&lt;/b&gt;를&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;하나도 빠짐없이 리턴하는지&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;를 확인하는 메서드인 것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그런데 여기서 놓치지 말아야 할 부분은 반대로, &lt;span style=&quot;color: #ffffff; background-color: #ee2323;&quot;&gt;&lt;b&gt;&amp;nbsp;falsy를 하나라도 리턴한다면, 해당 메서드는 바로 false를 리턴한다는&lt;/b&gt;&lt;/span&gt; 생각도 해야 한다!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;지금 계속 모두 만족을 강조하고 있는데, 위 예시 코드에서 첫 번째 요소만 0으로 바꿔서 실행해 보자.&lt;/p&gt;
&lt;pre id=&quot;code_1693755200487&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const values = [0, 2, 3, 4, 5, 6];

const isPositive = values.every((currentElement, index, currentArray) =&amp;gt; {
    console.log(`요소: ${currentElement}`);
    console.log(`index: ${index}`);
    console.log(currentArray);
      
    return currentElement &amp;gt; 0;
});

console.log('isPositive');
console.log(isPositive); // ?&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1136&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dSebPQ/btssToF6yto/YsYXanswqv4PkHepgMA3n0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dSebPQ/btssToF6yto/YsYXanswqv4PkHepgMA3n0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dSebPQ/btssToF6yto/YsYXanswqv4PkHepgMA3n0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdSebPQ%2FbtssToF6yto%2FYsYXanswqv4PkHepgMA3n0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;525&quot; height=&quot;102&quot; data-origin-width=&quot;1136&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;isPositive는 false이고, 콘솔에 찍힌 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;반복 횟수가 단 한 번&lt;/b&gt;&lt;/span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;values의 첫 번째 요소인 0&lt;/span&gt;&lt;/b&gt;이 이미 주어진 콜백 함수의&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;span&gt; &lt;/span&gt;false 리턴&lt;/span&gt;&lt;/b&gt;을 이뤄냈기 때문에&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;span&gt; &lt;/span&gt;every는 false 값으로 반복이 종료&lt;/span&gt;&lt;/b&gt;된 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;기존에 공부한 some과 다르지만 비슷한 원리로 활용가능한 부분이 바로 이 부분이다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;every 역시 some과 마찬가지로 배열의 요소 개수만큼 콜백 함수를 실행하지 않을 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 부분은 상황에 따라&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;효율을 관리&lt;/b&gt;하는데 충분히 이용될 수 있을 것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1693755200507&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const values = [];

const isPositive = values.every((currentElement, index, currentArray) =&amp;gt; {
    console.log(`요소: ${currentElement}`);
    console.log(`index: ${index}`);
    console.log(currentArray);
      
    return currentElement &amp;gt; 0;
});

console.log('isPositive');
console.log(isPositive); // ?&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;만약 요소가 아무것도 없는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;빈 배열에서 every 메서드를 호출&lt;/b&gt;하면 어떻게 될까?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1136&quot; data-origin-height=&quot;86&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIaUHk/btssSCkAFO4/KBGfOop8wAbKNoO2qKEXb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIaUHk/btssSCkAFO4/KBGfOop8wAbKNoO2qKEXb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIaUHk/btssSCkAFO4/KBGfOop8wAbKNoO2qKEXb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIaUHk%2FbtssSCkAFO4%2FKBGfOop8wAbKNoO2qKEXb0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;48&quot; data-origin-width=&quot;1136&quot; data-origin-height=&quot;86&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결과는 true, 그리고 콜백 함수는 한 번도 실행되지 않는다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그렇다면 만약 undefined 나 null 요소가 들어가면 어떻게 될까?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;values를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;i&gt;[null, undefined]&lt;/i&gt;&lt;/b&gt;로 바꿔서 실행해 봤다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pKcX3/btssSqxEMPh/GAseRzmghb7xj18IaPNyJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pKcX3/btssSqxEMPh/GAseRzmghb7xj18IaPNyJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pKcX3/btssSqxEMPh/GAseRzmghb7xj18IaPNyJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpKcX3%2FbtssSqxEMPh%2FGAseRzmghb7xj18IaPNyJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;642&quot; height=&quot;124&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결과는 false, 그리고 some 메서드와는 다르게 콜백함수가 1번 실행이 되었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;왜일까?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;간단하게 결과만 말하자면, &lt;b&gt;null과 undefined의 number타입으로의 형변환이 각각 0과 NaN이기 때문&lt;/b&gt;이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;currentElement &amp;gt; 0 과의 비교에서 currnetElement로 들어간 null이 0으로 변환되고, 0 &amp;gt; 0 이 false 이기 때문에 이후의 콜백함수는 실행되지 않고 반복이 종료되면서 every 메서드의 결과는 false를 리턴하게 되는 것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그럼 마지막으로 요소 3개짜리 Array를 만들어서 실행하면 어떻게 될까?&lt;/p&gt;
&lt;pre id=&quot;code_1693755200545&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const values = new Array(3);

const isPositive = values.every((currentElement, index, currentArray) =&amp;gt; {
  console.log(`요소: ${currentElement}`);
  console.log(`index: ${index}`);
  console.log(currentArray);

  return currentElement &amp;gt; 0;
});

console.log('isPositive');
console.log(isPositive); // ?&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;90&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Qa01v/btss3ViknXr/LBzBLQBUrH6gjctf7TZDg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Qa01v/btss3ViknXr/LBzBLQBUrH6gjctf7TZDg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Qa01v/btss3ViknXr/LBzBLQBUrH6gjctf7TZDg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQa01v%2Fbtss3ViknXr%2FLBzBLQBUrH6gjctf7TZDg1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;645&quot; height=&quot;51&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;90&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결과는 &lt;span style=&quot;color: #ef5369; text-align: start;&quot;&gt;배열의 길이(values.length)가 분명히 3 임에도 불구하고 콜백 함수는 한 번도 실행되지 않았지만,&lt;/span&gt; 결과는 true였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 부분은 어떻게 동작한 건지 조금 의아하긴 하지만, 참고해도 좋을법하다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;내가 의아한 포인트는, 분명 values [0]이든 [1]이든 [2] 든 간에 values의 값에 접근하면 값이 undefined 이기 때문에,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;undefined &amp;gt; 0 이 false 일 텐데도 불구하고 결과 값이 true 인 부분인 것이다.&lt;/p&gt;</description>
      <category>프로그래밍 이야기/JavaScript 공부</category>
      <category>Array</category>
      <category>Every</category>
      <category>every 메서드</category>
      <category>filter</category>
      <category>Javascript</category>
      <category>SOME</category>
      <category>메서드</category>
      <category>배열</category>
      <category>배열 메서드</category>
      <category>자바스크립트</category>
      <author>BigTop</author>
      <guid isPermaLink="true">https://bigtop.tistory.com/80</guid>
      <comments>https://bigtop.tistory.com/80#entry80comment</comments>
      <pubDate>Mon, 4 Sep 2023 01:14:09 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 자바스크립트 some 메서드 이해하기</title>
      <link>https://bigtop.tistory.com/77</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdAJjQ/btrNEwXu7xE/2MkU5i7pw8zoIhc3agtPzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdAJjQ/btrNEwXu7xE/2MkU5i7pw8zoIhc3agtPzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdAJjQ/btrNEwXu7xE/2MkU5i7pw8zoIhc3agtPzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdAJjQ%2FbtrNEwXu7xE%2F2MkU5i7pw8zoIhc3agtPzk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;341&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;some 메서드란?&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;some 메서드는 배열의 요소들중 특정 조건을 만족하는 요소가 &lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;하나 이상 있는지&lt;/span&gt;&lt;/b&gt;를 확인하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;배열(Array)의 메서드&lt;/b&gt;&lt;/span&gt;다.&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;문법은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bigtop.tistory.com/58&quot;&gt;forEach&lt;/a&gt;&lt;span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bigtop.tistory.com/57&quot;&gt;map&lt;/a&gt;&lt;span&gt;&lt;span&gt;, &lt;a href=&quot;https://bigtop.tistory.com/74&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;filter&lt;/a&gt;&lt;/span&gt;와 거의 비슷하게 첫 번째 파라미터가 콜백 함수를 전달받지만, 앞의 메서드들과는 다르게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;boolean 타입의 값을 리턴&lt;/b&gt;&lt;/span&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문법&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1664715324916&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const values = [1, 2, 3, 4, 5, 6];

const hasOver5 = values.some((currentElement, index, currentArray) =&amp;gt; {
    console.log(`요소: ${currentElement}`);
    console.log(`index: ${index}`);
    console.log(currentArray);
      
    return currentElement &amp;gt; 5;
});

console.log('hasOver5');
console.log(hasOver5); // ?&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문법은 &lt;b&gt;filter 메서드와 거의 똑같다. &lt;/b&gt;some 메서드 또한 filter 메서드와 같이 첫 번째 파라미터로 전달해되는 함수의 리턴 값이 중요한데, filter 메서드와 마찬가지로 &amp;nbsp;마지막 리턴 값을 boolean 타입으로 평가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 한가지 다른 점은 이 평가를 토대로 true, 혹은 false를 리턴한다는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1508&quot; data-origin-height=&quot;876&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sqzA3/btrNCgHpqf7/7okZn2Uz6uF1QjiDCZK2oK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sqzA3/btrNCgHpqf7/7okZn2Uz6uF1QjiDCZK2oK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sqzA3/btrNCgHpqf7/7okZn2Uz6uF1QjiDCZK2oK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsqzA3%2FbtrNCgHpqf7%2F7okZn2Uz6uF1QjiDCZK2oK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;372&quot; data-origin-width=&quot;1508&quot; data-origin-height=&quot;876&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;독특한 점?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;한 가지 독특한 점은 지금부터다. 위 예제 결과를 봐서는 잘 모르겠지만 some 은 그동안 살펴본 배열의 메서드와는 조금 다르게 동작한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;앞서 설명한 some 메서드의 정의를 다시 한번 곱씹어보자.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;some 메서드는 배열의 요소들중 &lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;특정 조건을 만족하는 요소가&amp;nbsp;&lt;/span&gt;&lt;b&gt;하나 이상 있는지&lt;/b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;를 확인&lt;/span&gt;&lt;/span&gt;하는&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;배열(Array)의 메서드&lt;/span&gt;다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금만 디테일 하면서도 약간 복잡하게 말하면 &lt;span style=&quot;color: #f89009;&quot;&gt;배열의 각 요소를 반복하면서 콜백 함수의 첫 번째 아규먼트(currentElement)로 배열의 요소를 넘겨줬을 때, 콜백 함수가 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;truthy&lt;/span&gt;&lt;/b&gt;를 리턴하게 되는 경우가 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;하나라도 있는지&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;를 확인하는 메서드인 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 계속 하나 이상을 강조하고 있는데, 위 예시 코드에서 배열의 순서만 123456 에서 654321로 바꿔서 실행해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1664716355426&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const values = [6, 5, ,4, 3, 2, 1];

const hasOver5 = values.some((currentElement, index, currentArray) =&amp;gt; {
    console.log(`요소: ${currentElement}`);
    console.log(`index: ${index}`);
    console.log(currentArray);
      
    return currentElement &amp;gt; 5;
});

console.log('hasOver5');
console.log(hasOver5); // true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfyeCj/btrNzJ4nS6b/WiatsIIlLAHCYyGrgbIb31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfyeCj/btrNzJ4nS6b/WiatsIIlLAHCYyGrgbIb31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfyeCj/btrNzJ4nS6b/WiatsIIlLAHCYyGrgbIb31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfyeCj%2FbtrNzJ4nS6b%2FWiatsIIlLAHCYyGrgbIb31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;106&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;230&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;hasOver5는 true 로&lt;span&gt;&lt;span&gt; &lt;span&gt;결과는 똑&lt;/span&gt;같&lt;/span&gt;&lt;/span&gt;다. 하지만 콘솔에 찍힌&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;반복 횟수가 단 한 번&lt;/b&gt;&lt;/span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;values의 첫 번째 요소인 6&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이 이미 주어진 콜백 함수의&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt; truthy 리턴&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;을 이뤄냈기 때문에&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt; some은 ture 값으로 반복이 종료&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;된 것&lt;/span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;기존에 공부한 forEach, map, filter와 다르게 독특한 점이 바로 이 부분이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;some 은 배열의 요소 개수만큼 콜백 함수를 실행하지 않을 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 상황에 따라 &lt;b&gt;효율을 관리&lt;/b&gt;하는데 충분히 이용될 수 있을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1664717308929&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const values = [];

const hasOver5 = values.some((currentElement, index, currentArray) =&amp;gt; {
    console.log(`요소: ${currentElement}`);
    console.log(`index: ${index}`);
    console.log(currentArray);
      
    return currentElement &amp;gt; 5;
});

console.log('hasOver5');
console.log(hasOver5); // ?&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 요소가 아무것도 없는 &lt;b&gt;빈 배열에서 some 메서드를 호출&lt;/b&gt;하면 어떻게 될까?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1592&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpmQmk/btrNxa9iMYx/9d5aqGKpVSkh5U30kVuKok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpmQmk/btrNxa9iMYx/9d5aqGKpVSkh5U30kVuKok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpmQmk/btrNxa9iMYx/9d5aqGKpVSkh5U30kVuKok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpmQmk%2FbtrNxa9iMYx%2F9d5aqGKpVSkh5U30kVuKok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;54&quot; data-origin-width=&quot;1592&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 false, 그리고 콜백 함수는 한 번도 실행되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 만약 undefined 나 null 요소가 들어가면 어떻게 될까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;values를 &lt;b&gt;&lt;i&gt;[null, undefined]&lt;/i&gt;&lt;/b&gt;로 바꿔서 실행해봤다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/V1wAf/btrNv0TWCsP/hyJTvb3j3ng91W6AestpVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/V1wAf/btrNv0TWCsP/hyJTvb3j3ng91W6AestpVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/V1wAf/btrNv0TWCsP/hyJTvb3j3ng91W6AestpVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FV1wAf%2FbtrNv0TWCsP%2FhyJTvb3j3ng91W6AestpVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;146&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;362&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 false, 그리고 콜백 함수는 null 과 undefined 모두 요소로 인식해서 콜백함수는 2번 실행이 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 마지막으로 요소 3개짜리 Array를 만들어서 실행하면 어떻게 될까?&lt;/p&gt;
&lt;pre id=&quot;code_1664717715031&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const values = new Array(3);

const hasOver5 = values.some((currentElement, index, currentArray) =&amp;gt; {
    console.log(`요소: ${currentElement}`);
    console.log(`index: ${index}`);
    console.log(currentArray);
      
    return currentElement &amp;gt; 5;
});

console.log('hasOver5');
console.log(hasOver5); 
console.log(values);
console.log(values.length);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WldUz/btrNyF87rKP/YoALFdx4FBJm41gaJNH2J0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WldUz/btrNyF87rKP/YoALFdx4FBJm41gaJNH2J0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WldUz/btrNyF87rKP/YoALFdx4FBJm41gaJNH2J0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWldUz%2FbtrNyF87rKP%2FYoALFdx4FBJm41gaJNH2J0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;95&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 false 그대로지만, &lt;span style=&quot;color: #ef5369;&quot;&gt;배열의 길이(values.length)가 분명히 3 임에도 불구하고 콜백 함수는 한 번도 실행되지 않았다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>프로그래밍 이야기/JavaScript 공부</category>
      <category>Array</category>
      <category>Javascript</category>
      <category>javascript some</category>
      <category>js</category>
      <category>SOME</category>
      <category>some js</category>
      <category>some 메서드</category>
      <category>메서드</category>
      <category>배열</category>
      <category>배열 메서드</category>
      <author>BigTop</author>
      <guid isPermaLink="true">https://bigtop.tistory.com/77</guid>
      <comments>https://bigtop.tistory.com/77#entry77comment</comments>
      <pubDate>Sun, 2 Oct 2022 22:38:55 +0900</pubDate>
    </item>
  </channel>
</rss>