위 사진은 Stack Overflow에서 진행한 언어 사용 순위이다.
javascript는 근 몇년간 계속 가장 인기 있는 언어 1위를 지켜왔을 만큼 사람들이 많이 사용하는 언어이다.
하지만 javascript를 사용하다 보면 왜 이렇게 동작하는지 이해되지 않는 부분들이 하나씩 보이기 시작한다.
자바스크립트를 공부하면서, 또는 직접 사용해보면서 느낀 자바스크립트에서 주의할 점, 개선해야 할 점들을 개인적으로 정리하여 3개로 압축해보았다.
이 글에서 말하고 싶은 자바스크립트의 함정 세 가지는
이다.
위 올려둔 사진들은 자바스크립트의 너무도 유연한 구조가 가져오는 단점들을 드러내고 있다.
많은 경우, 이 문제는 연산 중 일어나는 암묵적 형변환 때문에 발생한다.
1 == "1";
이렇게 다른 타입의 피연산자를 이용해 연산할 때, 다른 프로그래밍 언어라면 연산이 되지 않도록 막아두는 것이 일반적일 것인데, javascript는 이를 허용하여 더욱 유연하게 처리한다.
그렇지만 이런 처리는 사람의 직관을 벗어나는 범위에서 동작하는 경우가 있기에 예상치 못한 버그를 만들어낼 수 있다.
따라서, 더욱 유연한 연산을 위해 설계된 암묵적 형변환으로부터 초래되는 단점들이 있음을 인지하고,
===
)를 적극적으로 사용하거나하는 것이 바람직할 것이다.
예를 들어 다음과 같은 함수가 있다고 해보자.
function sum(x, y) {
return x + y;
}
이 함수는 두 개의 파라미터 x와 y를 받아 둘의 합을 return하는 함수이다.
만약 다음과 같이 함수를 호출하면 어떻게 될까?
sum(1, 2); // 3
sum(); // NaN
sum(1); // NaN
sum(1, 2, 3, 4, 5); // 3
sum("1"); // "1undefined"
sum("1", "2"); // "12"
(출력된 결과의 값이 제대로 된 것인지 아닌지는 차치하고서라도) 놀랍게도 위 모든 경우에서 에러 없이 정상 작동된다.
위에서 정의한 함수는 두 개의 숫자 값을 입력하여 하나의 숫자 값을 출력하도록 의도한 것이었을 텐데, 함수에 1개의 값을 입력해도, 2개의 값을 입력해도, 5개의 값을 입력해도, 심지어 값을 입력하지 않아도 어떠한 결과가 나오는 것을 확인할 수 있다.
이런 파라미터 입력의 유연성을 통해 다른 유용한 기능을 개발하는 데에 도움을 얻을 수 있을지는 몰라도, 큰 규모의 개발에서는 이와 같은 유연성이 독으로 작용할 가능성이 크다.
자바스크립트는 이상하리만큼 예외를 적극적으로 던지지 않는다.
예를 들어 아래 경우를 보자.
var person1 = {
_name: "Yechan",
get name() { return this._name; }
}
console.log(person1.name); // "Yechan"
person1.name = "Thomas";
console.log(person1.name); // "Yechan"
var person2 = {
_name: "Yechan",
set name(value) { this._name = value; }
}
console.log(person2.name); // undefined
위 두 경우에서는 모두 예외가 발생하지 않는다.
첫 번째 경우에서는 setter가 없는 프로퍼티에 강제로 값을 대입하려 하였으나, 아무런 피드백 없이 값이 바뀌지 않은 것을 볼 수 있고,
두 번째 경우에서는 getter가 없는 프로퍼티를 강제로 읽어오려 하였으나, undefined만을 반환하여 person2에 name 프로퍼티가 있는지에 대한 추가적인 정보 하나 없이 정상적으로 코드가 실행되었다.
web 환경을 염두에 두고 만들어진 언어이다보니, 예외보다는 null이나 undefined을 반환하는 방법 등을 더욱 선호하는 듯 하나, 이는 어디에서 오류가 발생했는지 알기 어렵게 함으로써 디버깅을 어렵게 하고, 런타임에 가서야 오류가 발생했음을 확인하게 되는 경우가 생긴다.
null이나 undefined를 반환하더라도 그 값이 올바르지 않은 값이므로 프로그램이 정상적으로 동작하지 않을 확률이 높으므로, 이럴 경우에는 null, undefined를 반환하는 것보다는 확실하게 예외를 던지고 그 예외를 처리하는 것이 더 나은 품질의 개발을 하게 할 수 있을 것이라고 생각한다.
자바스크립트는 정말 많은 곳에서, 정말 많은 시간 동안 사용되어 왔지만, 이상하리만큼 자바스크립트는 그 명성만큼의 표준 라이브러리를 지원하지 않는다.
물론 자바스크립트 전역 객체로서 지원하는 Number
, Math
, RegExp
, JSON
, Map
과 같은 built in object들이 있기는 하지만, 아직까지도 지원되는 라이브러리의 수가 그 정도밖에 안된다는 사실이 놀랍다.
또한 물론 stdlib-js와 같은 표준 라이브러리의 개발 시도는 있는 것으로 보이나, 아직 버전이 0으로 시작하는 초기 개발 버전이다.
https://docs.python.org/3/library/
다른 언어 중 python의 경우를 예로 들어보면, datetime
, calendar
, collections
, heapq
, math
, shutil
, csv
, os
, time
, logging
, multiprocessing
, json
, html
, http
, locale
, tkinter
, unittest
, trace
, sys
등등등… 다 써보지도 못하고 죽을 정도로 아주 다양한 모듈들을 공식으로 지원한다.
Golang의 경우도 예로 들어보면, 여러 종류의 패키지들이 종류에 맞춰 잘 정리되어 있는 것을 볼 수 있다.
C++ 또한 STL을 통해 빠르게 개발할 수 있고
https://docs.oracle.com/javase/8/docs/api/allclasses-frame.html
자바 또한 세기 힘들 정도의 라이브러리를 제공한다.
이 정도만 살펴보아도 자바스크립트가 시대에 역행하는 건가 하는 생각이 들 정도로 의아하지만,
때문에 변화가 쉽지 않은 것 같다는 생각도 든다.
따라서 체계적이고 강력한 표준 라이브러리의 부재로 인해
과 같은 문제가 있다고 할 수 있겠다.
다행히, 위 문제들은 ES6의 여러 기능들과 ‘use strict’
, 그리고 typescript의 사용으로 인해 어느 정도 피할 수 있다.
다만 레거시 프로젝트에 손을 대거나, 협업을 하는 경우 등등을 생각해보면, 모든 환경에서 ES6, ‘use strict’
, typescript를 사용할 수는 없다.
따라서 자바스크립트에 잠재적인 문제가 있음을 인지하고 그에 맞게 대응하는 점이 최선이라고 할 수 있겠다.
이와 같이 자바스크립트가 가지는 3가지의 단점들에 대해 정리해보았는데, 개인적인 의견이니만큼 이 글을 읽고 있는 여러분의 생각은 조금 다를 수도 있겠다.
만약 다른 의견이 있다면 댓글로 공유 바라며 글을 마친다.
모던 자바스크립트 입문 (이소 히로시, 길벗출판사)
Effective Javascript (데이비드 허먼, 인사이트)
Stackoverflow 2023 Developer Servey (https://survey.stackoverflow.co/2023/#technology-most-popular-technologies)