[Toy Projects] 팁 계산기

Frontend Mentor - tip calculator app 

 


동작설명

 

bill(가격), select tip%(팁 퍼센테이지), Number of people(사람 수)을 입력/선택하면 팁값(가격/사람수*(팁퍼센트/100))과 본인이 내야하는 전체 금액(음식값(가격/사람수)+팁값)을 입력과 동시에 실시간으로 계산해준다. 팁 값과 전체 금액은 소수점 이하 2자리로 표시.

 Number of people(사람 수)의 경우 입력하지 않으면 한 명(1)으로 계산되지만 0을 입력하면 입력창의 테두리가 붉게 변하며 can't be zero라는 안내문구가 뜬다.

RESET버튼을 누르면 모든 입력값이 초기화된다.

bill을 제외한 select tip%과 number of people 은 입력하지 않아도 작동한다 (bill을 입력하지 않으면 전체 금액과 팁 값 모두 0달러로 표시).

 

 

사용스택


html, css, javascript


결과물

 

 

팁 계산기

 

팁 계산기 동작하는 모습 gif 파일

 

값을 입력/선택하면 오른쪽 화면에 계산된 값이 실시간으로 출력된다.

 

에러화면

0을 입력하면 경고 문구 출력

 

Demo

https://angrydoggaebi.github.io/FrontendMentor-Tip-calculator-app-main/

 

Frontend Mentor | Tip calculator app

 

angrydoggaebi.github.io

데스크탑으로 접속하면 이곳에서 내가 만든 팁 계산기를 직접 사용해볼 수 있다. 

 

 

고민했던 부분과 해결방법

 

1. 일단 입력하는 순간 바로 출력하려고 하니 계산식이 생각보다 복잡했다. 입력해야하는 bill, select tip%, number of people 3가지 중 하나만 입력한 경우, 2개만 입력한 경우, 모두 입력한 경우를 전부 예상해야 했을 뿐 아니라 입력했다가 지우는 경우, 0을 입력하는 경우, 버튼 대신 직접 입력하는 경우 등 고려해야 할 변수가 상당히 많았다. 

입력했다 지우는 경우 같은 생각지 못한 변수는 직접 이런저런 숫자를 넣어보며 문제가 있는 부분을 발견할 때마다 고민하고 수정하는 방향으로 진행했다. 

 

 

2. 이것저것 만지다보니 입력한 숫자를 삭제하면 0(=null)으로 반환된다는 것을 알았는데, 0을 입력한 경우와 빈 칸인 경우를 구분하기 위해 정규식을 이용해 숫자 체크와 공백 체크를 했다. 여기서 재미있었던 점은 숫자 체크를 위한 정규식에 .을 추가하면 소수점 이하까지도 체크가 가능했다는 것이다.

let check = /^[0-9.]+$/; //숫자체크(실수 가능)
var blankCheck = /^\s+|\s+$/g; // 공백 체크

 

 

3. 또 다른 문제는 select tip % 부분에서 원하는 팁 퍼센테이지를 선택한 후 마음이 바뀌어 custom으로 직접 원하는 숫자를 입력하고 싶어진 경우에 있었다. custom으로 숫자를 입력해도 한 번 누른 버튼의 클릭 상태 디자인이 계속 활성화되어있는 부분이었다. 이 부분은 이것저것 시도해보느라 고민도 많이 하고 시간도 굉장히 오래 걸렸는데, custom에 onclick을 걸어 for문으로 모든 버튼의 체크 상태를 false로 바꾸는 함수를 만들어 실행하는것으로 해결했다. 

// 체크된 ladio버튼 초기화
    var ladioReset = document.getElementsByName('btn');
    for(var i = 0; i<5; i++){
        ladioReset[i].checked = false;

(구현하고나서 보면 별 것 아닌데 시간을 많이 써버려 속상...)

 

 

4. 마지막으로 Number of people에 0을 입력하면 안내 문구와 함께 입력창의 테두리를 빨갛게 바꾸는 부분이 구현에 고전했다. 이 부분이 어려웠던 이유는 :focus 라는 의사 클래스의 상태를 변경해야했기 때문이다. 기본 상태는 유지하고, 창을 클릭한 경우(:focus상태)만 변경하려니 의사클래스는 dom이 아니라서 javascript로 속성을 변경할 수 없다고 한다.

 

이 부분은 의사클래스의 상태에 직접 변화를 주는 대신 class를 바꿔버리는 방법을 선택했다. css를 기본class일 때와 기본 class:focus 일 때(테두리 초록), 변화된 class일 때와 변화된 class:focus일 때(테두리 빨강) 4개를 만들어두고 창에 0을 입력하는 순간 javascript에서 class를 바꿔주면 같은 id에 변화된 class의 속성이 적용된다. 

 

이 때 중요한 것은 class를 다시 되돌리는 함수도 만들어 적절한 위치에 넣어주어야 한다는 것이다. 그래야 다시 숫자를 입력했을 때 원래의 focus 상태로 되돌릴 수 있다.

//Number of people 창에 0입력시 error 활성화
function enableZeroErrorOfNumOfPeople(){
    //0입력시 클래스명 바꿔서 의사클래스 :focus를 변화
    document.getElementById('peopleNum').className = "Error";
    //안내문구 출력
    document.getElementById('cannotZero').innerHTML = "can't be zero";
};
//Number of people 창 error 비활성화
function disableZeroErrorOfNumOfPeople(){
    //0입력때 바꾼 클래스 되돌리기
    document.getElementById('peopleNum').className = "peopleNum";
    //0입력때 출력한 안내 문구 없애기
    document.getElementById('cannotZero').innerHTML = "";
};

 

 

 

아쉬운 점

 

1. vanilla js만으로 구현하고싶었는데 값을 실시간으로 가져오는 jquary 함수

$("#id").on("propertychange change keyup paste input", function() {}

를 javascript로 구현하는 방법을 찾지 못해 이 부분을 jquary로 작성한것이 아쉽다.

 

2. 처음 javascript를 배울 때 초보자는 var로 변수를 할당하길 추천받아 지금까지 대부분의 변수를 var로 할당해왔다. 그런데 이번에 조금 복잡한 스크립트를 짜면서 같은 변수명에 새로운 값을 할당할 수 있는 var의 특징이 조금 불편하게 느껴졌다. 이리저리 계산식을 옮기고 붙이고 하다보면 같은 이름의 변수를 두 번 만들어버리는 경우가 생겼다. 

 

변수 중복 선언의 불편함을 느낀 이번 기회에 변수를 확실하게 공부하여 다음 프로젝트때부턴 변수의 스코프를 최대한 줄일 수 있는 방식으로 선언하도록 노력해야겠다.

 

3. 화면의 크기에 맞춰 계산기의 모양이 변하는 반응형 웹 화면으로 만들고싶었는데 이번엔 만들지 못했다. 

 

 

후기

 

하나를 만들 때 마다 많은걸 배운다. 정말 많이 배운다. 그리고 만들면 만들수록 정교하고 아름답게, 완벽하게 만들고싶은 마음이 커진다. 이번에도 bill, select tip%, number of people 3가지를 전부 입력받은 후 결과를 출력하면 간단했을 것을 실시간으로 받겠다고 엄청 고생을 했다. 하지만 잘하고싶은 욕심은 사람을 성장시킨다. 지금 욕심나는 부분은 동적 화면이다. 이 부분도 잘 할 수 있도록 더 연구해봐야겠다.

 

github 주소 : https://github.com/AngryDoggaebi/FrontendMentor-Projects

 

 

 

 


 

프론트엔드 멘토에서는 프론트엔드를 공부하는 사람들이 다양한 프로젝트에 도전해 볼 수 있도록 단계별 아이디어와 디자인 가이드를 제공해준다. 디자인 파일과 아이디어를 보고 실제로 동작하도록 구현해보면 된다. 답안은 제공하지 않는다. 

Frontend Mentor 주소:

https://www.frontendmentor.io/home