일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 수코딩
- 개발
- 프로젝트캠프
- frontend
- STATE
- 리액트프로젝트
- 웅진씽크빅
- sucoding
- React
- Server State
- 상태 관리 라이브러리
- 스나이퍼팩토리
- TypeScript
- tanstack query
- 공식문서
- 프론트엔드
- React Query
- 프론트엔드 개발
- 유데미
- Today
- Total
yunicornlab
JavaScript의 특징 - 동적 타입 언어 본문
자바스크립트는 동적 타입 언어라는 특징이 있다.
그럼 동적 타입 언어는 무엇이고, 왜 동적 타입으로 만들어졌는 지에 대해 알아보자.
동적 타입 언어란?
동적 타입 언어란, 프로그램 실행 중에 변수의 타입이 결정되고 변경될 수 있는 프로그래밍 언어를 말한다.
1) 변수를 선언할 때 타입을 명시할 필요가 없다.
동적 타입 언어 - JavaScript 예시
// 자동으로 string 타입으로 결정됨
let message = "Beautiful Day ~ !";
// 자동으로 number 타입으로 결정됨
let price = 10000;
정적 타입 언어 - Java 예시
// 'int'로 정수 타입 명시
int number = 10000;
// 'String'으로 문자열 타입 명시
String text = "Cheer Up!!";
2) 동일한 변수에 다른 타입의 값을 할당할 수 있다.
// 자동으로 string 타입으로 결정됨
let message = "Beautiful Day ~ !";
// 자동으로 number 타입으로 변경됨
message = 9900;
Java와 같은 정적 타입 언어는, 변수를 선언할 때 정해놓은 타입 그래도 재할당할 수 있다.
만약, string 타입으로 변수를 선언했는데 다른 타입의 값을 할당하면 오류가 발생한다.
동적 타입 언어 vs. 정적 타입 언어
동적 타입 언어로는 대표적으로 JavaScript, Python, 그리고 Ruby, PHP 등이 있고,
정적 타입 언어로는 대표적으로 Java와 C언어, 그리고 C++, 코틀린 등이 있고, JavaScript의 단점을 보완하기 위해 나온 TypeScript도 정적 타입 언어에 속한다.
정적 타입 언어는 컴파일러가 타입 검사를 수행해서 타입 오류를 사전에 방지할 수 있게 하기 때문에, 변수의 타입이 컴파일 과정에서 결정되고 이후에는 변경할 수 없다.
타입 체크가 컴파일 시점에 수행되기 때문에, 타입 체크를 통과하지 못하면 에러가 발생하고 프로그램 실행 자체가 안된다.
이렇게 타입과 관련된 오류를 미리 확인할 수 있기 때문에 안전성이 비교적 높다.
그리고 컴파일러가 타입 정보를 알고 있기 때문에 얻을 수 있는 이점도 많다. 타입에 따라 변수가 고정된 메모리 크기를 가지기 때문에 메모리 할당이나 접근이 더 빠르게 이루어질 수 있다. 그리고 런타임에서 타입 검사를 수행할 필요가 없기 때문에 예외 처리 코드가 줄어들고 성능을 향상될 수 있다.
동적 타입 언어는 정적 타입 언어와 반대로 생각하면 된다. 일단, 변수의 타입이 런타임에 결정되고 필요에 따라서 변경할 수 있다.
위에서 말했듯이 타입 선언이 필요하지 않고 변수에 할당한 값에 따라서 자동으로 타입이 결정된다.
코드를 유연하게 작성할 수 있기 때문에 유지보수하기 좋고, 요구 사항이 빠르게 변할 때 대응하기 좋아서 빠르게 프로토타입을 만들고 테스트하기 좋다.
하지만, 타입 오류를 런타임 시점에 발견하기 때문에 예외 처리 코드를 잘 작성해주어야 하고, 그럼에도 프로그램 실행 중에 예상치 못한 오류가 발생할 수 있다. 성능적으로도 정적 타입 언어보다 비교적 낮을 수 있다.
JavaScript는 왜 동적 타입으로 설계되었을까?
브랜든 아이크 개발자님이 자바스크립트 언어를 10일 만에 만들었다고 했다.
처음 목적 자체가 웹을 동작할 수 있는 간단한 기능을 원해서 동적 타입이 되었을 수도 있다.
진짜 목적까지는 몰라도, 유추할 수는 있다.
동적 타입은 문법이 단순하고 직관적이며 확실히 코딩하기 편하기 때문에 초보자도 쉽게 배울 수 있다.
게다가 웹 개발에서는 요구사항이 자주 변하기 때문에 이런 점에 대처하기 편하다.
위에서도 말했듯이, 이런 편리성 덕분에 프로토타입을 빠르게 만들고 테스트하기 좋다.
자바스크립트를 많은 사람이 사용하게 된 이유이기도 하다고 생각한다.
변수에 값을 할당할 때의 동작
변수를 선언하고 값을 할당하면, 자바스크립트 엔진이 변수를 스코프 내 변수 환경에 등록하도록 지시한다.
그리고 해당 값을 저장할 메모리 공간을 할당한다.
이때, 값이 원시 타입일 경우 스택 메모리에 2진수로 변환해 저장한다.
참조 타입일 경우에는 객체는 힙 메모리에 저장하고 스택에 객체의 참조(메모리 주소)를 저장한다.
갑자기 이 얘기를 하는 이유는, 메모리를 할당할 때 값에 따라 달라지는 메모리 공간의 크기를 알아보기 위해서이다.
보통은 데이터 타입 별로 메모리 크기가 정해져있다.
자바스크립트는 Number 타입의 경우, 정수형인지 부동 소수형인지 구분하지 않고 8바이트를 할당(정확히는 64비트 부동소수점 형식)하고, 문자열은 UTF-16 인코딩을 사용하여 각 문자를 16비트(2바이트)로 저장한다.
하지만! 자바스크립트에서 데이터 타입별 메모리 크기는 사실 명확히 고정되어 명시되어있지는 않다.
숫자와 문자 타입은 위에서 말한 게 거의 공통인 것 같긴 한데, 그 외의 데이터 타입은 자바스크립트의 엔진의 구현에 따라 달라질 수 있다.
그럼 어차피 동적 타입인데, 그럼에도 굳이 "타입"이 필요한 이유는 뭘까?
자바스크립트 딥 다이브에 예시가 나와있다.
메모리에 "0100 0001"이 저장되어있다면, 이를 읽어들일 때 숫자로 해석하면 65이지만, 문자열로 해석하면 "A"이다.
즉, 해당 변수에 어떤 타입이 미리 할당되어있는지에 따라 결과가 달라진다.
해당 변수를 참조했을 때 메모리 공간에서 읽어들인 2진수값을 65로 해석할 수도 있고, "A"로 해석할 수도 있는 것이다.
그리고 한 가지 더 말해보자면, "변수"가 타입을 갖는 것이 아니라 "값"이 타입을 갖는 것이다.
그렇기 때문에 변수는 할당된 값에 따라 타입이 동적으로 결정되는 것이다.
더 조사해본 결과를 정리해보자면 다음과 같다.
(1) 메모리 사용을 효율적으로 관리할 수 있다.
- 값을 저장할 때 확보해야 하는 메모리 공간의 크기를 결정하기 위해 필요하다.
(2) 값을 참조할 때 한 번에 읽어 들여야 할 메모리 공간의 크기를 결정하기 위해 필요하다.
(3) 메모리에서 읽어들인 2진수를 어떻게 해석할지 결정하기 위해 필요하다.
(4) 데이터의 의미와 용도를 명확히 하기 위해 필요하다.
- 사용할 수 있는 연산이 달라지고, 코드의 목적과 동작 방식을 쉽게 이해할 수 있기 때문이다.
JavaScript가 동적 타입 언어라서 가진 치명적인 단점
명시적 타입 변환(타입 캐스팅) vs. 암묵적 타입 변환(타입 강제 변환)
정적 타입 언어와 달리 동적 타입 언어인 자바스크립트는 실제로 변수의 값을 찍어보기 전에는 타입을 확신할 수 없다.
암묵적으로 타입이 변환될 수도 있기 때문이다. 그래서 개발자의 의도와는 상관 없이 바뀌어있을 수도 있다.
이를 방지하려면 또 타입을 체크하기 위한 코드가 삽입되어야 한다.
명시적 타입 변환
그럼, 자바스크립트에서의 타입 변환에 대해 한 번 알아보자.
먼저는 명시적으로 타입을 변환하는 방식이 있다.
let before = 9900;
let after = String("9900");
// after = before.toString();
위의 예시처럼 String(), toString(), Number(), Boolean()과 같은 함수를 사용해서 딱 봐도 타입을 변경하려는 의도가 명백히 보이게 작성하는 방식이 "명시적 타입 변환(Explicit Coercion) 또는 타입 캐스팅(Type Casting)" 방식이다.
암묵적 타입 변환
let num = 10;
let str = "The number is " + num; // "The number is 10"
let str = "5";
let result = str - 2; // 3 (문자열 "5"가 숫자 5로 변환됨)
if ("") {
console.log("Truthy");
} else {
console.log("Falsy"); // 빈 문자열은 falsy
}
어질어질하다!
문자열 + 숫자를 했는데 에러가 발생하지 않고 숫자가 문자열로 바뀌면서 이어졌다.
문자열 - 숫자를 했는데 에러가 발생하지 않고 문자가 숫자로 바뀌면서 계산이 되어졌다.
""가 자동으로 Boolean 타입으로 바뀌면서 if 문이 해석되어졌다.
이게 바로 암묵적 타입 변환의 기본적인 예시이다.
예시에도 보여지듯이, 의도하지 않은, 예상치 못한 결과를 얻을 수 있다.
암묵적 타입 변환에 대해서 파고들다 보면 분량이 정말 많아진다. 동등 연산자와 일치 연산자도 이어질 수 있고, 논리 연산자를 이용한 단축 평가나 Truthy/Falsy에 대해서도 다뤄야하기 때문이다. 그래서 이 부분은 다른 글에서 하나씩 따로 알아볼 것이다!
따라서, 둘의 차이를 요약해보자면,
명시적 타입 변환은 "개발자가" 명확하게 타입 변환하는 코드를 작성하는 것이고,
암묵적 타입 변환은 "자바스크립트 엔진"이 자동으로 타입 변환을 수행하는 것이다. 주체가 다르다!
그럼, 무조건 명시적 타입 변환만 써야 하나?
그건 또 아니다. 상황에 따라 다르긴 하겠지만, 암묵적 타입 변환 방식이 가독성 측면에서 더 이해하고 간결한 표현일 수도 있기 때문이다.
어떻게 사용하든지 다른 사람이 이해할 수 있고 오해받지 않을 코드를 작성하면 된다.
결론
자바스크립트는 동적 타입 언어이다. 변수 선언시에 타입을 명시할 필요도 없고, 동일한 변수에 다른 타입의 값을 할당할 수 있다.
심지어 자바스크립트 엔진이 자동으로 타입을 변환하는 암묵적 타입 변환이 일어날 수도 있다.
이를 미리 숙지하고 주의해서 사용한다면, 동적 타입 언어로서 얻을 수 있는 이점은 챙기고, 안정성이 비교적 낮은 단점도 보완할 수 있다.
그렇기 때문에, "동적 타입 언어"라는 특성에 대해서 잘 알아야 한다!
(물론 타입스크립트 사용과 같은 방법도 있다.)
'Frontend > JavaScript' 카테고리의 다른 글
JavaScript의 핵심! 실행 컨텍스트 이해하기 (0) | 2024.08.07 |
---|---|
JavaScript의 특징 - 멀티 패러다임 언어 (2) | 2024.07.22 |
JavaScript의 특징 - 싱글 스레드 언어 (0) | 2024.07.15 |
JavaScript의 특징 - 인터프리터 언어 (0) | 2024.07.14 |
[JavaScript] 자바스크립트 sort() 함수 이해하고 사용하기 (0) | 2024.06.11 |