Javascript 의 클로저는 보통 Scope 와 같이 기술되는 특징적인 개념이다.

그 이유는 Closure 라는 개념이 Javascript 의 특징적인 Nested Scope 개념을 이용하기 때문이다.

 

다음 예제를 확인해보자.

 

위의 예제에서 함수 foo 는 innerFoo 의 실행 결과를 반환한다. outerFoo() 함수가 nestedFunction 을 return 해주고 있기 때문이다. 

이런 방식의 호출을 클로저(Closure) 라고 하며, 클로저로 정의된 innerFoo 함수는 외부 함수인 outerFoo 의 변수에 접근할 수 있기 때문에 Side effect 관리가 용이하며 정보 은닉(Private) 의 특성을 지닌다.

 

아울러 이렇게 정의된 outerFoo 는 innerFoo 를 위한 언어적 환경(Lexical environment) 를 제공하게 되기 때문에, 디자인 패턴적으로 높은 유연도를 가질 수 있게 된다. 

 

가령, outerFoo 를 innerFoo 를 위한 Factory 처럼 사용하거나 outerFoo 에 Parameter 를 받아 "독립적인 객체" 와 같은 환경을 만들거나 Singleton 처럼 사용할 수도 있다.

 

클로저의 중요한 특징 중 하나는 Scope Chain 을 이해하는 것이다.

근본적으로 Nested Scope 로 정의되는 Closure 는 3가지 종류의 Scope 를 가질 수 있으며 이를 순차적으로(Chaining) 접근하게 된다.

 

코드를 위와 같이 조금 변경해보았다.

 

(1) Local scope

 

(2) Outer function scope

 

(3) Global scope

 

위의 코드에서 Closure 는 위와 같은 3가지의 Scope 를 전부 가질 수 있으며,

동일한 이름의 변수에 대해서는 우선순위에 따라 다른 Scope 의 변수를 가리는(Hide) 모습을 볼 수 있다.

 

위와 같이 Closure 함수의 실행은 Scope 에서 Scope 로 전이되며 Scope 내에서 Scope 를 다시 선언하는 Scope chain 을 생성하는 과정이라 할 수 있다.

 

클로저를 이해하는 건 어렵지않으며, 중요한 것은 Scope chaining 을 이해하는 것이다.

 

주로 Javascript 의 유사한 동작을 패턴화 시키고, 그에 따른 독립적인 환경의 격리(private)가 필요할 때 사용하곤 한다.

 

 

다른 언어들과 마찬가지로 Javascript 역시 Scope 를 갖고 있으며, 이를 기본적으로 이해하는 것이 아주 중요하다.

 

Javascript 의 Scope 에는 다음 2가지가 있다.

 

(1) Local scope

지역 스코프를 말하며, Braclet({}) 안에서 정의되는 항목으로 정의된 해당 범위 내에서만 변수의 사용을 허용한다.

다른 범위에서 참조가 불가능하다.

 

(2) Global scope

전역 스코프를 말하며, 바닐라 자바스크립트에서 일반적으로 Braclet({}) 에 포함되지 않도록 정의된다.

전역으로 선언된 변수는 Window 객체로 포함되어 웹페이지 내에서 어디서든 참조가 가능하다.

 

그리고 응용된 Scope 로 Javascript 에서는 Nested Scope 라는 개념을 가질 수 있다.

 

(3) Nested Scope

Scope 내에서 별도의 Scope 를 정의한 경우 바깥쪽 Scope 에서 안쪽 Scope 에 접근이 불가능하지만 안쪽 Scope 에서는 바깥쪽 Scope 의 변수에 접근이 가능하다. 가령 다음과 같은 경우를 보자.

 

outerFoo() 함수의 출력 결과는 함수 내에서 innerFoo를 호출하기 때문에 70이 된다. innerFoo 함수에서 outerFoo 의 변수에 접근해서 곱하고 있는 모습이다. Nested Scope 에 의해 그 역은 성립되지 않는다.

이를 Lexical Scope 라고 하는데, 이는 변수나 함수가 문맥적으로 정의된 곳(Callee) 의 Context 를 참조한다는 일종의 원칙이다.

(이에 대한 대칭점으로 오래된 언어들에는 Dynamic Scope 라는 개념이 있고, 이는 변수나 함수가 불려진 곳(Caller) 의 Context 를 참조하는 개념이다.)

 

 

Javascript 의 Scope 는 기본적인 개념이라 익숙하면서도 자바스크립트의 특징적인 개념 중 하나이며, 중요한 개념인 Closure 를 이해하는 데 필수적이므로 잘 익혀두도록 하자.

 

 

구글 Protobuf 는 강력한 데이터구조이며 환경간 이식성이 뛰어나고 패킷으로 사용할 때, 자체의 성능(통신 속도 및 작은 패킷 크기)이 뛰어나지만, 정해진 형식이 있다보니 사용에 있어서 알아두어야할 점들이 몇가지 있다.

 

실무에서 사용하면서 알아두어야 했던 점들 및 특징적인 점들 몇가지를 정리해보았다.


1. protobuf 는 패킷간 상속과 추상화를 지원하지않는다.

프로토버프를 도입하기 가장 꺼려지는 이유인데, protobuf 의 Data Structure는 상속과 추상화와 같은 생산성을 위한 개발자들의 구조를 부정한다.

Protobuf 는 애초에 범용(?) 목적으로 설계되었다기 보다는 확실한 단일 목적에 대해 Compact 하게 설계된 Data Structure 이다.

즉, 확실히 의미를 갖는 필요한 데이터만 저장할 수 있게 되어있으며, 그렇기 때문에 Stream 으로 사용할 시 필요한 정보만 주고받는 효율성을 이점으로 취할 수 있는 반면, 데이터를 담는 데 있어서 유연하지 못하다.

 

그렇기 때문에 프로토콜 버퍼를 패킷으로 통신을 해야 한다면 모든 패킷에 필요한 정보들을 분류해서 정의해주는 것이 필요하다.

 


2. protobuf 의 패킷 넘버링은 생각보다 엄격하지않다. 하지만 패킷의 순서는 매우 중요하다.

다음과 같은 에러 처리를 위한 프로토콜 버퍼 Data Structure가 있다고 가정해보자.

위의 데이터 구조에서 time_stamp 패킷의 넘버링을 4로 바꿔도 무방하다. 프로토콜 버퍼에서 구조 내에서 중요한 것은 패킷들의 순서를 지키는 일이다.

다만, Protocol Buffer 를 enum 형태로 정의해서 쓰는 경우라면 조금 얘기가 다른데,

위와 같은 Enum 패킷에서는 numbering 이 의미를 갖는다. enum 의 경우 넘버링이 Enum 클래스의 ordinal 과 동치되기 때문에, Compile 해서 사용할 경우 패킷이 다르다면 예기치 못한 에러가 발생할 수 있다.

 

 

3. Protobuf 구조가 프로토콜로 정해졌다면 데이터 구조는 변경하지 않는 것이 좋다.

통신에 있어서 Protobuf 를 사용하는데, 기존 데이터 구조가 삭제 또는 변경된다면 그 구조를 삭제 & 변경하는 것이 아니라 새로 패킷을 추가하는 편이 좋다.

그 이유는 하위호환성 때문으로, 통신하는 양쪽의 Protobuf 빌드가 항상 동기화가 완벽하다면 문제가 없지만, 개발을 하다보면 버전이 달라질 수밖에 없다.

이 때 문제를 방지하기 위해 데이터 구조의 크기를 늘리는 방법을 선택해야 한다.

하지만 패킷의 크기가 커질지는 염려하지 않아도 된다. Protobuf 의 특징 상 입력되지않는 패킷은 보내지않도록 퍼포먼스 측면에서 최적화가 지원된다.

 


4. 구글이 지원해주는 protobuf 라이브러리가 있으며, 이를 사용하면 프로토버프의 사용이 매우 편리해진다. 

다음 링크를 참조하자.

https://github.com/protocolbuffers/protobuf

 

protocolbuffers/protobuf

Protocol Buffers - Google's data interchange format - protocolbuffers/protobuf

github.com

protobuf 라이브러리는 언어별로 필요한 기능들을 유틸리티 형태로 지원한다.

아주 방대하니 전체를 쓸 생각보다는 환경에 맞게 필요한 만큼만 모듈을 가져다 쓰는 것이 좋다.

또한 protobuf 라이브러리에는 proto 파일 내에서 사용할 수 있는 공통 protobuf 형식들도 정의되어 있으므로 참고하는 것이 좋다. 
가령 proto 파일 내에서 Collection 이나 timestamp 등의 기능을 사용할 수 있도록 정리되어있다. 

 

 

5. 당연한 얘기지만 proto 파일의 주석조차 compile 결과로 빌드된 소스에 포함 된다. 

만약 소스 자체로 어떤 스크립트가 실행되어야 한다면 환경에 주의하자.

주석에 한글 특수문자가 포함된 proto 파일을 자동화 스크립트로 돌리다가 문제가 생기는 일이 더러 있었다.

 

 

프로토콜 버퍼는 구글이 지원하고 있는 직렬화방식이고 강력하며 쓰임새도 다양하다.

하지만 현재로써는 아는만큼 사용할 수 있는 도구임이 분명하다. 사용에 있어 유의하고 항상 공식 지원을 참고하는 것이 좋겠다.

+ Recent posts