JavaScript
2021-12-14#
List#
- JS-Proxy
- Creating a proxy object
- A simple proxy example
- Proxy Traps
JS-Proxy#
Proxy는 특정 객체를 감싸 프로퍼티 읽기, 쓰기와 같은 객체에 가해지는 작업을 중간에서 가로채는 객체이다.
가로채진 작업은 Proxy 자체에서 처리되기도 하고, 원래 객체가 처리하도록 그대로 전달되기도 한다.
Creating a proxy object#
- target – 감싸게 될 객체로, 함수를 포함한 모든 객체 포함
- handler – 동작을 가로채는 메서드인 '트랩(trap)'이 담긴 객체로, 여기서
Proxy를 설정
A simple proxy example#
user 객체에 proxyUser로 접근할경우 get() 메서드가 호출된다.
user 객체를 변경하면 proxyUser에도 반영된다.
proxyUser 객체를 변경해도 user에 반영된다.
Proxy Traps#
The get() trap#
일반적으로 get() 메서드에 커스텀한 로직을 작성하여 property에 접근할 때 get() trap을 발생시킬 수 있다.
The set() trap#
set() trap 은 target의 property가 set될때 발생한다.
The apply() trap#
apply() trap은 함수가 호출될때 발생한다.
proxy trap의 작동 시점#
| 내부 메서드 | 핸들러 메서드 | 작동 시점 |
|---|---|---|
| [[Get]] | get | 프로퍼티를 읽을 때 |
| [[Set]] | set | 프로퍼티에 쓸 때 |
| [[HasProperty]] | has | in 연산자가 동작할 때 |
| [[Delete]] | deleteProperty | delete 연산자가 동작할 때 |
| [[Call]] | apply | 함수를 호출할 때 |
| [[Construct]] | construct | new 연산자가 동작할 때 |
| [[GetPrototypeOf]] | getPrototypeOf | Object.getPrototypeOf |
| [[SetPrototypeOf]] | setPrototypeOf | Object.setPrototypeOf |
| [[IsExtensible]] | isExtensible | Object.isExtensible |
| [[PreventExtensions]] | preventExtensions | Object.preventExtensions |
| [[DefineOwnProperty]] | defineProperty | Object.defineProperty, Object.defineProperties |
| [[GetOwnProperty]] | getOwnPropertyDescriptor | Object.getOwnPropertyDescriptor, for..in, Object.keys/values/entries |
| [[OwnPropertyKeys]] | ownKeys | Object.getOwnPropertyNames, Object.getOwnPropertySymbols, for..in, Object/keys/values/entries |
참고자료#
후기#
js proxy는 다양한 라이브러리와 프레임워크에서 사용되고 있다고 한다.
잘 활용해서 JS 환경에서 좀 더 클린하고 효율적인 코드를 작성할 수 있지 않을까 기대를 해본다.
2021-12-21#
List#
- Module Bundler
- Webpack
- Rollup
Module Bundler#
Module Bundler는 프론트엔드 개발자들이 주로 사용하며 JavaScript 모듈을 브라우저에서 실행할 수 있는 단일 JavaScript 파일로 묶는 데 사용되는 도구이다.
최신 모듈 번들러 예시
- webpack
- rollup
- fusebox
- parcel
다음과 같은 이유로 Module Bundler를 필요로 할 수 있다.
- 브라우저는 모듈 시스템을 지원하지 않지만 오늘날에는 완전히 사실이 아닙니다.
- 코드의 종속성 관계를 관리하는 데 도움이 되며 종속성 순서로 모듈을 로드합니다.
- 종속성 순서, 이미지 자산, CSS 자산 등으로 자산을 로드하는 데 도움이 됩니다.
Module?#
Module이란 프로그래밍 관점에서 특정 기능을 갖는 작은 코드 단위를 의미합니다.
JavaScript의 Simple Example
이 math.js 파일은 아래와 같이 3가지 기능을 갖고 있는 Module이다.
- 두 숫자의 합을 구하는 sum() 함수
- 두 숫자의 차를 구하는 substract() 함수
- 원주율 값을 갖는 pi 상수
이처럼 성격이 비슷한 기능들을 하나의 의미 있는 파일로 관리하면 Module로 취급된다.
Why Need Bundler#
설명을 위해 여러 JavaScript 파일로 구성된 웹 응용 프로그램을 구축하는 상황을 가정해보자
아래는 필요한 JavaScript 파일을 html에 추가하는 예시
각 파일에는 5개의 왕복 요청인 별도의 http 요청이 필요하다.
따라서 5개의 파일을 모두 하나로 결합할 수 있다면 더 효율적이다.
Bundle Problem#
- 포함될 "파일" 의 순서를 어떻게 유지?
- "파일" 사이에 일종의 종속성 순서가 있으면 좋음
- "파일" 간의 이름 충돌을 방지하려면?
- 번들 내에서 사용되지 않은 "파일"을 어떻게 확인?
다음과 같이 각 파일 간의 관계를 알면 이 모든 것을 해결할 수 있습니다.
- 어떤 파일이 다른 파일에 종속되어 있는지?
- 파일에서 노출되는 인터페이스는 무엇?
- 어떤 노출된 인터페이스가 다른 사람에 의해 사용되고 있습니까?
부여된 이러한 정보는 각각 제기된 문제를 해결할 수 있다.
따라서 우리에게 필요한 것은 파일 간의 관계를 설명하는 선언적 방법이며, 이는 우리를 JavaScript 모듈 시스템으로 이끈다.
CommonJS & ES6 Module#
CommonJS 또는 ES6 모듈은 우리가 의존하고 있는 파일과 파일에서 사용 중인 인터페이스를 지정할 수 있는 방법을 제공한다.
How Bundle?#
모듈 시스템에서 수집한 정보로 어떻게 파일을 함께 연결하고 모든 것을 캡슐화하는 번들 파일을 생성할까?
대표적인 2개의 Module Bundler를 사용
- webpack
- rollup
우리는 3개의 파일을 가지고 있다고 가정해보자
- circle.js
- square.js
- app.js
"웹팩 방식"#
"webpack 방식" 번들은 어떻게 생겼을까?
첫째, 가장 먼저 눈에 띄는 것은
Module Map이다. 모듈 이름을 함수로 래핑된 모듈 자체에 매핑하는 사전입니다.Module Map은 항목을 추가하여 모듈을 쉽게 등록할 수 있다.둘째, 각 모듈은 함수로 Wrapping 된다. 이 함수는 모듈 내에서 선언된 모든 것이 자체 내에서 범위가 지정되는 모듈 범위를 시뮬레이션합니다. 함수 자체를
Module Factory Function라고 합니다. 모듈이 인터페이스를 내보내고 다른 모듈에서 요구할 수 있도록 몇 가지 매개 변수를 사용한다.셋째, 어플리케이션이 시작되고
webpackStart는 모든 것을 함께 붙여주는 함수이다. 종종런타임이라고 하는 함수 자체는 번들에서 가장 중요한 부분이다.모듈 맵과입력 모듈을 사용하여 애플리케이션을 시작한다.
webpackStart require function과 module cache의 2가지를 정의한다.
require 기능은 CommonJS의 기능과 다르다.
require 구문은 exported interface를 module로 부터 반환한다.
예시: circle.js 라면 -> { default: function area(radius){ ... } } 반환
내보낸 인터페이스는 모듈 캐시에 캐시되므로 동일한 모듈 이름의 require를 반복적으로 호출하면 모듈 팩토리 함수가 한 번만 실행됩니다.
require가 정의된 상태에서 애플리케이션을 시작하는 것은 입력 모듈을 "요구"하는 것뿐입니다.
"롤업 방식"#
이제 "롤업 방식" 번들을 살펴보자.
- 첫째, 롤업 번들의 주요 차이점은 웹팩 번들에 비해 훨씬 작다. "webpack 방식"에 비해 모듈 맵 이 없으며, 모든 모듈은 번들로 "평평하게" 정의된다. 모듈의 래핑
function이 없다. 모듈 내에서 선언된 모든 변수/함수는 이제 전역 범위로 선언된다.
혹시 개별 모듈 범위에서 선언된 모든 것이 전역 범위로 선언된 경우 2개의 모듈이 동일한 이름의 변수/함수를 선언한다면?
- 롤업은 이름 충돌이 발생하지 않도록 변수/함수 이름을 변경한다.
- 예시에서
circle.js and square.js는 모두function area(){}모듈 내에서 선언 되었으며 번들될 때 충돌을 피하기 위해 두 함수와 그 사용법이 모두 이름이 변경된 것을 볼 수 있다.
모듈을 함수로 래핑하지 않는 부작용 중 하나의 동작이다
eval. 자세한 설명 은 문서를 참조
- 둘째, 번들 내 모듈의 순서가 문제가 있을 수 있다.
circle$area->square$area->console.log순서대로 작동하지만 temporal dead zone 때문에 PI전에 선언해야한다.
따라서 종속성 순서대로 모듈을 정렬하는 것은 "롤업 방식"에 중요하다.
대체로 "롤업 방식"이 "웹팩 방식"보다 나은 것 같아보인다. 모든 기능을 제거하여 더 작은 번들과 더 적은 런타임 오버헤드를 갖는 특징이 있다.
요약#
- 모듈 번들러 는 여러 JavaScript 모듈을 하나의 JavaScript 파일로 결합하는 데 큰 도움이 된다.
- "웹팩 방식"
- 모듈 맵 사용
- 함수를 사용하여 각 모듈을 래핑
- 모듈을 함께 연결하는 런타임 코드가 있음
- "롤업 방식"
- 더 평평하고 작은 묶음
- 모듈을 래핑하기 위해 함수를 사용하지 않음
- 순서 문제, 종속성을 기반으로 한 정렬 필요
- 순환 종속성이 작동하지 않을 수 있음
참고자료#
2021-12-28#
List#
- Micro Service
- Micro Service 6
- 마이크로 서비스 찬반
Micro Service#
마이크로서비스 아키텍처라고도 하는 마이크로서비스는 애플리케이션을 다음과 같은 서비스 모음으로 구성하는 아키텍처 스타일이라고 할 수 있다.
그림예시)

- 높은 유지보수 및 테스트 가능
- 느슨한 결합
- 독립적으로 배포 가능
- 비즈니스 역량을 중심으로 구성
- 소규모 팀 소유
마이크로서비스 아키텍처를 사용하면 크고 복잡한 애플리케이션을 빠르고 자주 안정적으로 전달할 수 있으며, 또한 조직이 기술 스택을 발전시킬 수 있다.
상황예시)
- 서버측 엔터프라이즈 애플리케이션을 개발 중입니다.
- 데스크톱 브라우저, 모바일 브라우저 및 기본 모바일 애플리케이션을 비롯한 다양한 클라이언트를 지원해야 합니다.
- 애플리케이션은 제3자가 사용할 API를 노출할 수도 있습니다.
- 웹 서비스나 메시지 브로커를 통해 다른 애플리케이션과 통합할 수도 있습니다.
- 애플리케이션은 비즈니스 로직을 실행하여 요청(HTTP 요청 및 메시지)을 처리합니다.
- 데이터베이스 액세스; 다른 시스템과 메시지 교환 HTML/JSON/XML 응답을 반환합니다.
- 응용 프로그램의 다양한 기능 영역에 해당하는 논리적 구성 요소가 있습니다.
문제#
애플리케이션의 배포 아키텍처
상황#
- 응용 프로그램에서 작업하는 개발자 팀이 있다
- 새로운 팀원은 신속하게 생산성을 발휘해야 한다.
- 응용 프로그램을 이해하고 수정하기 쉬워야 한다.
- 애플리케이션의 지속적인 배포를 연습하고 싶은 경우
- 확장성 및 가용성 요구 사항을 충족하려면 여러 컴퓨터에서 애플리케이션의 여러 인스턴스를 실행해야 한다.
- 새로운 기술(프레임워크, 프로그래밍 언어 등)을 활용하려는 경우
해결책#
느슨하게 결합된 협업 서비스 세트로 애플리케이션을 구성하는 아키텍처를 정의한다.
- 유지 관리 및 테스트 용이성 - 빠르고 빈번한 개발 및 배포 가능
- 다른 서비스와 느슨하게 결합 - 팀이 다른 서비스의 변경 사항에 영향을 받지 않고 다른 서비스에 영향을 주지 않고 대부분의 시간 동안 독립적으로 서비스 작업을 수행할 수 있습니다.
- 독립적으로 배포 가능 - 팀이 다른 팀과 협력하지 않고도 서비스를 배포할 수 있습니다.
- 소규모 팀으로 개발 가능 - 큰 팀의 높은 커뮤니케이션 헤드를 피하여 높은 생산성에 필수적
서비스는 HTTP/REST와 같은 동기 프로토콜 또는 AMQP와 같은 비동기 프로토콜을 사용하여 통신합니다.
서비스는 서로 독립적으로 개발 및 배포할 수 있습니다.
각 서비스에는 다른 서비스와 분리하기 위해 자체 데이터베이스 가 있습니다.
결과 컨텍스트#
이 솔루션에는 다음과 같은 많은 이점이 있다.
- 크고 복잡한 애플리케이션을 지속적으로 제공하고 배포할 수 있음
- 개선된 유지보수성 - 각 서비스가 상대적으로 작기 때문에 이해하고 변경하기 쉬움
- 더 나은 테스트 가능성 - 서비스는 더 작고 테스트하기 더 빠름
- 더 나은 배포 가능성 - 서비스를 독립적으로 배포할 수 있음
- 이를 통해 여러 자율적인 팀을 중심으로 개발 노력을 구성할 수 있다. 각(소위 두 개의 피자) 팀은 하나 이상의 서비스를 소유하고 책임이 있습니다. 각 팀은 다른 모든 팀과 독립적으로 서비스를 개발, 테스트, 배포 및 확장할 수 있습니다.
- 각 마이크로 서비스는 상대적으로 작습니다.
- 개발자가 이해하기 쉽게
- IDE는 개발자의 생산성을 더 빠르게 만듭니다.
- 애플리케이션이 더 빨리 시작되어 개발자의 생산성이 향상되고 배포 속도가 빨라집니다.
- 향상된 결함 격리. 예를 들어, 한 서비스에 메모리 누수가 있는 경우 해당 서비스만 영향을 받습니다. 다른 서비스는 계속해서 요청을 처리합니다. 이에 비해 모놀리식 아키텍처의 오작동 구성 요소 중 하나는 전체 시스템을 다운시킬 수 있습니다.
- 기술 스택에 대한 장기적인 약속을 제거합니다. 새로운 서비스를 개발할 때 새로운 기술 스택을 선택할 수 있습니다.
- 마찬가지로 기존 서비스를 크게 변경할 때 새로운 기술 스택을 사용하여 다시 작성할 수 있습니다.
단점#
이 솔루션에는 여러 가지 단점이 있다.
- 개발자는 분산 시스템 생성의 추가적인 복잡성을 처리해야 합니다.
- 개발자는 서비스 간 통신 메커니즘을 구현하고 부분적 오류를 처리해야 합니다.
- 여러 서비스에 걸친 요청을 구현하는 것이 더 어렵습니다.
- 서비스 간의 상호 작용을 테스트하는 것이 더 어렵습니다.
- 여러 서비스에 걸친 요청을 구현하려면 팀 간의 세심한 조정이 필요합니다.
- 개발자 도구/IDE는 모놀리식 애플리케이션 구축을 지향하며 분산 애플리케이션 개발에 대한 명시적인 지원을 제공하지 않습니다.
- 배포 복잡성. 프로덕션 환경에는 다양한 서비스로 구성된 시스템을 배포하고 관리하는 작업의 복잡성도 있습니다.
- 메모리 소비 증가.
마이크로서비스 아키텍처는 N개의 모놀리식 애플리케이션 인스턴스를 NxM 서비스 인스턴스로 대체한다. 각 서비스가 일반적으로 인스턴스를 격리하는 데 필요한 자체 JVM(또는 이와 동등한 것)에서 실행되는 경우 JVM 런타임의 M배에 달하는 오버헤드가 있습니다. 또한 Netflix의 경우와 같이 각 서비스가 자체 VM(예: EC2 인스턴스)에서 실행되는 경우 오버헤드가 훨씬 더 높다.
Micro Service 6#
1. 다중 구성 요소#
- 마이크로서비스로 구축된 소프트웨어는 정의에 따라 여러 구성 요소 서비스로 나눌 수 있다.
- 따라서 이러한 각 서비스는 애플리케이션의 무결성을 손상시키지 않고 독립적으로 배포, 조정 및 재배포될 수 있다.
(결과적으로 전체 응용 프로그램을 다시 배포하는 대신 하나 이상의 고유한 서비스만 변경하면 된다.) - 그러나 이 접근 방식에는 비용이 많이 드는 원격 호출(in-process 호출 대신), 더 세분화된 원격 API, 구성 요소 간 책임 재분배 시 복잡성 증가 등의 단점이 있다.
2. 비즈니스용으로 구축#
- 마이크로서비스 스타일은 일반적으로 비즈니스 기능과 우선 순위를 중심으로 구성된다.
- 각기 다른 팀이 UI, 데이터베이스, 기술 계층 또는 서버 측 논리에 대해 특정 초점을 맞추는 기존의 모놀리식 개발 접근 방식과 달리 마이크로서비스 아키텍처는 기능 간 팀을 활용한다.
- 각 팀의 책임은 메시지 버스를 통해 통신하는 하나 이상의 개별 서비스를 기반으로 특정 제품을 만드는 것이다.
3. 단순 라우팅#
- 마이크로서비스는 고전적인 UNIX 시스템과 다소 유사하게 작동한다.
- 요청을 수신하고 처리하고 그에 따라 응답을 생성한다.
- 메시지 라우팅, 구성 및 비즈니스 규칙 적용을 위한 첨단 시스템이 활용되는 ESB(Enterprise Service Buses)와 같은 다른 제품의 수와 반대이다.
- 마이크로 서비스에는 정보를 처리하고 논리를 적용하는 스마트 엔드포인트와 정보가 흐르는 덤 파이프가 있다고 말할 수 있다.
4. 탈중앙화#
- 마이크로서비스는 다양한 기술과 플랫폼을 포함하기 때문에 중앙 집중식 거버넌스의 구식 방법은 최적이 아니다.
- 마이크로서비스 커뮤니티는 분산 거버넌스를 선호한다.
(그 이유는 개발자가 유용한 도구를 생성하여 다른 사람들이 동일한 문제를 해결하는 데 사용할 수 있기 때문이다.) - 분산된 거버넌스와 마찬가지로 마이크로서비스 아키텍처도 분산된 데이터 관리를 선호합니다.
(모놀리식 시스템은 여러 애플리케이션에서 단일 논리 데이터베이스를 사용한다.) - 마이크로 서비스 애플리케이션에서 각 서비스는 일반적으로 고유한 데이터베이스를 관리한다.
5. 고장 방지#
- 다재다능한 아이처럼 마이크로서비스는 실패에 대처하도록 설계되었다.
- 여러 고유하고 다양한 서비스가 함께 통신하고 있기 때문에 서비스가 실패할 가능성이 있다.
(예: 공급자를 사용할 수 없는 경우). - 클라이언트는 가능한 인접 서비스가 작동하도록 허용해야 한다.
- 마이크로 서비스를 모니터링 하면 실패 위험을 방지하는 데 도움이 될 수 있다.
- 이런 요구 사항은 모놀리식 시스템 아키텍처에 비해 마이크로서비스에 더 많은 복잡성을 추가한다.
6. 진화#
- 마이크로서비스 아키텍처는 혁신적인 설계이며, 언젠가는 애플리케이션에 액세스할 수 있는 장치 유형을 완전히 예측할 수 없는 진화적인 시스템에 이상적이다.
- 많은 애플리케이션은 모놀리식 아키텍처를 기반으로 시작하지만 몇 가지 예상치 못한 요구 사항이 표면화됨에 따라, API를 통해 이전 모놀리식 아키텍처와 상호 작용하는 마이크로 서비스로 천천히 개선될 수 있다.
마이크로 서비스의 찬반#
마이크로서비스는 만병통치약이 아니며, 이를 구현하면 이전에는 암묵적으로 드러났지만 이제는 공개되지 않은 커뮤니케이션, 팀워크 및 기타 문제를 노출할 수 있다.
그러나 마이크로서비스의 API 게이트웨이는 빌드 및 QA 시간과 노력을 크게 줄일 수 있습니다.
- 한 가지 일반적인 문제는 서비스 간에 스키마/검증 논리를 공유하는 것과 관련된다.
- B가 다른 요구 사항을 가지고 있는 경우 일부 데이터가 유효한 것으로 간주하기 위해 A가 요구하는 것이 항상 B에 적용되는 것은 아니다.
- 가장 좋은 권장 사항은 버전 관리를 적용하고 공유 라이브러리에 스키마를 배포하는 것이다.
- 라이브러리에 대한 변경 사항은 팀 간의 토론이 될 수 있으며, 또한 강력한 버전 관리에는 종속성이 발생하여 더 많은 오버헤드가 발생할 수 있습니다.
- 이를 극복하기 위한 가장 좋은 방법은 이전 버전과의 호환성을 계획하고 외부 서비스/팀의 회귀 테스트 를 수락하는 것일 수 있다.
- 이는 다른 사람의 비즈니스 프로세스를 방해한 후에가 아니라 방해 하기 전에 대화를 나누도록 해야한다.
다른 모든 것과 마찬가지로 마이크로 서비스 아키텍처가 각 서비스에 적합한지 여부는 모두 장단점이 있기 때문에 요구 사항에 따라 다를 수 있다.
정리#
장점#
- 마이크로서비스 아키텍처는 개발자가 서비스를 독립적으로 개발하고 배포할 수 있는 자유를 제공한다.
- 마이크로 서비스는 상당히 작은 팀에서 개발할 수 있다.
- 다른 서비스에 대한 코드는 다른 언어로 작성할 수 있다.(많은 실무자가 권장하지 않음).
- 손쉬운 통합 및 자동 배포(Jenkins, Hudson 등과 같은 오픈 소스 지속적 통합 도구 사용)
- 개발자가 쉽게 이해하고 수정할 수 있으므로 새로운 팀원이 신속하게 생산성을 높일 수 있다.
- 개발자는 최신 기술을 사용할 수 있다.
- 코드는 비즈니스 기능을 중심으로 구성된다.
- 웹 컨테이너를 더 빨리 시작하므로 배포도 더 빨라진다.
- 애플리케이션의 특정 부분에 변경이 필요한 경우 관련 서비스만 수정하여 재배포할 수 있으며 전체 애플리케이션을 수정하고 재배포할 필요가 없다.
- 더 나은 오류 격리: 하나의 마이크로 서비스가 실패해도 다른 하나는 계속 작동한다.
(모놀리식 애플리케이션의 문제가 있는 영역 중 하나가 전체 시스템을 위험에 빠뜨릴 수 있음) - 쉽게 확장하고 타사 서비스와 통합
- 기술 스택에 대한 장기 약정 없음
단점#
- 분산 배포로 인해 테스트가 복잡하고 지루할 수 있다.
- 서비스 수가 증가하면 정보 장벽이 생길 수 있다.
- 이 아키텍처는 개발자가 내결함성, 네트워크 지연을 완화하고 다양한 메시지 형식과 로드 밸런싱을 처리해야 하므로 복잡성이 추가로 발생한다.
- 분산 시스템이므로 노력이 중복될 수 있습니다.
- 서비스의 수가 증가하면 전체 제품의 통합 및 관리가 복잡해질 수 있음
- 모놀리식 아키텍처의 여러 복잡성 외에도 개발자는 분산 시스템의 추가적인 복잡성을 처리해야 한다.
- 개발자는 서비스 간의 통신 메커니즘을 구현하는 데 추가 노력을 기울여야 한다.
- 분산 트랜잭션을 사용하지 않고 둘 이상의 서비스에 걸쳐 있는 사용 사례를 처리하는 것은 어려울 뿐만 아니라 다른 팀 간의 커뮤니케이션과 협력을 요구한다.
후기#
현재 아이랩팀은 모놀리식 어플리케이션의 형태로 구성이 되어있다.
서비스 증가 및 각 업무 도메인을 분산시키기 위해 마이크로 서비스가 필요해질 수 있다.
미리 많은 사례들과 마이크로 서비스의 기본 설계, 구조, 구축방향 등을 팀내에서 지속적으로 생각해놓고 정리해놓는것 또한 필요한 일이 아닐까 생각이 든다.