-
Node.js로 사칙연산 계산기를 만들어봐요 - 3편(계산기 완성하기)프로그래밍 언어/Node.js(노드) 2018. 11. 11. 18:08
2편에 이어서 이제 핵심인 계산기 화면과 계산기 로직을 통해 계산기를 완성해보겠습니다!
팝업창으로 호출한 calculator/calculatorPop url을 받기위해서 calculator 모듈을 만들겠습니다.
router 폴더 밑에 아래처럼 폴더와 js파일을 만들어주세요.
calculator.js에 아래의 코드를 작성해주세요.
var express = require('express')var router = express.Router()router.get('/calculatorPop', function(req,res){res.render('calculator.ejs')})module.exports = router;calculatorPop이란 호출이 들어오면(get으로 받습니다) calculator.ejs로 보냅니다.
이때 res.render 메서드를 사용합니다.
마지막에 외부에서도 사용 가능하도록 module.exports 잊지 마시구요!
ejs를 템플릿 엔진으로 사용한다고 했었던 것 기억나시나요 ? views 폴더를 만들어두면 자동으로 views 아래 ejs파일들을 읽습니다.
아래의 경로로 calculator.ejs를 만들어주세요.
calculator.ejs 화면을 먼저 만들어볼게요.
<!DOCTYPE html><html><head><meta charset="utf-8" /><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"><script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script><title>계산기</title></head><body><div class="container bg-danger" style="height:100%"><div class="form-group"><input class="form-control" type="text" id="textBox" style="text-align:right; width:100%"placeholder="0" readonly/></div><div class="form-group" style="text-align:center"><button class="btn btn-primary" style="width:23%" value="7" onclick="typing('7')">7</button><button class="btn btn-primary" style="width:23%" value="8" onclick="typing('8')">8</button><button class="btn btn-primary" style="width:23%" value="9" onclick="typing('9')">9</button><button class="btn btn-info" style="width:23%" value="+" onclick="typing('+')">+</button></div><div class="form-group" style="text-align:center"><button class="btn btn-primary" style="width:23%" value="4" onclick="typing('4')">4</button><button class="btn btn-primary" style="width:23%" value="5" onclick="typing('5')">5</button><button class="btn btn-primary" style="width:23%" value="6" onclick="typing('6')">6</button><button class="btn btn-info" style="width:23%" value="-" onclick="typing('-')">-</button></div><div class="form-group" style="text-align:center"><button class="btn btn-primary" style="width:23%" value="1" onclick="typing('1')">1</button><button class="btn btn-primary" style="width:23%" value="2" onclick="typing('2')">2</button><button class="btn btn-primary" style="width:23%" value="3" onclick="typing('3')">3</button><button class="btn btn-info" style="width:23%" value="*" onclick="typing('*')">X</button></div><div class="form-group" style="text-align:center"><button class="btn btn-primary" style="width:23%" value="0" onclick="typing('0')">0</button><button class="btn btn-light" style="width:23%" id="clear">C</button><button class="btn btn-warning" style="width:23%" id="calculation" value="=">=</button><button class="btn btn-info" style="width:23%" value="/" onclick="typing('/')">/</button></div></div></body></html>부트스트랩을 이용해 화면을 구성했고, 버튼을 눌릴 때마다 typing이라는 함수를 타도록 만들었습니다.
input 화면은 버튼을 통해서만 계산할 수 있도록 했습니다.
main.html에서 계산기 버튼을 눌리면 디자인된 계산기 화면을 볼 수 있습니다.
이제 계산기에 로직을 추가해보겠습니다.
<!DOCTYPE html><html><head><meta charset="utf-8" /><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"><script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script><title>계산기</title></head><body><div class="container bg-danger" style="height:100%"><div class="form-group"><input class="form-control" type="text" id="textBox" style="text-align:right; width:100%"placeholder="0" readonly/></div><div class="form-group" style="text-align:center"><button class="btn btn-primary" style="width:23%" value="7" onclick="typing('7')">7</button><button class="btn btn-primary" style="width:23%" value="8" onclick="typing('8')">8</button><button class="btn btn-primary" style="width:23%" value="9" onclick="typing('9')">9</button><button class="btn btn-info" style="width:23%" value="+" onclick="typing('+')">+</button></div><div class="form-group" style="text-align:center"><button class="btn btn-primary" style="width:23%" value="4" onclick="typing('4')">4</button><button class="btn btn-primary" style="width:23%" value="5" onclick="typing('5')">5</button><button class="btn btn-primary" style="width:23%" value="6" onclick="typing('6')">6</button><button class="btn btn-info" style="width:23%" value="-" onclick="typing('-')">-</button></div><div class="form-group" style="text-align:center"><button class="btn btn-primary" style="width:23%" value="1" onclick="typing('1')">1</button><button class="btn btn-primary" style="width:23%" value="2" onclick="typing('2')">2</button><button class="btn btn-primary" style="width:23%" value="3" onclick="typing('3')">3</button><button class="btn btn-info" style="width:23%" value="*" onclick="typing('*')">X</button></div><div class="form-group" style="text-align:center"><button class="btn btn-primary" style="width:23%" value="0" onclick="typing('0')">0</button><button class="btn btn-light" style="width:23%" id="clear">C</button><button class="btn btn-warning" style="width:23%" id="calculation" value="=">=</button><button class="btn btn-info" style="width:23%" value="/" onclick="typing('/')">/</button></div></div><script>function typing(inputValue){var originalText = $('#textBox').val();if(inputValue == '+' || inputValue == '-' || inputValue == '*' || inputValue == '/'){// 연속된 기호를 못 붙이기 위함var isNumber = parseInt(originalText.charAt(originalText.length-1));if(isNaN(isNumber)){return;}}$('#textBox').val(originalText+inputValue);}</script></body></html>기존의 inputText에서 값을 가져와서 덧붙여주는 역할을 수행합니다. 연속된 기호를 못 붙이기 위함이라는 뜻이
12++13이나 14*+12 등이 될 수 없도록 연산 기호들이 연속으로 올 수 없도록 합니다. 그게 아니라면 연속된 텍스트를 입력할 수 있습니다.
부가적인 기능을 만들어볼게요. 'C'를 눌리면 초기화하고 백스페이스를 눌리면 입력된 값이 지워지도록 해보겠습니다.
<script>$(document).ready(function(){$('#clear').on("click", function(){$('#textBox').val('');})$(document).keydown(function(event){if(event.keyCode == '8'){var originText = $('#textBox').val();$('#textBox').val(originText.substring(0, originText.length-1));}})})function typing(inputValue){var originalText = $('#textBox').val();if(inputValue == '+' || inputValue == '-' || inputValue == '*' || inputValue == '/'){// 연속된 기호를 못 붙이기 위함var isNumber = parseInt(originalText.charAt(originalText.length-1));if(isNaN(isNumber)){return;}}$('#textBox').val(originalText+inputValue);}</script>jQuery를 사용하니까 훨씬 이벤트 만들기가 편한데요. id가 clear라는 버튼을 눌리면 textBox의 값이 ''로 초기화됩니다.
$(document).keydown은 키패드 이벤트인데요. 백스페이스는 KeyCode가 8입니다. 그래서 백스페이스를 눌렀을 경우,
텍스트박스의 값이 뒷자리부터 하나씩 지워집니다.
이제 '='을 눌렀을 때 Node 서버에서 입력된 값들을 계산 할거에요. 계산 결과는 비동기로 보여주는게 더 깔끔할 것 같아서 ajax로 처리했습니다.
$(document).ready(function(){$('#calculation').on("click", function(){var parameter = $('#textBox').val();$.ajax({type: 'POST',url: '/calculator/calculatorPop',data: {inputString : parameter},success: function(result){if(result.calculationOutput == '0'){$('#textBox').val('');}else{$('#textBox').val(result.calculationOutput);}},error: function(err){console.log('ajax error')}})})$('#clear').on("click", function(){$('#textBox').val('');})$(document).keydown(function(event){if(event.keyCode == '8'){var originText = $('#textBox').val();$('#textBox').val(originText.substring(0, originText.length-1));}})ajax로 inputString이라는 key값으로 textBox값을 담아 파라미터로 던집니다. url은 같은 url로 던지지만, http 메서드가 달라요.
POST 방식으로 값을 던집니다. 값을 가공할거니까요?! 서버에서 calculationOutput으로 결과값을 담아 던질건데, 그 값이 0이라면 초기화 시켜버리고, 다른 계산된 값이라면 결과 값을 textBox에 값을 넣어주는 거죠.
자 그럼 server에서 해당 url을 만들고 파라미터를 받고 결과 값을 리턴해줄 수 있는 메서드를 만들어보겠습니다.
다시 calculator.js로 갑니다. 설명은 주석으로 대신합니다. post 방식으로 받기 위해 router.post를 사용합니다.
var express = require('express')var router = express.Router()router.get('/calculatorPop', function(req,res){res.render('calculator.ejs')})router.post('/calculatorPop', function(req, res){var inputText = req.body.inputString; // 넘어온 파라미터 텍스트if(isNumber(inputText.charAt(inputText.length-1))== 'false'){ // 마지막에 숫자가 아닌 부호가 들어오면 잘라줌inputText = inputText.substring(0, inputText.length-1);}var appendNumber = ''; // 자릿수를 문자열로 조합해 완전한 수로 만들어줌var calArray = new Array(); // 숫자와 기호로 이루어진 배열var arrayCount = 0; // calArray의 인덱스for(var i=0; i<inputText.length; i++){var oneCharater = inputText.charAt(i);if(isNumber(oneCharater) == 'true' || (i== 0 && oneCharater == '-')){ // 입력된 값이 숫자라면 더해줌// 아니면 첫번째 숫자 결과값이 음수일 경우,}else{calArray[arrayCount++] = appendNumber; // 연산 기호가 나왔다면 앞의 appendNumber을 대입calArray[arrayCount++] = oneCharater; // 연산 기호를 담아줌appendNumber = ''; // 초기화}}calArray[arrayCount] = appendNumber; // 연산 기호 다음, 마지막으로 들어온 appendNumber을 대입arrayCount = 1; // 연산 기호가 있는 인덱스를 가리킴var calculationOutput = 0; // 리턴될 결과값/** arrayCount는 연산 기호가 있는 위치를 가리킨다. 연산 기호가 배열의 마지막 값에 들어갈 수 없으므로* 배열의 길이보다 -1의 위치가 마지막 연산 기호가 있을 수 있는 위치이다.* ex) 1+3+4는 가능하지만 1+4+5+ 는 안됨.** 숫자가 올 수 있는 배열의 인덱스는 0,2,4,6으로 온다. 345*9+123을 보면 알 수 있다.* 똑같이 연산 기호는 1,3,5 홀수의 위치만 올 수 있다.*/while(arrayCount < calArray.length){switch(calArray[arrayCount]){case '+':if(arrayCount == 1){ // 첫 연산 기호일 경우 앞의 숫자와 뒤에 오는 숫자를 같이 계산해준다.calculationOutput = parseInt(calArray[arrayCount-1])+parseInt(calArray[arrayCount+1]);}else{ // 첫 연산기호가 아닐 경우는 이제까지 계산된 결과에 대해서 연산을 수행하면 된다.calculationOutput += parseInt(calArray[arrayCount+1]);}break;case '-':if(arrayCount == 1){calculationOutput = parseInt(calArray[arrayCount-1])-parseInt(calArray[arrayCount+1]);}else{calculationOutput -= parseInt(calArray[arrayCount+1]);}break;case '*':if(arrayCount == 1){calculationOutput = parseInt(calArray[arrayCount-1])*parseInt(calArray[arrayCount+1]);}else{calculationOutput *= parseInt(calArray[arrayCount+1]);}break;case '/':if(arrayCount == 1){calculationOutput = parseInt(calArray[arrayCount-1])/parseInt(calArray[arrayCount+1]);}else{calculationOutput /= parseInt(calArray[arrayCount+1]);}break;}arrayCount += 2; // +2를 통해서 숫자는 건너뛰고 연산 기호만 비교할 수 있다.}var result = {};result.calculationOutput = calculationOutputres.json(result); // json형태로 결과 값을 리턴한다.})/** 입력된 값이 숫자인지 문자인지 판별 */function isNumber(numOrString){var output = parseInt(numOrString)if(isNaN(output)){ // 숫자가 아니면 parseInt를 수행할 경우 NaN 결과 값을 내뱉는다.return 'false';}return 'true';}module.exports = router;그럼 결과 값을 return해주는 모습을 볼 수 있습니다.
->
그런데 문제는 결과값이 한 번 나오고 숫자를 입력하면 결과값에 합쳐진다는 것이죠 ㅠㅠ위의 결과 값에 3을 눌렸더니 17 뒤에 텍스트가 붙으면서 173이 되네요 ㅠㅠ?? 이러면 안되겠죠.
결과를 한 번 받아봤다면, 숫자를 눌릴 경우 초기화되면서 새로운 값이 들어가고, 연산 기호를 눌리면 기존이 결과값에 계산이 되도록 만들어볼게요~!
전 flag를 이용했습니다.
<script>var resetFlag = 'true' // =을 클릭하고 새로할 때는 새로운 값이 입력되게 하려고 'false'면 리셋을 시켜줘야함$(document).ready(function(){$('#calculation').on("click", function(){var parameter = $('#textBox').val();$.ajax({type: 'POST',url: '/calculator/calculatorPop',data: {inputString : parameter},success: function(result){if(result.calculationOutput == '0'){$('#textBox').val('');}else{$('#textBox').val(result.calculationOutput);resetFlag = 'false';}},error: function(err){console.log('ajax error')}})})$('#clear').on("click", function(){$('#textBox').val('');})$(document).keydown(function(event){if(event.keyCode == '8'){var originText = $('#textBox').val();$('#textBox').val(originText.substring(0, originText.length-1));}})})function typing(inputValue){var originalText = $('#textBox').val();if(inputValue == '+' || inputValue == '-' || inputValue == '*' || inputValue == '/'){var isNumber = parseInt(originalText.charAt(originalText.length-1));if(isNaN(isNumber)){return;}}if(resetFlag== 'false'){ // '='을 클릭하고 값을 리셋해주기 위해서resetFlag = 'true';if(!isNaN(parseInt(inputValue))){ // 숫자의 경우 리셋, 기호가 들어오면 계산 진행$('#textBox').val(inputValue);return;}}$('#textBox').val(originalText+inputValue);}</script>전역변수로 사용할 수 있게 script 밑에 resetFlag라는 변수를 만들었습니다. resetFlag가 'false'라면 값을 리셋을 해주어야한다는 표시입니다.
ajax 결과를 받아왔을 때 resetFlag를 false로 만듭니다. 한 번 연산이 수행되었다는 뜻이죠.
연산이 수행되었고 새로운 버튼을 눌렸을 때 resetFlag=='false'를 타겠죠?
그럼 다음 연산을 위해 flag값은 다시 true로 돌려놓습니다. 그리고 새로 입력된 값이 숫자면 초기화 시켜서 새로운 계산이 될 수 있도록 만듭니다.
하지만 연산 기호가 들어오면 진행되었던 결과 값에 계속해서 연산을 수행할 수 있도록 만듭니다.
그럼 아까와 똑같은 방식으로 진행해본 사진입니다.
->
->
이 계산기의 단점은 textBox에 +, *, /, - 연산 표시가 모두 되지만 앞에서 부터 쭉 연산을 수행하기 때문에 곱셈이나 나눗셈이 문자열 뒤에 들어왔다고 해서 먼저 계산되지는 않아요.
Node 공부를 하기 위해서였기 때문에 개선을 고려하고 있진 않습니다. Node로 서버와 클라이언트단을 모두 공부해볼 수 있던 기회였던 것 같습니다!!
포스팅 작성하는데도 여간 시간이 많이 드는게 아니지만 좋은 복습이 된 것 같네요.
완성된 코드는 이쪽으로 들어오시면 확인하실 수 있습니다. 감사합니다.
'프로그래밍 언어 > Node.js(노드)' 카테고리의 다른 글
Node.js로 사칙연산 계산기를 만들어봐요 - 2편(첫 화면 띄우기) (0) 2018.11.11 Node.js로 사칙연산 계산기를 만들어봐요 - 1편(환경설정) (0) 2018.11.05