logo태영이의 공부방

[JavaScript] 변수와 상수

2022년 07월 09일

변수와 상수

자바스크립트 애플리케이션은 사용자나 서버로부터 입력받은 정보를 처리하는 방식으로 동작한다.

이때 변수는 아래와 같은 정보를 저장하는 용도로 사용된다.

  • 온라인 쇼핑몰 : 판매 중인 상품이나 장바구니 등의 정보
  • 채팅 애플리케이션 : 사용자 정보, 메시지 등의 정보

변수Variable

변수variable란 데이터를 저장할 때 쓰이는, 이름이 붙은 저장소이다.

변수의 필요성

10 + 20

컴퓨터(자바스크립트 엔진)는 위 자바스크립트 코드를 아래와 같은 과정으로 실행한다.

  1. 10 + 20의 의미를 해석한다.
  2. + 연산자의 피연산자를 기억한다.
  3. 임의의 메모리 주소에 저장된 피연산자를 읽어들여 연산을 수행한다.
  4. 연산 결과인 30을 임의의 메모리 주소에 저장한다.

여기서 아래와 같은 의문점이 발생한다.

변수가 없어도 메모리 주소를 통해 재사용 할 수 있는 것이 아닌가?

아니다.

그 이유는 아래와 같다.

  • 메모리 주소를 통해 값에 직접 접근하는 일은 치명적인 오류(ex. 시스템 다운)를 발생시킬 가능성이 높은 매우 위험한 일이다.
  • 자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않는다.
  • 동일한 컴퓨터에서 동일한 코드를 실행해도 값이 저장될 메모리 주소는 실행될 때마다 변한다.

따라서 안전하게 값에 접근하기 위해 변수를 사용하는 것이다.

다시말해 기억하고 싶은 값을 메모리에 저장하고, 저장된 값을 읽어 들여 재사용하기 위해 변수를 사용한다.

변수의 이름, 값, 할당, 참조

  • 변수 이름/변수명/식별자: 어떤 값을 구별해서 식별할 수 있는 고유한 이름, 값이 아닌 메모리 주소를 기억
  • 변수 값: 변수에 저장된 값
  • 할당/대입/저장: 변수에 값을 저장하는 것
  • 참조: 변수에 저장된 값을 읽어 들이는 것

변수 선언

자바스크립트 에서는 var, let, const 키워드를 사용해 변수를 생성(선언)할 수 있다.

var msg; // msg란 이름의 변수 생성(선언)

위 변수 선언문은 자바스크립트 엔진에 의해 2단계에 거쳐 수행된다.

  1. 선언 단계: 변수 이름을 등록해 자바스크립트 엔진에 변수의 존재를 알린다.
  2. 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.

undefined로 초기화는 왜 하는걸까?

초기화 단계가 없다면 메모리 공간에 다른 애플리케이션이 사용했던 값(쓰레기 값)이 남아있을 수 있다.

값의 할당

= 을 사용해 변수에 데이터를 저장할 수 있다.

let msg; // 변수 선언
msg = 'Hello, World!' // 문자열 저장
 
// 한 줄에 변수 선언과 값 할당을 할 수도 있다.
let msg = 'Hello, World!' // 변수 정의, 값 할당

자바스크립트 엔진은 변수 선언과 값의 할당을 나누어 각각 실행하기 때문에 위 2가지 코드는 동일하게 동작한다.

이때, 변수 선언은 런타임 이전에 실행되지만 값의 할당은 런타임에 실행되기 때문에 주의해야 한다.

console.log(message); // undefined
 
var message;
message = 'hello javascript';
// 혹은,
var message = 'hello javascript';
 
console.log(message) // hello javascript

추가로, 변수에 값을 할당할 때 undefined가 저장된 메모리 공간을 지우고 할당 값을 저장하는 것이 아니라 새로운 메모리 공간을 확보하고 그곳에 저장하므로 주의하자.

값의 재할당

값의 재할당이란 말 그대로 이미 값이 할당된 변수에 새로운 값을 다시 할당하는 것을 말한다.

이때 만약 값을 재할당할 수 없다면 상수constant라 한다. 즉, 상수는 한 번 정해지면 변하지 않는 값이다.

ES6에서는 const 키워드를 사용해 상수를 표현한다.

값의 재할당도 역시 값의 할당과 마찬가지로 새로운 메모리 공간을 확보하고 재할당 값을 저장한다.

이전에 저장했었던 값들은 어떻게 될까?

불필요한 값들은 가비지 콜렉터에 의해 자동으로 메모리에서 해제된다.

변수 접근 방법

저장한 데이터는 변수명을 이용해 접근할 수 있다.

alert(msg) // 변수에 저장된 값을 보여준다.

여러 변수 선언

한 줄에 여러 변수를 선언할 수도 있다.

let a = 'apple',
  b = 'banana',
  c = 'carrot'

하지만 위와 같은 방법은 가독성이 떨어지기 때문에 권장하는 방법은 아니라고 한다.

한 줄에 하나의 변수를 작성하는 것이 코드가 길어 보이더라도 읽기에는 편하다.

여러가지 변수 선언 방식

선언할 때마다 let 사용

let a = 'apple'
let b = 'banana'
let c = 'carrot'

쉼표와 줄바꿈 사용

let a = 'apple',
  b = 'banana',
  c = 'carrot'

앞 부분에 쉼표 사용

let a = 'apple'
  , b = 'banana'
  , c = 'carrot'

위의 세 가지 모두 한 줄에 하나의 변수만을 선언했으므로 어떤 방식을 사용하는지는 개인의 취향에 달려있다.

let 대신 var

오래된 스크립트에서 let 대신 var라는 키워드를 사용해 변수를 선언하는 경우가 있다.

letvar 모두 변수를 선언하는 데 쓰이지만 var는 오래된 방식이다.

이에 대해서는 다음 포스팅에서 다루도록 하겠다.

변수의 특징

변수에는 어떤 값이든지 넣을 수 있고, 원하는 만큼 값을 변경할 수도 있다.

let anything = 123
anything = 12.3
anything = 'Hi'

변수 복사

변수를 두 개 선언하여 한 변수의 데이터를 다른 변수에 복사할 수도 있다.

let original = 'Hello'
let copied
 
copied = original

위의 경우 copied 변수와 original 변수는 같은 데이터를 가진다.

변수 중복 선언

변수를 두 번 선언할 경우 에러가 발생하므로 주의해야한다.

let msg = 'Hello'
let msg = 'Hi'
// 같은 이름의 변수를 여러 번 선언하면 에러 발생

선언한 변수를 참조할 때는 let 없이 변수명만 쓰도록 하자.

변수 명명 규칙

자바스크립트에선 변수명을 정할 때 아래 세 가지 제약 사항이 존재한다.

  • 식별자는 특수문자를 제외한 문자, 숫자, 언더스코어(_), 달러($)를 포함할 수 있다.
  • 식별자는 숫자로 시작하지 않아야 한다.
  • 예약어는 식별자로 사용할 수 없다.

ES5부터 식별자에 유니코드 문자를 허용해 한글 식별자도 사용할 수 있지만 권장하지는 않는다.

네이밍 컨벤션

하나 이상의 영어 단어로 구성된 식별자를 가독성 좋게 구분하기 위해 규정한 명명 규칙을 네이밍 컨벤션이라 한다. 주로 아래 4가지 유형이 사용된다.

  • 카멜 케이스 camelCase
  • 스네이크 케이스 snake_case
  • 파스칼 케이스 PascalCase
  • 헝가리언 케이스 typeHungarianCase

자바스크립트에서는 보통 변수나 함수는 카멜 케이스를 생성자 함수, 클래스에는 파스칼 케이스를 사용한다.

⚠️

대소문자 구별

thisIsVarthisisvar는 서로 다른 변수이므로 주의하자.

변수명에 한자 사용?

비 라틴계 언어도 변수명에 사용할 수 있지만 권장하진 않는다.

키릴 문자, 상형문자와 같은 모든 언어를 변수명에 사용할 수 있다.

하지만 영어를 변수명에 사용하는 것이 국제적인 관습이기 때문에 영어 사용을 권유하고있다.

변수명으로 let(예약어)?

예약어 목록에 있는 단어는 변수명으로 사용할 수 없다.

아래와 같은 단어를 변수명으로 사용할 경우 문법 에러를 발생시킨다.

let, class, return, function, …

use strict 없이 값 할당하기

이전에는 let 없이도 값을 할당해 변수를 생성하는 것이 가능했다.

과거 스크립트와의 호환성 유지를 위해 현재도 이 방식을 사용할 수 있지만…

'use strict' // 전체 스크립트 엄격 모드 구문
num = 5 // error: num is not defined

엄격 보드에서 에러를 발생시키기 때문에 위와 같은 변수 생성 방식은 좋지 않은 관습이라고 한다.

상수Constant

상수란 변화하지 않는 변수로, 값을 재할당할 수 없다.

상수를 선언할 땐 const를 사용하고 이를 변경하려고 하면 에러가 발생한다.

const fixedVar = 'Hello'
fixedVar = 'Bye' // error: can't reassign the constant

그렇다면 상수는 언제 쓰이는 것일까?

변숫값이 절대 변경되지 않을 것이라는 확신이 들 경우 상수로 선언한다.

이는 값이 변경되는 것을 방지함과 동시에 다른 개발자들에게 상수라는 것을 알릴 수 있다.

대문자 상수

이전부터 기억하기 힘든 값은 변수에 할당하여 별칭으로 사용해왔다.

이런 상수는 대문자와 밑줄로 구성된 이름으로 명명한다.

16진수 컬러 코드에 대한 상수 예제를 확인해보자.

const COLOR_RED = '#F00'
const COLOR_GREEN = '#0F0'
const COLOR_BLUE = '#00F'
const COLOR_ORANGE = '#FF7F00'
 
let color = COLOR_ORANGE
alert(color) // #FF7F00

대문자로 상수를 만들 경우 아래와 같은 장점이 있다.

  • 기억하기 쉽다.
  • 오타를 낼 확률이 낮다.
  • 코드 가독성이 증가한다.

일반적인 방식 vs. 대문자 사용

그렇다면 상수명은 모두 대문자를 사용해야하는 것일까?

일반적인 방식(카멜케이스) 사용

런타임 과정에서 계산되지만 최초 할당 이후 값이 변하지 않는 상수

대문자 사용

실행 전에 이미 값을 알고 있고, 코드에서 직접 그 값을 쓰는 경우

정리하자면, 대문자 상수는 하드 코딩한 값의 별칭을 만들 때 사용하면 된다.

아래 예제를 통해 확실히 알아보자.

올바른 대문자 상수의 사용

birthday 변수를 이용하여 구한 나이를 age에 담고자 한다.

어떤 변수를 대문자 상수로 만들어야 할까.

const birthday = '18.04.1982'
// 대문자 상수로 적합하다.
 
const age = someCode(birthday)
// 런타임에 평가되므로 대문자 상수에 적합하지 않다.

바람직한 변수명

변수명은 간결하고 명확해야 한다.

이는 변수가 담고있는 것이 무엇인지 잘 설명할 수 있어야한다는 것이다.

변수 명명 시 참고하기 좋은 규칙들
  • userName이나 shoppingCart처럼 사람이 읽을 수 있는 이름을 사용해라.
  • 무엇을 하고 있는지 명확히 알고 있지 않을 경우 외에는 줄임말이나 a, b와 같은 짧은 이름은 피해라.
  • 최대한 서술적이고 간결하게 명명해라.
  • datavalue는 안좋은 예이다. 이는 아무것도 설명해주지 않기 때문에 코드 문맥상 변수가 가리키는 데이터나 값이 아주 명확할 때에만 이런 이름을 사용하자.

위의 규칙을 참고하여 올바른 변수명을 지어보았다.

// 우리가 살고있는 행성의 이름을 값으로 가진 변수 이름 짓기
let outPlanetName = 'Earth'
// 나의 답 : ourPlanet
 
// 현재 방문자를 나타내는 변수 이름 짓기
let currentUserName
// 나의 답 : userName

변수명을 짧게만 써왔더니 전부 틀렸다..

변수의 재사용과 새로 만들기

결과적으로 변수를 추가하는 것은 악습이 아니라 좋은 습관이다.

변수를 재사용 할 경우 디버깅에 더 많은 시간을 쏟게되기 때문이다.

정리

  • 변수: 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름
  • 선언: 값을 저장하기 위한 메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것
  • 변수 선언과 값의 할당
    • 변수 선언: 런타임 이전 실행
    • 값의 할당: 런타임에 실행
  • 네이밍 컨벤션
    • 변수, 함수: 카멜 케이스 camelCase
    • 생성자 함수, 클래스: 파스칼 케이스 PascalCase

💡

이 게시물은 모던 JavaScript 튜토리얼딥다이브 스터디를 참고하였습니다.