일단 단어 외우고 문법을 외운 다음 언어를 배우는 방법은 어릴 적 영어를 배울 때 해봤으나 별로 효과적이진 않았다. 자바스크립트를 배울 땐 다른 방법을 써보자. 작은 프로젝트를 구현하며 필요한 문법을 그때 그때 익혀보자.
자바스크립트는 웹브로우저에서 작동되게 설계된 언어이다. 이를 웹브라우저 밖에서 동작시키기 위해선 별도의 환경 구축이 필요하다. 관련된 내용이 필요한 사람은 아래 링크를 참고하자.
훌륭한 블로그 링크
필자는 아무것도 모를 땐 숫자 비교 게임을 만든다. 이 아이디어는 Swift 강사로 유튜브에서 활동하고 있는 Chris Cheng의 영상에서 빌려왔다.
Starting The War Card Game App - Lesson 4 (2024 / SwiftUI)
우리는 탱크를 만들고 싶다. 여러 기능을 가진 멋진 프로그램을 만들고 싶다. 그러나 많은 교육자료들은 이 탱크를 위에서부터 아래로 순서대로 가르친다. 탱크를 만들고 싶어도 일단 굴러가는 킥보드부터 만들자. 그리고 자전거, 오토바이, 자동차처럼 탱크처럼 굴러가는 것들을 보다 탱크스럽게 만들자. 그리고 마지막에 우리가 원하는 탱크를 만들자.
우선 숫자를 무작위로 생성해야 한다. 구글링하니 아래의 함수가 나왔다.
Math.random()
"Cmd + 클릭"을 하면 d.ts 파일이 열린다. 여기서 함수의 파라미터, 리턴값, 개발자의 코멘트를 볼 수 있다.


코멘트를 보니 해당 함수는 0에서 1 사이의 랜덤한(pseudorandom, 의사 난수) 수를 반환한다고 한다.
실제로 확인해보자.

난수가 잘 생성되고 있다. 하지만 소숫점을 길게 보는 건 복잡하니 한 자리 수만 반환하게 하자.
// 소수 부분을 버리고 정수 부분을 반환한다.
Math.floor(숫자)
// 1. 난수의 정수 부분을 한 자리 수로 만들고
// 2. 정수 부분만 반환한다.
Math.floor(Math.random() * 10)

이제 컴퓨터와 사용자의 수를 각각 만들고 이를 프린트해보자. 숫자가 더 큰 쪽이 승자이다.

이번엔 사용자가 이겼다.
승자를 판단하려면 두 수를 비교를 해야 한다. 이때는 if문(if statement)를 사용하자. 기본적인 문법은 아래와 같다.
if (조건) {
만족될 때 실행할 코드
} else {
조건 위배 시 실행할 코드
}
이를 이용해 사용자의 숫자가 클 때와 그렇지 않을 때를 나누면 다음과 같다.
if (myNumber > cpuNumber) {
console.log("I won")
} else {
console.log("Cpu won")
}
하지만 이 경우 사용자와 컴퓨터의 수가 같더라도 컴퓨터가 이긴 것으로 처리된다. 비긴 상황을 만들려면 첫 번 째 조건이 위배된 다음 새로운 조건을 다시 따져야 한다.
if (myNumber > cpuNumber) {
console.log("I won")
} else if (myNumber === cpuNumber) else {
console.log("Drew")
} else {
console.log("Cpu won")
}

자바스크립트에선 등호를 이용한 표현이 세 가지가 있다.
1. 할당=
2. 타입 무시 비교==
3. 타입 고려 비교===
코딩을 할 땐 언제나 타입을 확정짓는 것이 좋다. 타입을 확정지으면
1. 기존 변수에 다른 타입을 할당하여 기존 코드와 충돌이 일어나는 일을 피할 수 있다.
2. 기존 코드를 살펴볼 때, 파라미터, 반환값의 타입을 보고 함수의 역할과 한계를 쉽게 떠올릴 수 있다.
예를 들어보자.
console.log("1" == 1) // prints true
console.log("1" === 1) // prints false
특정 변수를 비교한 뒤 방정식에 넣으려고 한다고 해보자. ==를 이용해 확인하면 string을 number로 착각하는 일이 발생할 수 있다. 이를 막기 위해 비교 연산자는 꼭 세 글자로 쓰자.
=== !==프로그램을 실행했더니 내가 졌다. 그래서 다시 실행했다. 또 졌다. 다시 한 번 실행했을 땐 이겼다. 이 과정을 더 편하게 할 순 없을까?
while 반복문(while loop)를 이용해본자. 기본 구조는 아래와 같다.
// 조건이 위배되면 while loop는 끝난다.
while (조건) {
만족되면 실행할 코드
}
이를 적용해보자. 조건문에서 myNumber와 cpuNumber를 비교하기 위해 두 변수를 가변 변수 let으로 while loop 바깥에 할당해둔다.
let myNumber = 0
let cpuNumber = 0
// 사용자가 이김: myNumber > cpuNumber
// 사용자가 못 이김: myNumber <= cpuNumber
while (myNumber <= cpuNumber) {
myNumber = Math.floor(Math.random() * 10)
cpuNumber = Math.floor(Math.random() * 10)
...
}
딱 열 번만 반복하고 이긴 횟수가 많은 쪽이 최종 승자가 되게 하려면 어떻게 해야 할까? 이때는 for 반복문을 사용하자.
for loop의 구조는 아래와 같다.
for (수식1;
수식2;
수식3) {
// 실행될 코드 블록
}
괄호 안에 들어가는 각 수식의 역할을 다음과 같다.
수식1: {}로 감싸진 코드 블록이 실행되기 전에 한 번 실행된다.
수식2: 해당 수식이 만족되면 코드 블록을 실행한다.
수식3: 코드 블록이 실행되고 나면 실행한다.
간단한 예를 보자.
for (let i = 0;
i < 10;
i = i + 1) {
// ...
}
i = 0으로 설정한다. i < 10을 만족하므로 {}로 감싸진 코드 블록을 실행한다. 이후 i는 기존 i보다 1을 키운 값으로 재설정한다.
마지막 과정은 아래와 같이 축약할 수도 있다.
i = i + 1
i += 1
i++
원하는 횟수만큼 반복키 위해 for loop를 쓸 땐 관례상 세 수식을 한 줄에 쓰고 마지막 수식은 제일 짧은 i++ 형태로 쓴다.
for (let i = 0; i < 10; i++) {
// ...
}
코드를 작성하다보면 한 함수가 굉장히 길어지게 된다. 이는 나중에 해당 코드를 이해하는 데에 큰 장해가 된다. 쉽게 읽히는 코드를 작성하기 위해서 함수를 정리하자.
함수를 정리할 땐 아래의 규칙을 따른다.
1. 한 함수는 한 가지 작업만 한다.
2. 한 함수의 길이는 60줄로 제한한다.
한 함수를 60줄 이내로 작성해야 한다. 이는 A4에 인쇄했을 때 한 페이지 정도의 분량이다. 그보다 더 길어지게 되면 리팩터링을 하여 정리해야 한다.
다만, 한 파일 안의 함수가 너무 많아져도 가독성에 문제가 생긴다. 이때는 비슷한 역할의 함수들을 별도의 파일에 분리하자. 다른 파일에서의 함수를 불러내기 위해선 두 작업이 필요하다.
// firstFile.js
function firstFn() {
// ...
}
function secondFn() {
// ...
}
export { firstFn, secondFn }
파일의 맨 마지막에 export { firstOne, secondOne }를 작성함으로써 다른 파일에서도 {} 안의 함수들을 들여올 수 있게 한다.
import { getTwoNumbers, checkWinner } from './operations.js'
다른 파일의 함수를 사용하기 위해서는 파일의 맨 첫줄에서 import를 해야 한다. import 뒤에는 들여올 함수들을, from 뒤에는 해당 파일의 경로를 적는다. 절대 경로도 괜찮고 상대 경로도 괜찮다.
상대 경로를 적을 땐 아래의 규칙을 사용한다.
.: 현재 폴더(파일 기준)
..: 현재 폴더보다 한 칸 상위 폴더
...: 현재 폴더보다 두 칸 상위 폴더
for loop에 관한 설명은 w3school에서의 설명을 번역하는 정도에 그쳤다.
https://www.w3schools.com/js/js_loop_for.asp
좋은 코드가 무엇인지는 "Nasa's 10 coding rules"로도 불리는 아래의 문서를 따르고 있다.
원본은 나사 내부 문서로 접근이 불가능하다.
Holzmann, The Power of 10: Rules for Developing Safety-Critical Code (NASA/JPL, 2006)