Experience/[Javascript] Age Calculator

[Javascript] Age Calculator ③Refactoring

winCow 2021. 4. 18. 01:16

1. 배경

이전에 만든 Age calculator를 몇 번 실행시켜본 결과, 다음과 같은 문제점이 발생했다.

 - 현재 날짜 기준으로 생일이 지난 경우, yyyy-year 값을 리턴해야 하는데 여전히 yyyy-year-1 값을 리턴했다.

 - 나이의 한도를 0~150세로 잡고 싶다.

 - innerHTML은 보안상의 이유로 쓰지 않는 것이 좋다고 한다.

 

 

2. Refactoring: parseInt(string, n)

const today = new Date();
const dd = String(today.getDate()).padStart(2, '0');
const mm = String(today.getMonth() + 1).padStart(2, '0');
const yyyy = today.getFullYear();
console.log(yyyy);
console.log(mm);
console.log(dd);

위 코드는 기존에 작성했던 현재 날짜를 불러오는 코드이다. 현재 날짜 기준으로 생일이 지났으나 yyyy-year-1 값을 리턴한 이유를 알아보고자 콘솔 창을 확인했는데, 위 코드에서 해결책의 실마리를 찾았다. 콘솔창에서 yyyy값은 파란색으로 출력되는데 mm, dd는 검은색으로 출력되었다. 여기서 힌트를 얻어 typeof로 확인해 보니 역시나 mm, dd는 문자열이었기 때문에 계산이 되지 않았던 것으로 파악된다.

 

if (month > mm || (month == mm && date > dd)) {
      return printAge(yyyy-year-1);
    } else {
      return printAge(yyyy-year);
    }

위 코드는 기존에 잘못 작성했던, 만 나이를 계산하는 기능이다. 위 코드에서, mm, dd는 문자열 타입이었기 때문에 조건과 무관하게 printAge(yyyy-year-1)을 반환한 것 같다.

 

const today = new Date();
const dd = parseInt(String(today.getDate()).padStart(2, '0'), 10);
const mm = parseInt(String(today.getMonth() + 1).padStart(2, '0'), 10);
const yyyy = today.getFullYear();

function calculateAge(dateValue) {
  const { year, month, date } = dateValue;
  const yearNum = parseInt(year, 10);
  const monthNum = parseInt(month, 10);
  const dateNum = parseInt(date, 10);
  if (monthNum > mm || (monthNum == mm && dateNum > dd)) {
    return printAge(yyyy-yearNum-1);
  } else {
    return printAge(yyyy-yearNum);
  }
}

이를 해결하기 위해 위와 같이 parseInt(string, n) 매소드를 이용하여 문자열을 숫자로 바꿔 주었다. parseInt의 디폴트는 10진법이 아니기 때문에, 10진법을 사용하려면 n에 반드시 10을 입력해 주어야 한다.

 

 

3. Refactoring: 0 =< age =< 150

function calculateAge(dateValue) {
  const { year, month, date } = dateValue;
  const yearNum = parseInt(year, 10);
  const monthNum = parseInt(month, 10);
  const dateNum = parseInt(date, 10);
  if (yyyy-yearNum-1 > 150) {
    return alert("굉장히 오래 사셨네요!");
  } else if (yyyy-yearNum-1 < 0) {
    return alert("미래에서 오셨네요!")
  } else {
    return realAge();
  }

  function realAge() {
    if (monthNum > mm || (monthNum == mm && dateNum > dd)) {
      return printAge(yyyy-yearNum-1);
    } else {
      return printAge(yyyy-yearNum);
    }
  }
}

일단은 위와 같이 조건문을 하나 더 만들어 나이의 범위를 0~150으로 제한했다. 그러나, 이 방식으로 월, 일까지 제한하려고 하면 코드가 너무 복잡해질 것 같다. 다른 방법이 있는지 찾아볼 필요가 있다. 

 

 

4. Refactoring: createElement & appendChild()

function printAge(age) {
  const resultContainer = document.querySelector('.result');
  const createP = document.createElement('p');
  createP.innerText = `당신의 나이는 만 ${age}세입니다!`;
  console.log(createP);
  resultContainer.appendChild(createP);
}

innerHTML은 보안이 취약하므로 createElement와 appendChild를 활용하는 것이 좋다고 하여 바꿔 보았다. createElement는 태그를 생성하고, 여기에 innerText를 이용하면 태그의 내용을 작성할 수 있다. 태그가 삽입될 곳을 선택하고 .appendChild()를 이용하면 원하는 위치에 생성한 태그를 삽입할 수 있다. 그러나, 이 방식을 이용하면, 값을 입력할 때마다 태그가 추가되어 입력한 수만큼 결과 메시지가 출력된다. 

 

 

5. 보완점

어느 정도 개선했으나 다음과 같은 문제점이 발생했으므로 다시 수정이 필요하다.

 - 사용자가 입력할 수 있는 year, month, date의 범위를 실제 달력과 일치하게 제한해야 할 필요가 있다. 이 경우, 범위를 벗어나는 경우, 확인 버튼을 누르지 않아도 경고 메시지가 출력되도록 하고 싶다.

 - 사용자가 값을 입력하는 만큼 결과 메시지가 출력되는 문제를 해결해야 한다.

 - 값을 입력하여 제출할 때, 키보드의 enter를 입력해도 제출이 가능하도록 개선하고 싶다.