본문 바로가기

Web

Java 개발자 입장에서 보는 JavaScript

0. 들어가며


자바와 자바스크립트는 사실 이름만 비슷할 뿐 전혀 다른 언어라고 해도 과언이 아니다. 변수 선언시 자료형을 명시하지 않고, 코드가 간결하며, 함수를 1급객체로 취급한다. 이런점에서 보면 자바스크립트는 자바보다는 오히려 최신언어인 파이썬, 스위프트 등과 더 가까운 모습을 보인다.
하지만 그럼에도 난 자바 (초보)개발자다. 가장 초기에 배운 언어도 자바고, 자주 쓰는 것도 자바고, 알고리즘 문제도 자바로 푼다. 그렇기 때문에 어떤 언어를 배우던 항상 자바를 중심에 두고 다른 언어와 비교하며 학습한다. 본 글도 자바에 대한 애정이 듬뿍 들어가있다. 큰 틀에서는 자바스크립트에 대한 학습내용이지만, 거의 모든 부분에 "자바"라는 단어가 들어가며 각 개념들을 자바와 비교해가며 해석하고 있다.
또한 스스로 배운 내용을 정리하고자 함이 1차적인 목표이기 때문에, 설명이 구체적이지 않고 간결하게 작성했으며, 본 글을 통해 모든 내용을 이해하기 보다는, 간단한 힌트, 실마리를 통해 연쇄적으로 다른 내용들을 기억할 수 있도록 하기위한 요약글에 가깝다고 할 수 있을 것 같다.

1. 변수


자료형

변수에서 자바스크립트의 자바와의 가장 큰 차이점은 자료형을 미리 정해줄 필요가 없다는 것이다. 사용자는 모든 자료형에 대해서 var 키워드로 선언하며 구체적인 타입은 실행환경에서 내부적으로 정해진다. 이러한 특성을 가진 프로그래밍 언어를 어려운말로 Loosely typed language라고 한다. 반면에 자바나 C처럼 명시적으로 타입을 지정해줘야하는 언어를 Strongly typed language라고 한다.
게다가 자바스크립트는 자바에 비해 자료형의 숫자또한 적은 편인데, 이들은 다음과 같은 7가지의 형태로 표현된다.

  • Boolean
    자바의 "boolean"과 동일
  • Number
    자바의 int, long, double 등과 같이 정수, 실수를 표현하는 모든 자료형들이 Number로 표현된다.
    정수만을 표현하기 위한 자료형은 없으며, NaN(Not a Number)이라는 특별한 값을 가지고 있다.
  • String
    자바와 동일하며 마찬가지로 "immutable"이다
  • Null
    자바의 null값과 동일하지만, 자바에서 String과 대부분의 객체에서 초기값을 지정하지 않을 시, null 값을 초기화하는 반면에, 자바스크립트에서는 후술할 Undefined라는 새로운 자료형을 할당한다.
  • Undefined
    값을 할당하지 않은 변수는 Undefined 자료형을 갖는다.
  • Object
    자바의 객체와 동일
  • Symbol
    추가예정

변수의 범위

"대부분의 언어와는 달리 자바스크립트의 변수는 블록 수준(Block-Level)이 아닌 함수 수준(Function-Level) 의 범위를 갖는다."

본 내용은 위와같은 단 한 문장으로 요약할 수 있지만, 기존 자바에서 당연한듯 사용했던 핵심적인 부분을 관통하고 있기 때문에 익숙해지기 쉽지 않았다. 자바에서 블럭단위, 즉 {}안에서 생명주기를 갖던 변수들은 이제 블럭 밖에서도 소멸되지 않는다.
.

즉 위와같이 자바 프로그래머들에겐 눈을 의심케하는 결과가 발생할 수 있다. (참고로 위 사진에서 변수 i 역시 소멸되지 않는다)

이러한 사실을 망각하고, 블럭안에서 무분별하게 중복된 이름의 변수를 선언하다가는 원치않게 같은이름의 전역변수의 값을 변경시킬 수 있다. 이는 또한 실행과정에서 어떠한 오류도 발생시키지 않기 때문에, 더욱 골치아픈 문제로 번질 우려가 있다. 그렇기 때문에 자바스크립트에서 변수를 선언할 때는 항상 사용범위를 꼼꼼히 체크하고, 되도록이면 동일 이름의 변수선언을 지양해야 할 것이다.

호이스팅

자바스크립트의 함수 내에서 변수 선언문은 항상 최우선으로 해석된다.

호이스트란 변수나 함수가 범위에 따라서 선언과 할당으로 분리되는 것을 뜻한다. 다음 예제를 통해 보면 쉽게 이해할 수 있다.


function Test() {  
    console.log("name : " + name); // name : undefined  
    var name = "Wan";  
    console.log("name : " + name); // name : Wan  
}  

자바에서 위와같이 작성한다면 윗 줄에서 name 변수에 대한 선언이 없으므로, 첫 출력문에서 컴파일 오류가 발생할 것이다. 하지만 자바스크립트에서는 문제없이 실행되며 결과 역시 위와같이 출력된다.

function Test() {  
    var name;  
    console.log("name : " + name); // name : undefined  
    name = "Wan";  
    console.log("name : " + name); // name : Wan  
}  

좀 더 이해를 돕기 위한 코드다. 즉, 자바스크립트에선 위 두가지 코드는 정확히 같은 동작으로 구현된다. 또한 후술할 함수 역시 변수와 동일방식으로 호이스팅 된다.

개인적으로 이러한 코드를 남발하면 협업 측면에서 굉장히 큰 문제가 생길 수 있다고 생각한다. 그렇기 때문에 웬만하면 호이스트 되더라도 TDZ(Temporal Dead Zone) 내에서 보호되는 let이나 Const를 사용도록 하자.

한가지 유의할 점은, 같은 이름의 변수나 함수가 선언될 경우, 순서와 상관없이 함수의 선언이 변수의 선언을 덮어씌워 버린다는 것이다. 그렇기 때문에 같은 이름의 변수, 함수 선언시 주의해야 하며, 위에도 설명했지만 가장 좋은 방안은 같은 이름의 변수/함수를 사용하지 않는 것이 되겠다.

2. 함수


함수를 1급객체로 취급

1급객체?

함수 역시 변수 못지 않게 자바와 어마어마한 차이가 존재한다. 그 중에서도 가장 큰 차이점은 자바스크립트가 함수를 1급 객체로 취급한다는 점이다.

1급 객체에 대해선 나중에 더 알아본 뒤 글을 쓸 생각이기 때문에, 간략하게 적고 넘어가려고 한다. 결론부터 말하자면 함수가 1급객체가 되면 반환값다른 함수의 매개변수로 사용될 수 있다. 특히 후자의 경우가 중요한데, 이를 통해 함수의 반환값을 매개로 또다른 함수를 중첩시키는 이른바 고차함수의 사용이 가능해지기 때문이다. 파이썬 등에서도 자주 사용되는 map, reduce 등이 이러한 고차함수에 속한다.

함수선언식 vs 함수표현식

먼저 함수선언식은 기존의 다른 프로그래밍언어에서 함수를 정의하는 방법과 거의 동일한 방식이다. 함수명과 함께 매개변수를 설정하고 블럭안에 함수의 내용을 담는다.(중요한 내용을 안적을뻔 했는데, 자바스크립트의 함수엔 반환값이 없다. 아무 값도 반환하지 않는 함수는 undefined를 반환한다)
함수는 위치와 상관없이 최우선으로 선언되며, 어느 구간에서든 호출할 수 있다.

이에 반해 함수표현식은 굉장히 낯선 함수 표현방법이다. 함수를 이름과 함께 선언하는 것이 아니라, 먼저 변수(혹은 상수)를 만들고, 생성된 이름없는 함수를 초기화하는 방식이다.
이 방법의 가장 큰 특징은 함수의 초기화 순서가 좌변에 정의된 형식에 종속된다는 것이다. 이런 형태는 각각 var, let, const가 선언, 할당되는 순서와 동일하다. 즉 담는 항목만 변수에서 함수로 바뀌었을 뿐 정확히 똑같이 동작한다. 호이스팅 역시 일어나며, 무엇보다 함수의 할당 자체가 문맥순서에 따르기 때문에 함수의 위치가 굉장히 중요해진다.

Arrow Function

Swift에서 클로저를 축약하는 방식과 유사하다. 자바에서도 람다식이라는게 있다는데 해당 부분은 배운 적이 없어서 나중에 확인 후 추가가 필요할 것 같다.
아무튼 대단한건 아니고 function 대신 뒤에 =>를 붙여서 표현하는 것이다. Swift 클로저 만큼은 아니지만 자바스크립트 개발자들도 어지간히 줄여쓰는걸 좋아하는 것 같다. 아무래도 언어의 특성상 매개변수나 반환값으로 사용될 여지가 많기 때문에 조금이라도 더 축약해보려고 노력하는 것 같다.
기능은 기존 Function으로 쓰던 때와 거의 동일한데, 한가지 달라진 점은, 초과된 매개변수를 담는 객체인 arguments의 사용이 불가능하다는 점이다. Arrow Function이 개발된 시기엔 이미 spread 표현식 때문에 더이상 arguments가 필요치 않아서 삭제됐다고 하는 것 같다.

끝으로


오랜만에 자바스크립트로 돌아와서 그런지, 너무 낯설고 적응이 안되서 간략하게 정리해봤는데, 역시나 쓰고나니 더 헷갈리기만 한다. 간단하게 느낀점은 자바스크립트는 자유로운 언어지만, 그만큼 뭔가 확실하지 않고 덜 직관적인 부분이 많은 것 같다. 최근 Swift언어를 배울 때는 너무 폐쇄적인 부분이 많아서 (특히 옵셔널) 답답했었는데, 자바스크립트의 자유로움에 시달리고나니, 진심으로 Swift의 폐쇄성이 그리워질 정도다.
배우는 언어를 늘려갈 수록, 하나를 배우면 예전에 배웠던 하나를 까먹어가는 기분이다. 아주 먼훗날에 시간이 되면 각 기능단위로, 다양한 언어에서 해당 기능이 어떠한 문법으로 사용되는지 통합적으로 정리해 봐야 겠다.

참고
(https://developer.mozilla.org/ko/docs/Web/JavaScript/Data_structures)

(http://chanlee.github.io/2013/12/10/javascript-variable-scope-and-hoisting/)

'Web' 카테고리의 다른 글

[JavaScript] EventLoop와 비동기 동작  (0) 2019.07.31
자주 묻는 Programming 질문들  (0) 2019.07.16