JS : 형변환 (Type Casting & Type Coercion) 완전 정리

Erica Gong·2022년 7월 21일
3

JS

목록 보기
2/4
post-thumbnail

들어가며

JavaScript 개발자라면 반드시 한 번은 봤을 유명한 밈이다. 이 밈은 JavaScript에서 느슨한 비교 연산자 ==를 사용하였을 때 발생하는 암시적 형변환(Type Coercion)으로 인한 문제점에 대해 이야기하고 있다. 만약, 저 밈이 말하는 바가 정확히 무엇인지, 더 나아가서는 JS의 암시적 형변환이 일어나는 세 가지 경우를 읊어볼 수 있다면, 이 포스팅을 읽을 필요가 없다.

하지만 만약 누군가로부터 JS 형변환이 뭐죠? 라고 질문이 들어왔을 때 답변할 자신이 없다면 5분만 시간을 내 이 포스팅을 살펴보면 좋을 듯 하다.

이번 포스트에서는 JS의 두 가지 종류의 형변환에 대해 다룬다. 암시적 형변환의 세 가지 케이스와 명시적 형변환의 두 가지 방법에 대해 소개하고자 한다. 부디 이 포스트가 도움이 되었으면 한다.

JS 형변환의 두 종류

형변환이란 변수의 기존 자료형이 다른 자료형으로 바뀌는 것을 의미한다. JS외에도 모든 언어의 형변환은 크게 암시적 형변환(Implicit Type Coercion)명시적 형변환(Explicit Type Casting)으로 나뉜다. 암시적, 명시적이라는 단어에서도 유추할 수 있듯 두 방식을 나누는 기준은 형변환의 주체이다. 암시적 형변환은 개발자의 의도와 무관하게 언어 내부에서 자동으로 변수의 자료형을 바꾸는 것을 의미한다. 반면, 명시적 형변환은 개발자가 함수나 생성자 등을 활용한 코드를 짜서 의도적으로 변수의 자료형을 바꾸는 행위를 지칭한다.

  • 암시적 형변환(Type Coercion) : JS 엔진이 자동으로 변수의 자료형을 변환
  • 명시적 형변환(Type Casting) : 개발자가 의도적으로 변수의 자료형을 변환

요약하자면, JS에는 크게 두 종류의 형변환이 있으며, 이는 형변환의 주체에 따라 구분한다. JS 엔진이 자동으로 변수의 자료형을 변환한 것은 암시적 형변환이며 개발자가 직접 코드를 작성해 변수의 자료형을 변환한 것을 명시적 형변환이라 지칭한다. 정의에 대해서는 이 정도만 이해해도 충분하다.

암시적 형변환의 세 종류

단순히 웃긴 밈으로 넘겨선 안된다. 만약, 암시적 형변환이 발생하는 대표적인 세 케이스를 모른다면 자신이 작성한 코드에서도 JS 엔진이 자동으로 수행한 형변환에 의해 고통 받을지도 모른다. (저 뇌가 내 뇌가 되어서는 안된다...)

내 코드에서 내가 모르는 암시적 형변환이 발생해서는 안된다. 이를 막기 위해 우리는 대표적인 3가지 암시적 형변환 케이스에 대해 알고 있어야 한다. JS 엔진산술 연산자, 느슨한 비교 연산자, 이중 부정을 사용할 때 자동으로 암시적 형변환을 수행한다. 이 세 케이스에 대해 알아보자.

산술 연산자(+)에 의한 암시적 형변환

개발자가 서로 다른 자료형을 가지는 변수를 대상으로 산술 연산자를 사용했을 때, 산술연산을 위해 JS 엔진은 두 자료형을 공통된 자료형으로 통일해버린다. (혹자는 이를 JS의 유연성이라며 칭찬할 수 있지만, 쓰다보면 사실 암시적 형변환 때문에 고생스러운 경우가 더 많다)

산술 연산자에 의한 암시적 형변환은 + 연산자에 의한 경우와 그 외 다른 연산자에 의한 경우 두 가지로 나눌 수 있다.

+ 연산자에 의한 암시적 형변환

서로 다른 자료형을 가지는 변수를 + 연산자로 연결했을 때, JS 엔진Boolean < Number < String의 우선 순위에 기반해 암시적 형변환을 수행한다. 만약 연속적으로 + 연산자를 사용한 경우, 다른 자료형을 만나기 전까지는 일반적인 + 연산자로 동작한다.

+ 연산자에 의한 암시적 형변환 우선 순위 : Boolean < Number < String

// 우선순위에 의한 형변환 
Number + Boolean // Number
Number + String // String
Boolean + String // String

// 실제 String을 만나기 전까지는 일반적인 + 연산자로 동작한다.
7 + 7 + 7; 			// = 21  
7 + 7 + "7"; 		// = 147  
"7" + 7 + 7; 		// = 777

그 외 산술 연산자(-,*,/,%)에 의한 암시적 형변환

+ 외의 산술 연산자는 + 연산자의 우선 순위와는 달리 다른 자료형의 두 변수에 사용 시 두 변수 모두를 Number 자료형으로 변환하고 계산을 수행한다.

-,*,/,% 연산자에 암시적 형변환 우선 순위: 모든 변수를 무조건 Number 자료형으로 형변환

//// * 외에 모든 다른 연산자(-,/,%)도 동일하게 작동한다.
String * Number 	// Number
String * String 	// Number
Number * Number 	// Number
String * Boolean 	// Number
Number * Boolean 	// Number1031* false; 	// 0
1031 * true; 		// 1031

느슨한 비교 연산자(==)에 의한 암시적 형변환

서로 다른 자료형을 가지는 변수== 연산자로 비교할 때, JS 엔진은 양 측의 두 변수를 공통된 자료형으로 변환한 후 엄격한 비교 연산자인 ===를 수행한 결과를 리턴한다.

만약 =====의 차이점에 대해 잘 모른다면, == vs ===를 참고하자.

느슨한 비교연산자로 서로 다른 자료형을 가지는 변수를 비교하는 경우 발생하는 암시적 형변환 규칙은 피연산자의 자료형에 따라 갈리며, 다른 우선순위 규칙에 비해 복잡한 편이다.

느슨한 비교 연산자(==)에 의한 암시적 형변환 : 피연산자의 자료형에 따라 형변환 수행
피연산자 중 String/Booelan 있는 경우 : String/Booelan -> Number 형변환
피연산자 중 Null/Undefined 있는 경우 : 양측이 모두 Null이나 Undefined인 경우에만 참
피연산자가 기본형객체(참조형)를 비교하는 경우 : 객체기본형으로 강제 형변환.

1 == 1            	// true
"1" == 1          	// true
1 == '1'          	// true
0 == false        	// true
0 == null         	// false
0 == undefined    	// false
null == undefined 	// true

위에 적어 둔 규칙 외에도 많은 사항이 있다. 예를 들어 두 피연산자 기본형객체(참조형)를 비교할 때 객체가 빈 배열이라면 숫자로 강제 변환한다든가, 피연산자 중 하나의 앞에 ! 연산자가 있는 경우 Boolean 형태로 강제 변환한다는 등의 내용이다. 이러한 내용을 모두 외울 필요는 당연히 없다! 개발자가 알지 못하게 암시적으로 형변환을 수행하는 느슨한 비교 연산자인 == 대신 엄격한 비교 연산자 ===을 사용하면 암시적 형변환 문제에서 벗어날 수 있기 때문이다.

이중 부정(!!)에 의한 암시적 형변환

암시적 형변환의 마지막 대표 케이스는 변수 앞에 !! 이중 부정 연산자를 사용한 경우이다. JS 엔진은 변수 앞에 !! 이중 부정연산자를 마주하면 해당 변수를 무조건 Boolean 자료형으로 강제 변환한다.

이중 부정 연산자(!!)에 의한 암시적 형변환 : Boolean으로 강제 변환

이중 부정 연산자에 의한 암시적 형변환은 주로 JS에서 false로 여겨지는 Falsy 값들을 활용하여 if문을 분기하는데 자주 사용된다.

JS Falsy 값: 0인 숫자, null, undefined, NaN, 빈 문자열, 빈 객체
Falsy 값 외는 모두 true로 판단됨

function check(variable) {
  if (!!variable) {
    console.log(variable);
  } else {
    console.log('잘못된 값');
  }
}
check(null); 		// 잘못된 값
check(3.14); 		// 3.14
check(undefined); 	// 잘못된 값
check(0); 			// 잘못된 값
check('Good'); 		// Good
check(''); 			// 잘못된 값
check(NaN); 		// 잘못된 값
check(5); 			// 5

명시적 형변환의 두 종류

앞서 말했듯, 명시적 형변환개발자가 해당 변수의 자료형을 변환할 의도를 가지고 코드를 작성하는 경우를 지칭한다. 명시적 형변환의 두 방법은 해당 변수를 특정 자료형의 생성자로 감싸는 방법자료형을 변환할 수 있는 특별한 함수를 사용하는 방식이 있다.

특정 자료형 생성자를 사용한 명시적 형변환

변수를 Object(), Stiring(), Booelan(), Number() 등의 특정 자료형의 생성자로 감싸는 경우, 개발자는 변수를 특정 자료형으로 쉽게 변환할 수 있다.

let trans = 100; 			//Number
Object(trans); 				//100
console.log(typeof trans); //Object
String(trans); 			   //”100"
console.log(typeof trans); //String
Boolean(trans); 			//true
console.log(typeof trans); //Boolean

자료형 변환 함수를 사용한 명시적 형변환

변수.toString(), 변수.toNumber(), 변수.toBoolean() 등의 특별한 자료형 변환 함수를 사용하여 변수를 특정 자료형으로 변환할 수도 있다.

// 모든 자료형 -> String
변수.toString()
숫자.toString(base) // base 진법의 문자열로 해당 숫자 변환 디폴트 = 10

// 모든 자료형 -> Number
undefined.toNumber() // NaN
null.toNumber() // +0
true.toNumber() // 1
false.toNumber() // +0

// 모든 자료형 -> Boolean
falsy값.toBoolean() // false
그 외 값.toBoolean() // true

그 외에도 String 자료형에 제공되는 parseInt(), parseFloat() 등의 특별한 함수를 사용해 자료형을 변환하는 방법도 있다.

// 문자열 -> 숫자
parseInt("문자열") // 문자열이 정수 외 포함시 NaN 반환
parseFloat("문자열") // 문자열이 정수 외 포함시 NaN 반환

나가며

앞서 알아본 암시적 형변환의 세 가지 케이스를 알고 JS를 사용하면, 개발자의 의도와 부합하지 않는 형변환이 일어났을 경우, 해당 지점을 쉽게 파악하고 해결할 수 있을 것이라 기대된다. 협업을 하는 환경에서는 암시적 형변환을 코드에 의도적으로 이용하는 것을 지양하고, 만약 의도적으로 자료형을 변경해야하는 경우 명시적 형변환을 수행해야 한다.

0개의 댓글