
┣─ assets/
│ ┣─ scripts/
│ │ ├─ app.js
│ │ └─ vendor.js
│ └─ styles/
│ └─ app.css
└─ index.html
app.jsconst defaultResult = 0;
let currentResult = defaultResult;
function add(num1, num2) {
const result = num1 + num2;
alert('The result is ' + result);
}
add(1, 2);
add(5, 5);
currentResult = (currentResult + 10) * 3 / 2 - 1;
let calculationDescription = `(${defaultResult} + 10) * 3 / 2 - 1`;
outputResult(currentResult, calculationDescription);
vendor.jsconst userInput = document.getElementById('input-number');
const addBtn = document.getElementById('btn-add');
const subtractBtn = document.getElementById('btn-subtract');
const multiplyBtn = document.getElementById('btn-multiply');
const divideBtn = document.getElementById('btn-divide');
const currentResultOutput = document.getElementById('current-result');
const currentCalculationOutput = document.getElementById('current-calculation');
function outputResult(result, text) {
currentResultOutput.textContent = result;
currentCalculationOutput.textContent = text;
}
app.css* {
box-sizing: border-box;
}
html {
font-family: 'Roboto', open-sans;
}
body {
margin: 0;
}
header {
background: #023d6d;
color: white;
padding: 1rem;
text-align: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
width: 100%;
}
#results,
#calculator {
margin: 2rem auto;
width: 40rem;
max-width: 90%;
border: 1px solid #023d6d;
border-radius: 10px;
padding: 1rem;
color: #023d6d;
}
#results {
text-align: center;
}
#calculator input {
font: inherit;
font-size: 3rem;
border: 2px solid #023d6d;
width: 10rem;
padding: 0.15rem;
margin: auto;
display: block;
color: #023d6d;
text-align: center;
}
#calculator input:focus {
outline: none;
}
#calculator button {
font: inherit;
background: #023d6d;
color: white;
border: 1px solid #023d6d;
padding: 1rem;
cursor: pointer;
}
#calculator button:focus {
outline: none;
}
#calculator button:hover,
#calculator button:active {
background: #084f88;
border-color: #084f88;
}
#calc-actions button {
width: 4rem;
}
#calc-actions {
margin-top: 1rem;
text-align: center;
}
index.html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Basics</title>
<link
href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="assets/styles/app.css" />
</head>
<body>
<header>
<h1>The Unconventional Calculator</h1>
</header>
<section id="calculator">
<input type="number" id="input-number" />
<div id="calc-actions">
<button type="button" id="btn-add">+</button>
<button type="button" id="btn-subtract">-</button>
<button type="button" id="btn-multiply">*</button>
<button type="button" id="btn-divide">/</button>
</div>
</section>
<section id="results">
<h2 id="current-calculation">0</h2>
<h2>Result: <span id="current-result">0</span></h2>
</section>
<script src="assets/scripts/vendor.js"></script>
<script src="assets/scripts/app.js"></script>
</body>
</html>
지금까지는 웹 페이지가 딱딱하게 굳어있는 것처럼 느껴졌을 거예요. 왜냐하면 우리가 app.js에 써놓은 코드는 페이지가 처음 열릴 때 그냥 쭉! 실행되고 끝나버렸거든요. 마치 책을 처음부터 끝까지 한번 읽는 것과 같아요. 중간에 우리가 뭘 누르거나 해도 아무 반응이 없었죠?
이제 이걸 바꿔볼 거예요! 우리가 원할 때만 콕! 찝어서 실행할 수 있는 특별한 코드를 만들 겁니다. 그게 바로 함수예요.
제가 함수를 "온디맨드 코드"라고 불렀죠? 마치 우리가 원하는 시간에 원하는 노래를 스트리밍 서비스에서 골라 듣는 것처럼, 필요할 때만 실행시킬 수 있는 코드 덩어리라는 뜻이에요.
함수는 이렇게 생겼어요.
function 인사하기(이름) {
console.log(이름 + "님, 안녕하세요!");
}
function 이라는 특별한 단어로 시작해요. "이제부터 함수를 만들 거야!"라고 알리는 거죠.인사하기)을 써요. 나중에 이 이름으로 이 함수를 불러서 실행할 수 있어요.() 안에는 매개변수 (이름)가 들어갈 수 있어요. 이건 마치 함수에게 주는 입력값 같은 거예요. 위 예시에서는 이름을 입력받아서 인사말을 만들어주겠죠? (매개변수가 없을 수도 있어요!){} 안에는 우리가 나중에 실행하고 싶은 코드들이 들어가요. 이걸 함수 본문이라고 불러요.함수가 정의되면 뭐가 달라질까요?
우리가 위처럼 함수를 만들어 놓기만 했을 때는, 그 안의 코드가 바로 실행되지 않아요! 마치 우리가 노래 제목을 저장해 놓기만 하고 아직 재생 버튼을 누르지 않은 것과 같아요.
대신, JavaScript는 이 함수를 "아, 이런 기능을 하는 코드가 있구나!" 하고 기억해 둬요. 마치 노래 목록에 추가해 놓는 거죠.
그럼 언제 실행될까요?
우리가 함수를 호출해야 실행돼요! 함수 이름 뒤에 괄호 ()를 붙여서 호출할 수 있어요.
인사하기("홍길동"); // "홍길동님, 안녕하세요!" 라고 콘솔에 출력됩니다.
인사하기("김철수"); // "김철수님, 안녕하세요!" 라고 콘솔에 출력됩니다.
만약 함수가 매개변수를 받는다면, 괄호 안에 실제로 사용할 값을 넣어줘야 해요. 위 예시에서는 "홍길동"이나 "김철수"처럼 이름을 넣어줬죠.
함수의 장점!
우리가 이미 사용하고 있는 함수!
우리가 vendor.js에서 봤던 outputResult(result, text)도 바로 함수예요!
function outputResult(result, text) {
currentResultOutput.textContent = result;
currentCalculationOutput.textContent = text;
}
이 함수는 계산 결과(result)와 설명(text)이라는 두 개의 입력값(매개변수)을 받아서, 웹 페이지의 특정 부분(#current-result, #current-calculation)의 내용을 업데이트하는 역할을 하죠?
그리고 app.js에서 아래 코드를 통해 이 함수를 호출하고 있었어요.
outputResult(currentResult, calculationDescription);
여기서 currentResult와 calculationDescription 안에 저장된 값들이 outputResult 함수에게 전달돼서, 그 값들이 화면에 표시된 거죠.
결론적으로, 함수를 사용하면 이제 우리도 웹 페이지를 훨씬 더 똑똑하고 상호작용이 가능하게 만들 수 있다는 거예요! 다음 단계에서는 우리만의 함수를 만들어서 계산기 버튼이 눌렸을 때 실제로 계산이 이루어지도록 바꿔볼 겁니다! 아주 신나겠죠? 😊
자, 우리가 지금까지 JavaScript의 기본적인 재료들(변수, 숫자, 글자 등)을 가지고 간단한 요리들을 만들어 봤어요. 화면에 결과도 띄울 수 있게 되었죠! 하지만 아직 우리 계산기는 "멍텅구리"예요. 왜냐하면 우리가 직접 코드에 "더하기 5 더하기 10은 15!" 이렇게 딱 정해놓은 결과만 보여주거든요. 마치 요리사가 미리 만들어 놓은 음식만 내놓는 식당 같아요. 우리가 "짜장면 주세요!"라고 주문해도 그냥 정해진 음식만 주는 거죠.
이제 우리 계산기를 "똑똑한 요리사"처럼 만들어 볼 거예요! 우리가 원하는 숫자를 입력하고, 원하는 버튼(더하기, 빼기 등)을 누르면, 그때 딱! 맞춰서 계산을 해주고 결과를 보여주는 거죠. 이렇게 하려면 우리가 아직 배우지 않은 아주 중요한 JavaScript 기능이 필요해요. 바로 함수(Function)입니다!
제가 함수를 "온디맨드 코드", 즉 "주문형 코드"라고 불렀죠? 이건 마치 우리가 식당에서 메뉴를 보고 "짜장면 하나 주세요!"라고 주문하면, 요리사가 그때 딱! 짜장면을 만들어 주는 것과 같아요. 우리가 원할 때만 콕! 찝어서 실행할 수 있는 코드 묶음이라는 뜻입니다.
함수는 왜 필요할까요?
지금까지 우리가 쓴 코드는 페이지가 처음 열릴 때 위에서부터 아래로 쭈욱 한 번 실행되고 끝이었어요. 마치 녹음된 테이프를 처음부터 끝까지 쭉 듣는 것과 같죠. 중간에 우리가 뭘 해도 멈추거나 다른 부분을 재생할 수 없었어요.
하지만 함수를 사용하면, 특정 작업을 하는 코드들을 하나의 이름으로 묶어놓고, 필요할 때마다 그 이름만 불러서 실행할 수 있게 돼요. 마치 리모컨의 특정 버튼을 누르면 원하는 기능(볼륨 높이기, 채널 바꾸기 등)이 실행되는 것과 같아요.
우리만의 "더하기" 함수 만들기!
자, 그럼 우리 계산기의 "더하기" 버튼을 누르면 입력한 숫자를 기존 결과에 더해주는 기능을 만들어 볼 거예요. 그러려면 두 개의 숫자를 더하는 역할을 하는 함수가 필요하겠죠?
함수를 만드는 방법은 아주 간단해요. app.js 파일에 다음과 같이 코드를 작성해 보세요. (어디에 작성하든 상관없어요! JavaScript는 똑똑해서 우리가 만든 함수를 알아서 찾아낸답니다. 하지만 보통은 코드의 윗부분이나 변수 선언 아래에 작성하는 게 보기 좋아요.)
// 더하기 기능을 하는 함수 만들기
function add(num1, num2) {
// 함수가 실행될 때 할 일들을 이 중괄호 안에 적습니다.
// num1과 num2를 더한 결과를 새로운 상자에 담기
const result = num1 + num2;
// alert 창으로 결과를 보여주기 (나중엔 화면에 보여줄 거예요!)
alert('결과는 ' + result + '입니다.');
}
함수 만들기, 하나씩 살펴보기!
function: 이건 "이제부터 함수를 만들 거야!"라고 JavaScript에게 알리는 특별한 키워드예요. 마치 "시작!" 버튼과 같아요.add: 이건 우리가 만든 함수의 이름이에요. 우리가 나중에 이 함수를 실행하고 싶을 때 이 이름을 사용할 거예요. 마치 리모컨의 "볼륨 업" 버튼처럼요. 여러분이 원하는 대로 이름을 지을 수 있지만, 이 함수가 무슨 역할을 하는지 잘 나타내는 이름을 짓는 게 중요해요. 예를 들어, 두 숫자를 더하는 함수니까 add나 addNumbers처럼요. giveMeTwoNumbers (두 숫자를 줘!)는 입력에 대한 설명만 있고 뭘 하는지는 모르겠죠? result (결과)도 마찬가지로 어떤 연산의 결과인지 알 수 없으니 좋은 이름은 아니에요.(num1, num2): 괄호 안에 있는 num1과 num2는 매개변수(parameter)라고 불리는 특별한 상자들입니다. 이건 마치 함수에게 주는 입력값이에요. "더하기"를 하려면 어떤 두 수를 더할지 알려줘야 하잖아요? 그래서 우리는 이 함수에게 num1이라는 첫 번째 숫자와 num2라는 두 번째 숫자를 받을 준비를 시킨 거예요. 마치 식당에서 "짜장면 하나랑 짬뽕 하나 주세요!"라고 주문하는 것과 같아요. 괄호 안이 비어있을 수도 있어요. 입력 없이 혼자서 작동하는 함수도 있답니다.{ ... }: 중괄호 {} 안에는 실제로 이 함수가 실행될 때 할 일들을 적습니다. 이걸 함수 본문(function body)이라고 불러요. 마치 식당의 주방과 같아요. 우리가 "짜장면 주세요!"라고 주문하면, 주방에서 면을 삶고, 소스를 만들고, 그릇에 담는 여러 가지 일련의 작업들이 일어나잖아요? 함수 본문 안에도 여러 줄의 코드를 작성해서 다양한 작업을 시킬 수 있습니다.const result = num1 + num2;: 함수 본문 안에서 우리는 num1과 num2에 들어온 값을 더해서 그 결과를 result라는 새로운 상수 상자에 담았어요. 이건 마치 주방에서 삶은 면과 만든 소스를 섞어서 새로운 짜장면을 만드는 과정과 같아요. 여기서 num1과 num2는 우리가 함수를 호출할 때 넣어줄 실제 숫자들을 임시로 담는 그릇이라고 생각하면 돼요. 이 num1과 num2는 함수 안에서만 사용할 수 있는 특별한 변수라서, 함수가 끝나면 사라져요.alert('결과는 ' + result + '입니다.');: 마지막으로, 우리는 alert()라는 내장 함수를 이용해서 계산 결과를 팝업창으로 보여줬어요. alert()는 JavaScript가 기본으로 제공하는 아주 편리한 함수랍니다. 마치 요리사가 완성된 짜장면을 우리 테이블에 가져다주는 것과 같아요. '결과는 ' + result + '입니다.'는 보여줄 메시지를 만든 거예요. result 상자에 담긴 계산된 숫자가 이 메시지 안에 합쳐져서 우리에게 보여지는 거죠. (나중에는 alert() 대신 웹 페이지의 특정 부분에 결과를 표시하도록 코드를 수정할 거예요.)함수 실행시키기! (함수 호출)
자, 우리가 맛있는 "더하기" 함수를 만들기만 했다고 해서 자동으로 실행되지는 않아요! 마치 우리가 짜장면 레시피를 가지고 있다고 해서 갑자기 짜장면이 눈앞에 나타나지는 않는 것과 같아요. 우리가 직접 요리사에게 "짜장면 하나 만들어 주세요!"라고 주문해야 짜장면이 만들어지듯이, 우리가 만든 함수도 호출(call)해야 실행됩니다.
app.js 파일의 맨 아래 (우리가 outputResult 함수를 호출했던 곳 아래)에 다음과 같이 코드를 추가해 보세요.
// 우리가 만든 add 함수를 실행해 봅시다!
add(5, 2); // add 함수에게 5와 2를 입력으로 줍니다.
add(10, -3); // 이번에는 10과 -3을 입력으로 줍니다.
함수 호출하는 방법!
우리가 만든 함수의 이름 (add)을 쓰고, 괄호 ()를 열고 닫고, 그 안에 이 함수가 필요로 하는 입력값(매개변수)들을 넣어주면 돼요. 여러 개의 입력값이 필요하면 쉼표 , 로 구분해서 넣어줍니다.
add(5, 2); 라고 쓰면, add 함수가 실행되면서 num1에는 5가 들어가고, num2에는 2가 들어가요. 그리고 함수 본문 안에서 5 + 2가 계산되어서 결과 7이 alert 창에 나타날 겁니다.add(10, -3); 라고 쓰면, 이번에는 num1에 10이, num2에 -3이 들어가서 10 + (-3)이 계산된 결과 7이 또 다른 alert 창에 나타날 거예요.이제 저장하고 index.html 파일을 웹 브라우저로 다시 열어보세요! 페이지가 처음 로드될 때 "결과는 3입니다." 와 "결과는 10입니다." 라는 alert 창이 먼저 뜰 거예요. 이건 우리가 app.js에서 add(1, 2); 와 add(5, 5); 라고 처음 함수를 호출했기 때문이에요. 그리고 우리가 새로 추가한 add(5, 2); 와 add(10, -3); 에 대한 alert 창도 차례대로 나타날 겁니다!
함수의 강력함!
우리가 만든 add 함수는 이제 우리가 원하는 숫자를 넣어서 원하는 만큼 여러 번 실행할 수 있어요! 마치 우리가 원하는 재료를 넣고 "짜장면 만들어 주세요!"라고 여러 번 주문할 수 있는 것처럼요. 매번 함수를 호출할 때마다, 그 안의 코드는 새로운 입력값을 가지고 독립적으로 실행됩니다.
다음 단계는?
아직 우리 계산기의 버튼을 눌렀을 때 이 add 함수가 자동으로 실행되지는 않아요. 그건 우리가 아직 이벤트 리스너(event listener)라는 특별한 기능을 배우지 않았기 때문입니다. 다음 모듈에서는 우리가 만든 "더하기" 함수를 웹 페이지의 "더하기" 버튼과 연결해서, 버튼을 클릭했을 때마다 우리가 입력한 숫자를 더해주는 진짜 상호작용하는 계산기를 만들어 볼 거예요! 정말 기대되지 않나요? 😊
우리가 작성하는 코드가 컴퓨터에게 명령을 내리는 언어라는 것은 이제 잘 아실 겁니다. 하지만 단순히 컴퓨터가 이해할 수 있는 코드와, 사람이 이해하기 쉽고 유지보수하기 좋은 코드를 작성하는 것 사이에는 큰 차이가 있습니다. 이번 시간에는 올바른 구문(syntax)을 지키는 것뿐만 아니라, 깔끔하고 읽기 쉬운 코드 스타일(code style)과 코딩 컨벤션(coding convention)을 따르는 것이 왜 중요한지, 그리고 어떻게 해야 하는지에 대해 자세히 알아보겠습니다.
1. 구문 오류 (Syntax Errors) vs. 가독성 있는 코드
구문 오류는 JavaScript 언어의 규칙을 어겼을 때 발생합니다. 마치 우리가 외국어를 말할 때 문법 규칙을 틀리면 의사소통이 안 되는 것과 같습니다. JavaScript 엔진은 구문 오류가 있는 코드를 이해하고 실행할 수 없습니다.
// 구문 오류 예시: 함수 정의에 매개변수 목록 괄호 () 가 없음
function greetUser {
alert('Hi there!');
}
위 코드는 function 키워드 뒤에 함수 이름이 오고, 그 뒤에는 반드시 매개변수 목록을 위한 괄호 ()가 있어야 합니다. 올바른 코드는 다음과 같습니다.
function greetUser() {
alert('Hi there!');
}
이 강의를 통해 우리는 JavaScript의 기본적인 문법 규칙 (함수 정의, 변수 선언 등)을 배우게 될 것입니다.
가독성 있는 코드는 문법적으로 올바르지만, 사람이 읽고 이해하기 쉬운 방식으로 작성된 코드를 의미합니다. 마치 잘 정리된 글이 읽기 편한 것처럼, 코드를 깔끔하게 작성하면 다른 개발자 (심지어 미래의 자신까지!)가 코드를 이해하고 수정하는 데 훨씬 수월합니다.
// 문법적으로 유효하지만 읽기 어려운 코드
function greetUser(){alert('Hi there!');}
let userName='Max';
let someResult = 5 + 10 - 3 + 22 - 10000 + 5.344 * 1200;
let someLongString = 'Hi, this is going to be a bit longer, ' + 'so maybe split it across multiple lines by ' + 'concatenating multiple strings!';
위 코드들은 JavaScript 엔진은 문제없이 실행할 수 있지만, 공백이나 줄 바꿈이 없어 어떤 부분이 어떤 역할을 하는지 한눈에 파악하기 어렵습니다.
2. 가독성을 높이는 방법
공백 (Whitespace), 줄 바꿈 (Line Breaks), 들여쓰기 (Indentation): 이 세 가지 요소는 코드의 구조를 시각적으로 나타내어 가독성을 크게 향상시킵니다. JavaScript 엔진은 이들을 무시하지만, 개발자에게는 코드의 논리적인 흐름을 보여주는 중요한 단서가 됩니다.
// 읽기 쉬운 코드
function greetUser() {
alert('Hi there!');
}
let userName = 'Max';
let someResult = 5 + 10 - 3 +
22 - 10000 +
5.344 * 1200;
let someLongString = 'Hi, this is going to be a bit longer, ' +
'so maybe split it across multiple lines by ' +
'concatenating multiple strings!';
= 주변에 공백을 넣어 변수 이름과 값을 명확히 구분합니다.긴 문자열 연결 시 주의사항: JavaScript에서 문자열 리터럴 (따옴표로 묶인 문자열)은 반드시 한 줄에 있어야 합니다. 다음과 같이 여러 줄에 걸쳐 작성하면 구문 오류가 발생합니다.
// 구문 오류! 문자열 리터럴은 한 줄에 있어야 합니다.
let someLongString = 'Hi, this is going to be a bit longer,
so maybe split it across multiple lines by
concatenating multiple strings!';
따라서 긴 문자열을 여러 줄로 표현하려면 문자열 연결 연산자 +를 사용해야 합니다.
세미콜론 (Semicolon): JavaScript에서 각 표현식(statement)의 끝에는 일반적으로 세미콜론 ; 을 붙여야 합니다. 이는 JavaScript 엔진에게 하나의 명령이 끝났음을 알려주는 역할을 합니다.
let message = 'Hello';
alert(message);
하지만 중괄호 {} 로 묶인 코드 블록 (예: 함수 정의, 객체 리터럴) 뒤에는 세미콜론을 붙이지 않는 것이 일반적인 컨벤션입니다.
function greetUser() {
alert('Hi there!');
} // 함수 정의 뒤에는 세미콜론을 붙이지 않는 것이 일반적입니다.
let person = {
name: 'Max',
age: 30
}; // 객체 리터럴 뒤에도 세미콜론을 붙입니다. (예외적인 경우!)
함수 정의 뒤에 세미콜론을 붙인다고 해서 오류가 발생하는 것은 아니지만, 대부분의 JavaScript 스타일 가이드에서는 이를 권장하지 않습니다.
3. 코딩 컨벤션 (Coding Conventions)
코딩 컨벤션은 개발자 커뮤니티에서 "약속"처럼 정해진 일련의 규칙들을 의미합니다. 이는 코드의 일관성을 유지하고, 여러 개발자가 함께 작업할 때 혼란을 줄이며, 코드 리뷰를 용이하게 합니다.
userName, totalAmount). 함수 이름은 동사로 시작하여 함수의 동작을 나타내는 것이 좋습니다 (예: greetUser(), calculateSum()).결론
올바른 구문을 지키는 것은 기본적인 필수 조건이며, 이를 통해 JavaScript 코드를 실행할 수 있습니다. 하지만 가독성 있는 코드 스타일과 코딩 컨벤션을 따르는 것은 협업의 효율성을 높이고, 코드 유지보수를 용이하게 하며, 더 나아가 더 나은 품질의 소프트웨어를 만드는 데 중요한 역할을 합니다. 처음에는 이러한 규칙들을 따르는 것이 번거롭게 느껴질 수 있지만, 꾸준히 연습하다 보면 자연스럽게 깔끔하고 이해하기 쉬운 코드를 작성하는 습관을 기를 수 있을 것입니다. 앞으로 우리가 작성할 코드에서도 이러한 점들을 염두에 두고 함께 노력해 봅시다!