06 데이터 타입
- 데이터 타입(data type) 줄여서 타입(type) 은 값의 종류를 말한다.
- 자바스크립트의 모든 값을 타입을 갖는다
- ES6에서 제공하는 데이터 타입은 7개이다.
- 7개의 데이터 타입은 원시타입(primitive type)과 객체타입(object type)으로 나뉜다.
구분 | 데이터 타입 | 설명 |
---|
원시 타입 | number 타입 | 숫자, 정수와 실수 구분 없이 하나의 숫자 타입만 존재 |
| boolean 타입 | 논리적 참(true)과 거짓(false) |
| undefined 타입 | var 키워드로 선언된 변수에 암묵적으로 할당되는 값 |
| null 타입 | 값이 없다는 것을 의도적으로 명시할 때 사용하는 값 |
| symbol 타입 | ES6에서 추가된 7번째 타입 |
객체 타입 | | 객체, 함수, 배열 등 |
- 숫자 타입의 값 1과 문자열 타입의 값 '1'은 비슷해 보이지만 전혀 다른 값이다
- 생성한 목적과 용도가 다르다
- 숫자 타입은 주로 산술 연산을 위해 생성
- 문자열 타입은 주로 텍스트를 화면에 출력하기 위해 생성
- 확보해야할 메모리 공간의 크기도 다르고
- 메모리에 저장되는 2진수도 다르며
- 읽어들여 해석하는 방식도 다르다
6.1 숫자 타입: number
- 하나의 숫자 타입만 존재, 모든 수를 실수로 처리
- 모두 10진수로 해석
- 자바스크립트는 독특하게 하나의 숫자 타입만 존재
C
나 Java
의 경우, 정수와 실수를 구분해서 int
, long
, float
, double
등과 같이 다양한 숫자 타입이 존재
- ECMAScript 사양에 따라 다름
- 숫자 타입의 값은 배정밀도 64비트 부동소수점 형식을 따른다
- 모든 수를 실수로 처리
정수만 표현하기 위한 데이터 타입(integer type)이 별도로 존재하지 않는다
var integer = 10;
var double = 10.12;
var negative = -20;
- 자바스크립트는 2진수, 8진수, 16진수 표현하기 위한 데이터 타입을 제공하지 않고 모두 10진수로 해석
var binary = 0b01000001;
var octal = 0o101;
var hex = 0x41;
console.log(binary);
console.log(octal);
console.log(hex);
console.log(binary === octal);
console.log(octal === hex);
- 정수로 표시된다 해도 사실은 실수라는 것을 의미
console.log(1 === 1.0);
- 숫자 타입은 추가적으로 세가지 특별한 값도 표현할 수 있다
Infinity
: 양의 무한대
-Infinity
: 음의 무한대
NaN
: 산술 연산 불가(not a number)
console.log(10 / 0);
console.log(-10 / 0);
console.log(1 * 'String');
- 대소문자 구별(case-sensitive)하므로
NaN
을 NAN
, Nan
, nan
과 같이 표현하면 에러가 발생
NAN
, Nan
, nan
을 값이 아닌 식별자로 해석
var x = nan;
6.2 문자열 타입: string
- 16비트 유니코드 문자(UTF-16)의 집합
- 일반적으로
single quote
를 사용해서 문자열을 표현
- 문자열은 원시타입(primitive type)이며 변경 불가능한 값(
Immutable value
)이다
- 텍스트 데이터를 나타내는데 사용
- 0개 이상의 16비트 유니코드 문자(UTF-16)의 집합으로 전 세계 대부분의 문자를 표현
- 작은 따옴표(
''
), 큰 따옴표(""
), 백틱(``
)으로 텍스트를 감싼다
- 가장 일반적인 표기법은 작은 따옴표를 사용
var string;
string = '문자열';
string = "문자열";
string = `문자열`;
문자열을 따옴표로 감싸는 이유🤔
- 키워드나 식별자 같은 토큰과 구분하기 위해서
- 따옴표로 감싸지 않으면 자바스크립트 엔진은 키워드나 식별자 같은 토큰으로 인식
- 문자열을 감싸지 않는다면 스페이스와 같은 공백 문자도 포함시킬 수 없다
- 문자열은 원시타입(primitive type)이며 변경 불가능한 값(Immutable value)이다
- 문자열이 생성되면 그 문자열을 변경할 수 없다는 것을 의미
C
는 문자열 타입을 제공하지 않고, 문자의 배열로 문자열을 표현하고,
Java
는 문자열을 객체로 표현
6.3 템플릿 리터럴: Template Literal
- ES6부터 템플릿 리터럴이라고 하는 새로운 문자열 표기법이 도입
- 멀티라인 문자열(multi-line string),
- 표현식 삽입(expression interpolation),
- 태그드 템플릿(tagged template) 등 편리한 문자열 처리 기능을 제공
- 런타임에 일반 문자열로 변환되어 처리
``
빅틱을 사용
✔️ 6.3.1 멀티라인의 문자열(multi-line string)
- 일반 문자열 내에서는 줄바꿈(개행)이 허용되지 않는다
var str = 'Hello
world.'; / SyntaxError : Invalid or unexpectied token
- 일반 문자열 내에서 줄바꿈 등의 공백(white space)을 표현하려면 빅슬래시(
\
)로 시작하는 이스케이프 시퀀스(escape sequence)를 사용
이스케이스 시퀀스 | 의미 |
---|
\0 | Null |
\b | 백스페이스 |
\f | 폼 피드(Form Feed) : 프린터로 출력할 경우 다음 페이지의 시작 지점으로 이동 |
\n | 개행(LF,Line Feed) : 다음 행으로 이동 |
\r | 개행(CR, Carriage Return) : 커서를 처음으로 이동 |
\t | 탭(수평) |
\v | 탭(수직) |
\uXXXX | 유니코드. 예를 들어'\u0041'은 'A', '\uD55c'는 '한', '\u{1F600}'는 스마일이모지 😃 |
\' | 작 따옴표 |
\" | 큰 따옴표 |
\ | 백 슬래시 |
예를 들어, 줄바꿈과 들여쓰기가 혀용된 HTML 문자열 아래 코드로 작성한다.
var template = '<ul>\n\t<li><a href="#">Home</a></li>\n</ul>';
- 템플릿 리터럴 내에서는 이스케이프 시퀀스를 사용하지 않고도 줄바꿈이 허용되며, 모든 공백도 있는 그대로 적용된다
var template = `<ul>
<li><a href="#">Home</a></li>
</ul>`;
✔️ 6.3.2 표현식 삽입
- 문자열 연산자
+
를 사용해 연결할 수 있다
+
연산자는 피 연산자 중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작
- 그 외의 경우는 덧셈 연산자로 동작
- 템플릿 리터럴 내에서는 표현식 삽입(expression interpolation)을 통해 간단히 문자열 삽입
- 문자열 연산자 보다 가독성이 좋고 간편하게 문자열을 조합할 수 있다
var name = 'April';
console.log('제 이름은' + name + '입니다');
var name = 'April';
console.log(`제 이름은 ${name} 입니다`);
6.4 불리언 타입: boolean
- 논리적 참, 거짓을 나타내는
true
, false
뿐이다
- 참과 거짓으로 구분되는 조건에 의해 프로그램 흐름을 제어하는 조건문에서 자주 사용
6.5 undefined 타입
- undefined 타입의 값은
undefined
가 유일
var
키워드로 선언한 변수는 암묵적으로 undefined
로 초기화
- 변수 선언에 의해 확보된 메모리 공간을 처음 할당이 이뤄질 때 까지 빈 상태로 내버려두지 않고 자바스크립트 엔진이
undefined
로 초기화
- 개발자가 의도적으로 할당하기 위한 값이 아니라 자바스크립트 엔진이 변수를 초기화할 때 사용하는 값
- 변수를 참조했을 때
undefined
가 반환된다면, 초기화 되지 않은 변수라는 것을 간파할 수 있다
- 변수에 값이 없다는 것을 명시하고 싶을 때는
undefined
를 할당하는 것이 아닌 null
을 할당
6.6 null 타입
- null 타입의 값은
null
이 유일
- 자바스크립트는 대소문자를 구별하므로 Null, NULL 등과 다르다.
- 프로그래밍 언어에서
null
은
- 변수에 값이 없다는 것을 의도적으로 명시(의도적 부재(intentional absence))할 때 사용
- 변수에
null
을 할당하면, 변수가 이전에 참조하던 값을 더 이상 참조하지 않겠다는 의미
- 자바스크립트 엔진은 누구도 참조하지 않는 메모리 공간에 대해 가비지 컬렉션을 수행
- 함수가 유효한 값을 반환할 수 없는 경우 명시적으로 null을 반환
- HTML 요소를 검색할 수 없는 경우 에러 대신 null을 반환
<html>
<body>
<script>
var element = document.querySeletor('.myClass');
console.log(element);
</script>
</body>
</html>
6.7 심볼 타입: symbol
- symbol은 ES6에서 추가된 7번째 타입
- 변경 불가능한 원시 타입의 값
- 다른 값과 중복도지 않는 유일무이한 값
- 주로 이름이 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해 사용
- 심볼 이외의 원시 값은 리터럴을 통해 생성, symbol은 symbol함수를 호출해 생성
- 생성된 심벌 값은 외부에 노출되지 않으며, 다른 값과 절대 중복되지 않는 유일무이한 값
var key = Symbol('key');
console.log(typeof key);
var obj = {};
obj[key] = 'value';
console.log(obj[key]);
6.8 객체 타입: Object
- 자바스크립트의 데이터 타입은 원시타입과 객체타입으로 분류하는 이유는 원시타입과 객체타입이 근본적으로 다르다는 의미.
- 자바스크립트는 객체 기반의 언어이며, 자바스크립트를 이루고 있는 거의 모든 것이 객체라는 것.
- 지금까지의 6가지 데이터 타입 이외의 값은 모두 객체 타입
6.9 데이터 타입의 필요성
데이터 타입은 왜 필요한 것일까? 🤔
- 낭비와 손실 없이 값을 저장하기 위해
- 메모리에서 읽어 들인 2진수를 어떻게 해석할지 결정하기 위해
✔️ 6.9.1 데이터 타입에 의한 메모리 공간의 확보와 참조
- 값은 메모리에 저장하고 참조할 수 있어야 한다.
- 메모리에 값을 저장하려면 먼저 확보해야 할 메모리 공간의 크기를 결정해야 한다
- 몇 바이트의 메모리 공간을 사용해야 낭비와 손실 없이 값을 저장할 수 있는지 알아야 한다
- 자바스크립트 엔진은 데이터 타입, 즉 값의 종류에 따라 정해진 크기의 메모리 공간을 확보
- 변수에 할당되는 값의 데이터 타입에 따라 확보해야 할 메모리 공간의 크기가 결정
✔️ 6.9.2 데이터 타입에 의한 값의 해석
- 모든 값은 데이터 타입을 가지며, 메모리에 2진수 즉, 비트의 나열로 저장.
- 메모리에서 읽어 들인 2진수를 어떻게 해석하느냐?
- 메모리에 2진수의
01000001
을 숫자로 해석하면 65, 문자열로 해석하면 'A'
6.10 동적 타이핑
✔️ 6.10.1 동적 타입 언어와 정적 타입 언어
자바스크립트의 모든 값은 데이터 타입을 갖는다. 그렇다면 변수는 데이터 타입을 가질까? 🤔
C
, Java
같은 정적 타입(static/string type)언어는
- 변수를 선언할 때 변수에 할당할 수 있는 값의 종류, 즉 데이터 타입을 사전에 선언
➔ 이를 명시적 타입 선언(expicit type declaration)이라 한다.
- 정적 타입 언어는 컴파일 시점에 타입 체크(선언한 데이터 타입에 맞는 값을 할당했는지 검사하는 처리)를 수행
- 만약 타입 체크를 통과하지 못했다면 에러를 발생시키고 프로그램의 실행 자체를 막는다.
➔ 타입의 일관성을 강제함으로써 더욱 안정적인 코드의 구현을 통해 런타임에 발생하는 에러를 줄인다.
- 대표적인 정적 타입 언어: C, C++, Java, Kotilin, Go, Haskell, Rust, Scala 등
자바스크립트
는 변수를 선언할 때 타입을 선언하지 않고 var
, let
, const
키워드를 사용해 변수 선언.
- 정적 언어와 같이 미리 선언한 데이터 타입의 값만 할당할 수 있는 것이 아닌, 어떠한 데이터 타입의 값이라도 자유롭게 할당이 가능
typeof
연산자로 변수의 데이터 타입을 조사
typeof
연산자로 변수를 연산하면 변수의 데이터 타입을 반환
➔ 변수의 데이터 타입을 반환하는 것이 아니라 변수에 할당된 값의 데이터 타입을 반환
- 변수에 값을 할당하는 시점에 변수의 타입이 동적으로 결정
➔ 변수의 타입은 언제든지 자유롭게 변경 가능
- 자바스크립트의 변수는 선언이 아닌 할당에 의해 타입이 결정(타입 추론(type inference))되고, 재할당에 의해 변수의 타입은 언제든지 동적으로 변할 수 있다.
- 정적 타입 언어와 구별하기 위해 이를 동적 타입(dynamic/weak type)언어라 한다.
- 대표적으로 JavaScript, Python, PHP, Ruby, Lisp, Perl 등
✔️ 6.10.2 동적 타입 언어와 변수
-
동적 타입 언어는 변수에 어떤 데이터 타입의 값이라도 자유롭게 할당할 수 있다. 하지만, 편리함의 이면에는 위험도 있다.
- 모든 소프트웨어 아키텍처에는 트레이드오프(trade-off)가 존재하며,
트레이드오프(trade-off): 두 개의 정책이나 목표 중 하나를 달성하려고 하면 다른 목표의 달성이 늦어지고나 희생되는 모순적 관계를 의미.
예를 들어, 실업률을 줄이면 물가가 상승하고, 물가를 안정시키면 실업률이 높아진다.
- 모든 애플리케이션에 적합한 은 탄환(silver bullet)은 없듯이 동적 타입 언어 또한 구조적인 단점이 있다
-
복잡한 프로그램에서는 변화하는 변수 값을 추론하기 어려울 수 있다
-
뿐만 아니라, 변수의 타입이 고정되어 있지 않고 값의 변경에 의해 타입도 언제든지 변경될 수 있다.
➔ 동적 타입 언어의 값을 확인하기 전에는 타입을 확신할 수 없다
-
유연성(flexbility)은 높지만 신뢰성(reliability)은 떨어진다
💡안정적인 프로그램을 만들기 위한, 변수 사용 시 주의 사항 🙃
- 변수는 꼭 필요한 경우에 한해 제한적으로 사용
- 변수 값은 재할당에 의해 언제든지 변경될 수 있다
- 이로 인해 동적 타입 언어인 자바스크립트는 타입을 잘못 예측해 오류가 발생할 가능성이 크다.
- 변수의 개수가 많으면 많을수록 오류가 발생할 확률도 높아진다.
➔ 따라서 변수의 무분별한 남발은 금물이며, 필요한 만큼 최소한으로 유지하도록 주의해야 한다
- 변수의 유효 범위(스코프)는 최대한 좁게 만들어 변수의 부작용을 억제해야 한다
- 변수의 유효 범위가 넓으면 넓을수록 변수로 인해 오류가 발생할 확률이 높아진다
- 전역 변수는 최대한 사용하지 않도록 한다
- 어디서든지 참조/변경 가능한 전역 변수는 의도치 않게 값이 변경될 가능성이 높고 다른 코드에 영향을 줄 가능성도 높다.
➔ 따라서 전액 변수는 프로그램의 복잡성을 증가시키고 처리 흐름을 추적하기 어렵게 만들고, 오류가 발생할 경우 오류의 원인을 특정하기 어렵게 만든다
- 변수보다는 상수를 사용해 값의 변경을 억제한다
- 변수 이름은 변수의 목적이나 의미를 파악할 수 있도록 네이밍한다
- 변수의 이름 뿐만이 아니라 모든 식별자(변수, 함수, 클래스 이름 등)는 존재 이유를 파악할 수 있는 적잘한 이름으로 지어야 한다
- 특히 식별자의 유효 범위가 넓을수록 명확한 이름을 명명하도록 노력하자
- 개발자의 의도를 나타내는 명확한 네이밍은 코드를 이해하기 쉽게 만들고, 이는 협업과 생산성 향상에 도움을 준다, ➔ 변수 이름은 첫아이 이름으 짓듯이 심사숙고해서 지어야 한다
- 코드는 오해하지 않도록 작성해야 한다
- 오해는 커뮨케이션을 어렵게 하는 대표적인 원인으로 생산성을 떨어뜨리는 것은 물론 팀의 사기까지 저하시킨다
- 사람이 이해할 수 있는 코드, 가독성이 좋은 코드가 좋은 코드이다
컴퓨터가 이해하는 코드는 어떤 바보도 쓸 수 있다. 하지만 훌륭한 프로그래머는 사람이 이해할 수 있는 코드를 쓴다.
-마틴 파울러, 리펙토링의 저자-