타이머 만들기 (with Typescript)

Bam·2023년 9월 5일
0

projects

목록 보기
4/4

⏱기획의도⏱

타입스크립트 문법을 어느정도 학습했으니 이제는 한 번 사용해보자 하고 예전에 자바스크립트로 만든 타이머 앱타입스크립트로 만들어 보기로 했습니다.

다만, 지금은 js -> ts 컨버팅을 하는 것이 목적이 아니기 때문에 결과물과 내용은 완전히 같지만, 기존 프로젝트 코드를 변환하는 것이 아니라 0부터 시작하기로 결정했습니다.


⏱프로젝트⏱

결과물

지난번이랑 다르게 이번엔 다크 모드에 관한 내용은 뺐습니다. 타입스크립트를 실전에 적용하는 것을 맛 봐보자 라는 것이 목표이기 때문에 핵심 기능들만 빠르게 제작했습니다.

거기에 더해 기존 코드에서 깨끗하지 못했다고 생각했던 부분들을 이번에 작성하면서 고쳐보게 되었습니다.

사용기술

  • HTML
  • CSS + Bootstrap
  • Typescript

기능 소개

기본적인 동작 소개는 자바스크립트 버전을 참조해주세요.

index.ts

import {startAndPauseButtonAction} from './Buttons/startAndPauseButtonAction';
import {resetButtonAction} from './Buttons/resetButtonAction';
import {getButtonElements} from './utils/getButtonElements';

document.addEventListener('DOMContentLoaded', () => {
  const [startAndPauseButton, resetButton] = getButtonElements();

  if (startAndPauseButton !== null) {
    startAndPauseButton.addEventListener('click', () => {
      startAndPauseButtonAction(startAndPauseButton);
    });
  }

  if (resetButton !== null) {
    resetButton.addEventListener('click', () => {
      resetButtonAction();
    });
  }
});

index.ts에서는 입력하고 버튼을 눌렀을 때, 이벤트들을 호출합니다.

이때 버튼 요소에 대해 null 타입이 아니라고 타입 좁히기를 수행한 후, 이벤트를 호출했습니다. 이때 각 버튼은 HTMLButtonElement 타입으로 정의됩니다.

getInputElement.ts

기존 코드에서는 시/분/초 입력 폼의 요소를 취하는 코드가 4~5개 파일에서 동일하게 계속 반복 되었습니다.

 const hour = document.getElementById('input-hour');
 const minute = document.getElementById('input-minute');
 const second = document.getElementById('input-second');

사용할 때마다 요소를 취득하는 것과 같은 코드가 계속해서 반복 되는 것이 별로 좋지 못하다고 생각되어 getInputElement라는 함수로 취득 하는 부분을 따로 분리했습니다.

export const getInputElements = (): HTMLInputElement[] => {
  const hourInputFormElement = <HTMLInputElement>document.getElementById('hour-input');
  const minuteInputFormElement = <HTMLInputElement>document.getElementById('minute-input');
  const secondInputFormElement = <HTMLInputElement>document.getElementById('second-input');

  return [hourInputFormElement, minuteInputFormElement, secondInputFormElement];
};

실제로 값을 사용할 때는 구조 분해 할당을 이용해서 사용했습니다.

  const [hourInputFormElement, minuteInputFormElement, secondInputFormElement] = getInputElements();

getButtonElements.ts

버튼 취득에 관한 코드도 역시 4~5개의 파일에서 계속해서 반복되어 사용되고 있었습니다. 그래서 시간 입력 폼 요소 취득과 동일하게 버튼 요소 취득도 함수로 분리한 후 구조 분해 할당을 이용하여 사용했습니다.

export const getButtonElements = (): HTMLButtonElement[] => {
  const startAndPauseButton = (<HTMLButtonElement>document.getElementById('startAndPauseButton'));
  const resetButton = (<HTMLButtonElement>document.getElementById('resetButton'));

  return [startAndPauseButton, resetButton];
};

getTimeInfo.ts

마찬가지로 시/분/초에 대한 정보도 계속해서 반복되는 코드이므로 함수로 분리했습니다. 거기에 더해 시/분/초 정보는 number 타입으로 활용되기 때문에 반환할 때 string타입에서 number 타입으로 변환해서 반환하고 있습니다.

export const getTimeInfo = () => {
  const hour = (<HTMLInputElement>document.getElementById('hour-input')).value;
  const minute = (<HTMLInputElement>document.getElementById('minute-input')).value;
  const second = (<HTMLInputElement>document.getElementById('second-input')).value;

  return [Number(hour), Number(minute), Number(second)];
};

checkInputValid.ts

기존 코드에서는 startAndPauseButtonAction에서 입력값이 유효한지 검사했었습니다. 하지만 그 방식은 모듈 자체를 복잡해보이게 만들고, 하나의 모듈에서 여러 일을 하므로 이 부분 역시 함수로 따로 분리했습니다.

import {getInputElements} from './getInputElements';

export const checkInputValid = (hour: number, minute: number, second: number): void => {
  if (Number.isNaN(hour) || Number.isNaN(minute) || Number.isNaN(second)) {
    const [hourInputFormElement, minuteInputFormElement, secondInputFormElement] = getInputElements();

    window.alert('유효한 입력값이 아닙니다.');

    hourInputFormElement.value = '';
    minuteInputFormElement.value = '';
    secondInputFormElement.value = '';
  }
};

소감

좋았던 점👍

  • 타입스크립트를 공부하고 처음으로 활용해보는 좋은 사례가 되었다.
  • 타입스크립트로 DOM을 조작하려니 엄청나게 많은 타입이 있음을 알게 되었다.

    DOM 요소 같은 경우 기존 자바스크립트에서는 사용하긴 하는데, 이 속성이 제대로 먹히는지 아닌지 실행이나 테스트에 가봐야 알았었던 기억이 많았다.
    하지만 타입스크립트를 이용하니 타입을 제대로 지정해 주어야함과 동시에 위와 같은 에러를 사전에 방지해주니 아주 걱정없이 프로그래밍 할 수 있었다. 물론 수많은 요소 타입이 있었기에 IDE가 알려주지 않았다면 상당히 골치를 썩였을 수도 있다.

  • 만족스럽게 기존 코드를 개선했다.

    어디까지나 주관적인 기준이긴 하지만 중복 코드를 제거하고, 로직을 더 좋게 변경하는 작업을 할 수 있는 계기가 되어서 더욱 좋았던 것 같다.

반성할 점👎

  • webpack 공부하자

    사실 이번 프로젝트는 배포에 실패했다. 그냥 깡으로 폴더 만들고 바로 작업을 했기 때문이다.
    알아서 모듈 설정이나, 빌드를 npm이나 ts 컴파일러가 잡아줄줄 알았는데 아니었다. 조사해보니, 웹팩을 통해 빌드를 하고 ~~ 그런 과정들을 거쳤어야 했는데 그러지 않았기 때문에 이런 일이 발생했다.
    최소한 보일러 플레이트라도 찾아서 썼으면 어땠을까 하는 생각이 들었다.

한편으로는 그동안 create-react-app이나 npm init의 작동 원리와 상세를 잘 모르고 작업했다는 이야기가 되기도 한다. 이건 반드시 반성하고 다시 처음으로 돌아가 이들을 연구해보아야겠다고 생각하게 되었다.

총평✍

이제 타입스크립트를 제대로 사용해볼 수 있겠다!라는 생각이 들게 만들어줬다. 하지만 그와 동시에 웹팩과 같은 개념들을 조금은 등한시 하고 있었다는 것도 깨닫게 되었다.

사실 그동안 해야지 해야지 생각은 하고 있었는데 이렇게 당해버리니까 공부의 필요성을 절실히 느끼게 되었다. (역시 사람은 당해봐야...?)

역시 무언가 하면 할 수록 배울거리가 늘어나는 개발의 세계는 심오하면서도 호기심을 자극해서 즐겁게 만들어주는 것 같다.

0개의 댓글