개요

웹 프로젝트의 입문이라고 할 수 있는 ‘쇼핑리스트 앱’ 프로젝트를 완성하였다. 기간은 하루 정도 걸렸던 것 같다. 아직은 프로젝트 경험이 부족해서 조금 헤메었지만 어렵지는 않았다. 그 동안 공부해왔던 DOM, 이벤트, 스크롤 제어 등의 기술을 적용해볼 수 있던 좋은 경험이었다.

결과물

1. 초기 화면

사용자가 데이터를 입력하기 전 초기 화면이다. 가능한 직관적으로 느껴지도록 디자인하였다. 상단의 헤더 부분에서는 오늘의 날짜를 표시해준다. 구매하려는 ‘물건 이름’과 ‘예상 가격’을 작성한 뒤에, 하단의 버튼을 클릭하여 입력할 수 있다. Enter key를 쳐서 데이터를 입력할 수도 있다. 이 부분은 form 태그를 통해 입력을 처리하였다.

쇼핑리스트 화면

2. 사용 화면

사용자가 데이터를 입력하면 표시되는 화면이다. ‘체크 아이콘’을 클릭하여 구매 여부를 관리할 수 있다. 그리고 ‘휴지통 아이콘’을 클릭하여 목록을 삭제할 수 있다. 또한, 예상 금액을 합산하여 밑 부분에 표시해주었다. 한편, ‘Check all’은 모든 목록을 체크하는 버튼이며, ‘Delete all’은 모든 목록을 삭제하는 버튼이다.

쇼핑리스트 화면

3. 데모 영상

영상 다운로드

코드 리뷰

전체 코드는 깃허브에서 확인해볼 수 있다. 클릭

그 중 중요하다고 생각한 코드를 리뷰해 보겠다.

  • 숫자만 입력받기
  // before
  const priceValue = estimatedPrice.value; 

input 태그를 통해 ‘예상 가격’을 입력받아 저장하는 코드이다. 나는 숫자만으로 이루어진 문자열(예: ‘2000’)을 입력받기를 기대하고 있다. 그런데 문제는, 사용자가 숫자와 문자가 혼용된 값(예: ‘2,000원’)을 입력할 수도 있다는 것이다. 이렇게 되면 입력값을 처리하는 것이 곤란해진다. 그래서 다음과 같은 코드를 추가하였다.

  // after
  const priceValue = estimatedPrice.value.replace(/[^0-9]/g, '');

입력값 중에서 숫자가 아닌 문자들을 모두 제거하는 것이다. 정규표현식과 replace 메서드를 조합하였다. 이 경우 기대와 어긋나는 값을 입력받더라도, 내가 원하는 데이터(숫자로 이루어진 데이터)를 추출할 수 있다. 물론, 이와는 달리 사용자에게 명시적인 경고를 줄 수도 있다. 하지만 이렇게 내부적으로 처리하는 것이 사용성 측면에서 더 좋다고 생각한다.

  • checkAll 버튼 구현
// before
checkAll.addEventListener('click', () => {
  let icons = [...document.querySelectorAll('.item__icon--check')];
  icons.forEach(icon => {
    icon.dispatchEvent(new Event('click'));
  });
});

checkAll 버튼은 모든 목록을 체크하는 버튼이다. 즉, 모든 목록의 check 아이콘을 활성화시켜야 했다. 직관적으로 생각하면, 모든 check 아이콘을 받아와서 click 이벤트를 발생시키면 될 것이다. 위의 코드가 바로 그렇다. 그러나 이 방식을 쓰면, 이미 활성화 된 check 아이콘은 비활성화되어 버린다. check 아이콘을 toggle 방식으로 만들었기 때문이다. 그래서 다음과 같이 코드를 수정하였다.

// after
checkAll.addEventListener('click', () => {
  let icons = [...document.querySelectorAll('.item__icon--check')];
  icons.forEach(icon => {
    if (!icon.className.includes('checked')) { // 수정한 부분
      icon.dispatchEvent(new Event('click'));
    }
  });
});

모든 check 아이콘을 받아오되, 활성화되지 않은(className에 checked가 없는) 아이콘만을 필터링하였다. 이를 통해 checkAll 버튼을 성공적으로 구현할 수 있었다.

마치며

매우 쉬운 난이도였지만 생각보다 배운 것이 많았다. 그 동안 책과 강의를 통해 이론적으로만 익혔던 기술(DOM, 이벤트, 배열 고차 함수 등)을 실습해볼 수 있던 좋은 경험이었다. 앞으로 더 어려운 프로젝트를 완성하기 위해 필요한 좋은 연습이었다고 생각한다.

한편, 아직은 경험이 부족해서 그런지 코드가 꽤 난잡하다. 더 경험을 쌓은 후에 코드를 리팩터링하여 효율적으로 개선해보겠다.

(제 글에서 틀린 것이 있다면 꼭 지적해 주세요. 감사히 배우겠습니다)