네로개발일기

개발자 네로의 개발 일기, 자바를 좋아합니다 !

'전체 글'에 해당되는 글 194건


반응형

 

🐥 MySQL 5.7

> show create table [table명];

 

 

출처

https://stackoverflow.com/questions/2433133/how-to-get-a-table-creation-script-in-mysql-workbench

 

How to get a table creation script in MySQL Workbench?

I am rolling back to MySQL GUI Tools' MySQL Query Browser since I can't find the shortcut to get a table's creation script in MySQL Workbench.

stackoverflow.com

 

728x90
반응형
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !

반응형

JSX

html 태그를 생성하는 자바스크립트 소스코드를 간결하게 입력할 수 있도록 자바스크립트 문법이 확장된 것

 

1) JSX 문법 예 

var s = <div><img src="image.png"/></div>;

 

=> React에서 다음과 같이 쓰인 코드는 @babel이라는 자바스크립트 컴파일러를 통해 다음과 같이 변환된다.

 

2) 위 jsx 문법 예제를 자바스크립트 소스코드로 변환한 결과

var s = React.createElement("div", null,
	React.createElement("img", {src: "image.png"})
);

프로젝트를 빌드할 때, 빌드 도구가 jsx 문법의 소스코드를 자바스크립트 소스코드로 자동 반환해준다.

 

확장자

jsx 문법을 포함하는 자바스크립트 파일의 확장자가 옛날에는 *.jsx, 최근은 *.js

 

DOM 객체 (Document Object Model)

웹 브라우저 내부에서 html 태그들은 객체 형태로 실행된다. 이 객체들을 DOM 객체라고 부른다. 즉, DOM 객체는 웹 브라우저 내부의 태그 객체이다.

 

VirtualDOM 객체

jsx 문법으로 구현된 자바스크립트 코드에서 생성한 html 태그 객체를 VirtualDOM 객체라고 부른다. 이 객체는 웹 브라우저 내부의 DOM 객체와 다르다. 

자바스크립트 코드에 의해서 생성된 VirtualDOM 객체들과 동일한 구조로, 웹 브라우저 내부 DOM 객체들을 변경하는 작업이 react.js 엔진에 의해 실행된다. 이 작업에 의해 jsx 문법으로 구현된 내용이 웹 브라우저 창에 그려지게 된다.

728x90
반응형
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !

반응형

 문제  동시 접속자 폭발

네트워크 소켓을 통해 최대로 커버 가능한 동시 접속자의 작업수는 1만개였다. 이때 당시는 사용자 수 = 프로세스 개수(혹은 쓰레드 개수)로 서버 인프라가 설계되어 CPU, 메모리 등 자원들이 사용되었다.

 해결  동시 접속에 특화된 Nginx를 쓰자!

효율적인 서버 자원(CPU, 메모리 등) 사용

1. Nginx 개요

세계에서 가장 많이 사용하고 있는 웹서버이다. (웹서버의 TOP2 아파치와 엔진엑스)

동시접속 처리에 특화된 웹 서버로, 가벼움높은 성능을 지향하고 있다.

Nginx는 요청에 응답하기 위해 비동기 이벤트 기반 구조이며 이는 Apache 서버의 스레드/프로세스 기반 구조와 대조적이다.

 

Nginx의 이벤트 기반(Event-Driven) 구조는 서버에 많은 부하가 생길 경우 성능을 예측하기 쉽게 해주며, 고정된 프로세스만 생성하고, 내부에서 비동기방식으로 작업들을 처리하기 때문에 스레드/프로세스를 효율적으로 처리할 수 있다.

 

* 웹 서버의 역할

1. 정적 파일을 처리하는 HTTP 서버

-  클라이언트가 정적 파일(HTTP, CSS, Javascript, 이미지)만 요청했다면 웹 서버가 직접 응답할 수 있다.

2. 응용프로그램 서버에 요청을 보내는 리버스 프록시

- 프록시는, 클라이언트와 서버 통신 중간에서 대신 통신을 해주는 서버를 의미한다.

- 포워드 프록시는, 내부망에 함께 있는 클라이언트가 인터넷을 통해 어딘가에 있는 서버로 요청을 보내려고 하면 이 요청을 받아 연결해준다. 클라이언트 앞단에서 처리!

- 리버스 프록시는, 내부망의 서버 앞단에서 요청을 배분하여 처리한다. 클라이언트가 리버스 프록시에 요청하면 프록시 서버가 배후 서버(reverse server, 응용 프로그램 서버)로부터 데이터를 가지고 온다. (nginx.conf 파일에서 location 지시어를 사용하여 요청을 배분한다.)

- WAS(Web Application Server)는 대부분 DB 서버와 연결되어 있으므로, WAS가 직접 통신하게 되면 보안에 취약해진다. 리버스 

 

Apache와 Nginx 차이?

과거 멀티 쓰레드를 사용하던 시절엔 Blocking I/O 방식으로 처리가 이루어진다. (*멀티 쓰레드: 하나의 프로그램에 동시에 여러 작업을 돌리는 작업으로, 프로세스 하나의 자원을 공유하다보니 처리 속도가 빠르다는 장점이 있지만, 한정된 프로세스 자원을 쪼개서 사용하는 만큼 쓰레드별로 자원을 효율적으로 분배해야 한다.)

동시 다발적으로 오는 작업에 부적합했다. 요청에 따라 쓰레드/프로세스를 생성하다보니 요청이 많아지거나 오랜 시간이 소요되는 작업에도 처리 방식이 무거워졌다. 

 

그래서 나온 방법 => Non-Blocking !

Non-Blocking 방식은 앞의 프로세스가 작업을 수행중이더라도, 다음 프로세스는 기다리면서 다른 작업을 할 수 있다.

Nginx는 Non-Blocking 방식을 사용하고 있다.

 

이에 따라 Apache와 Nginx의 차이점을 살펴볼 수 있다.

 

1) Apache

1995년부터 웹서버 기반 서버엔진.

Prefork와 Worker 방식으로 동작한다.

하나의 요청 당 서버에서는 하나의 프로세스(혹은 쓰레드)를 다룬다. 하지만 서버 내 CPU/메모리는 한정적임에 반해 프로세스(쓰레드)는 요청이 들어온 만큼 계속 생성/작업을 해 무리한 작업이 될 수 있다.

Process가 Blocking시, 프로세스 작업이 끝날 때까지 대기해야 한다.

주로 요청 하나당 프로세스(혹은 쓰레드) 하나가 쓰인다.

자원(CPU, 메모리 등) 사용이 유동적이다. (요청에 따라 쓰레드, 프로세스 할당 개수가 증감된다.)

서버내 자원(CPU, 메모리 등) 활용이 비효율적이다.

 

2) Nginx

2007년 오픈소스로 공개

프로세스를 효율적으로 활용함으로서 서버 자원을 최대한 활용하고, Event Driven을 활용한 비동기 Non-Blocking 방식을 선호하여 프로세스 작업이 끝날 때까지 대기하지 않아도 된다.

서버가 실행되면 쓰레드를 미리 생성한다. 클라이언트로부터 요청이들어오면 서버에서는 한정된 쓰레드 개수를 기반으로 요청을 처리한다. 하지만 요청이 더 많아질 경우, 늦게 들어온 요청은 잠시 큐에 대기를 하고 작업이 끝난 쓰레드는 큐에 대기하고 있는 요청을 처리한다.

 

2. Nginx 작동 과정

1. 쓰레드 개수(Thread Pool) 해당 스레드 풀 내에 한정된 자원만을 가지고 HTTP 요청에 대한 작업을 처리한다.

2. 요청에 대한 응답은 Nginx 내부에서 실행되고 있는 Worker Process에서 진행된다. Worker Process는 개발자가 따로 설정하지 않았다면 CPU에 맞게 자동으로 Worker Process가 생성된다.

3. Nginx는 Event Driven(비동기 처리방식)의 특성을 가지고 있다. Event Driven은 Event Loop 기반으로 요청에 대한 작업을 처리한다. (Event Loop에서 작업이 처리될 때, 비동기 방식으로 작업이 돌아간다.)

Nginx Event Driven 내에서 Event Handler에서 작업을 마치게 되면 완료된 순서대로 Queue에 쌒이고 Event Loop를 돌면서 Queue에 완료된 작업이 있는지 체크하면서 CPU가 IDLE한 상태가 없도록 활동한다. Queue에 완료된 작업이 있다면 클라이언트에 응답(Response)한다.

4. Queue에 있는 완료된 작업을 받아 클라이언트에 응답(Response)한다.

 

출처

https://kbs4674.tistory.com/126

 

Nginx 개념의 이해

글 시작 전 1. 해당 글은 단순 Nginx의 개념에 대한 설명글입니다. 2. Nginx를 활용한 자동배포(CD) 기능을 통해 편리하게 Ruby on Rails 프로젝트를 배포할 수 있습니다.  부록 AWS EC2+Nginx+Capistrano 지..

kbs4674.tistory.com

https://whatisthenext.tistory.com/123

 

Nginx 이해하기 및 기본 환경설정 세팅하기

NGINX Nginx의 개요 엔진엑스(Nginx)는 Igor Sysoev라는 러시아 개발자가 동시접속 처리에 특화된 웹 서버 프로그램이다. Apache 보다 동작이 단순하고, 전달자 역할만 하기 때문에 동시접속 처리에 특화

whatisthenext.tistory.com

 

 

728x90
반응형
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !

반응형

레거시 프로젝트가 Spring Mybatis로 되어있었고 DBMS는 Cubrid로 되어있었다. 이 프로젝트를 Spring JPA로 변경하기 위해 설정을 바꾸어 보았다.

 

🥑 Database: Cubrid 10.1.5.7809

🍒 Spring Boot version 2.6

🍇 Spring JPA, Spring Boot

🫐 Maven

 

pom.xml

    <repositories>
        <repository>
            <id>cubrid.release.repository</id>
            <url>http://maven.cubrid.org</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
    <dependencies>
    	...
        <dependency>
            <groupId>cubrid</groupId>
            <artifactId>cubrid-jdbc</artifactId>
            <version>10.1.5.7809</version>
        </dependency>
        ...
    </dependencies>

pom.xml파일에 repository와 dependency를 추가해준다. version을 잘 고려해서 넣으면 된다. (10.1.3.7765 버전 이상이어야 Spring JPA가 오류없이 작동하는 것 같다.) 

 

application.yml

spring:
  datasource:
    driver-class-name: cubrid.jdbc.driver.CUBRIDDriver
    url: jdbc:cubrid:[host 주소]:[port 번호]:[DB 이름]:public::?charSet=utf-8
    username: 
    password: 
  jpa:
    database-platform: org.hibernate.dialect.CUBRIDDialect

url, username, password만 수정해서 작성하면 된다.

728x90
반응형
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !

반응형

1. 이터레이션 프로포콜

ES6에서 도입된 이터레이션 프로토콜(iteration protocol)은 데이터 컬렉션을 순회하기 위한 프로토콜이다. 이터레이션 프로토콜을 준수한 객체는 for...of문으로 순회할 수 있고 Spread 문법의 피연산자가 될 수 있다.

이터레이션 프로토콜에는 이터러블 프로토콜(iterable protocol)과 이터레이터 프로토콜(iterator protocol)이 있다.

이터레이션 프로토콜(Iteration Protocol)

1) 이터러블

이터러블 프로토콜은 준수한 객체를 이터러블이라 한다. 이터러블은 Symbol.iterator 메서드를 구현하거나 프로토타입 체인에 의해 상속한 객체를 말한다. Symbol.terator 메서드는 이터레이터를 반환한다. 이터러블은 for...of 문에서 순회할 수 있으며 Spread 문법의 대상으로 사용할 수 있다.

배열은 Symbol.iterator 메서드를 소유한다. 따라서 배열은 이터러블 프로토콜을 준수한 이터러블이다.

const array = [1, 2, 3];

// 배열은 Symbol.iterator 메서드를 소유한다.
// 따라서 배열은 이터러블 프로토콜을 준수한 이터러블이다.
console.log(Symbol.iterator in array); // true

// 이터러블 프로토콜을 준수한 배열은 for...of 문에서 순회 가능하다.
for (const item of array) {
  console.log(item);
}

일반 객체는 Symbol.iterator 메서드를 소유하지 않는다. 따라서 일반 객체는 이터러블 프로토콜을 준수한 이터러블이 아니다.

const obj = { a: 1, b: 2 };

// 일반 객체는 Symbol.iterator 메서드를 소유하지 않는다.
// 따라서 일반 객체는 이터러블 프로토콜을 준수한 이터러블이 아니다.
console.log(Symbol.iterator in obj); // false

// 이터러블이 아닌 일반 객체는 for...of 문에서 순회할 수 없다.
// TypeError: obj is not iterable
for (const p of obj) {
    console.log(p);
}

일반 객체는 이터레이션 프로토콜을 준수(Symbol.iterator 메서드를 소유)하지 않기 떄문에 이터러블이 아니다. 따라서 일반 객체는 for...of 문에서 순회할 수 없으며 Spread 문법의 대상으로 사용할 수도 없다. 하지만 일반 객체도 이터러블 프로토콜을 준수하도록 구현하면 이터러블이 된다.

 

2) 이터레이터

이터레이터 프로토콜은 next 메서드를 소유하며 next 메서드를 호출하면 이터러블을 순회하며 value, done 프로퍼티를 갖는 이터레이터 리절트 객체를 반환하는 것이다. 이 규약을 준수한 객체가 이터레이터이다.

이터러블 프로토콜을 준수한 이터러블은 Symbol.iterator 메서드를 소유한다. 이 메서드를 호출하면 이터레이터를 반환한다. 이터레이터 프로토콜을 준수한 이터레이터는 next 메서드를 갖는다.

// 배열은 이터러블 프로토콜을 준수한 이터러블읻.
const array = [1, 2, 3];

// Symbol.iterator 메서드는 이터레이터를 반환한다.
const iterator = array[Symbol.iterator]();

// 이터레이터 프로토콜을 준수한 이터레이터는 next 메서드를 갖는다.
console.log('next' in iterator); // true

이터레이터의 next 메서드를 호출하면 value, done 프로퍼티를 갖는 이터레이터 리절트(iterator result) 객체를 반환한다.

// 배열은 이터러블 프로토콜을 준수한 이터러블이다.
const array = [1, 2, 3];

// Symbol.iterator 메서드는 이터레이터를 반환한다.
const iterator = array[Symbol.iterator]();

// 이터레이터 프로토콜을 준수한 이터레이터는 next 메서드를 갖는다.
console.log('next' in iterator); // true

// 이터레이터의 next 메서드를 호출하면 value, done 프로퍼티를 갖는 이터레이터 리절트 객체를 반환한다.
let iteratorResult = iterator.next();
console.log(iteratorResult); // { value: 1, done: false }

이터레이터의 next 메서드는 이터러블의 각 요소를 순회하기 위한 포인터의 역할을 한다. next 메서드를 호출하면 이터러블을 순차적으로 한 단계씩 순회하며 이터레이터 리절트 객체를 반환한다.

// 배열은 이터러블 프로토콜을 준수한 이터러블이다.
const array = [1, 2, 3];

// Symbol.iterator 메서드는 이터레이터를 반환한다.
const iterator = array[Symbol.iterator]();

// 이터레이터 프로토콜을 준수한 이터레이터는 next 메서드를 갖는다.
console.log('next' in iterator); // true

// 이터레이터의 next 메서드를 호출하면 value, done 프로퍼티를 갖는 이터레이터 리절트 객체를 반환한다.
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

이터레이터의 next 메서드가 반환하는 이터레이터 리절트 객체의 value 프로퍼티는 현재 순회 중인 이터러블의 값을 반환하고 done 프로퍼티는 이터러블의 순회 완료 여부를 반환한다.

3) 빌트인 이터러블

ES6에서 제공하는 빌트인 이터러블은 아래와 같다.

Array, String, Map, Set, TypedArray(Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array), DOM data structure(NodeList, HTMLCollection), Arguments

// 배열은 이터러블 프로토콜을 준수한 이터러블이다.
const array = [1, 2, 3];

// 이터러블은 Symbol.iterator 메서드를 소유한다.
// Symbol.iterator 메서드는 이터레이터를 반환한다.
const iterator = array[Symbol.iterator]();

// 이터레이터는 next 메서드를 갖는다.
// 이터레이터의 next 메서드를 호출하면 value, done 프로퍼티를 갖는 이터레이터 리절트 객체를 반환한다.
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

// 이터러블은 for...of문으로 순회 가능하다.
for (const item of array) {
    console.log(item);
}

// 문자열은 이터러블이다.
const string = 'hi';

iterator = string[Symbol.iterator]();

console.log(iterator.next()); // { value: "h", done: false }
console.log(iterator.next()); // { value: "i", done: false }
console.log(iterator.next()); // { value: undefined, done: true }

for (const letter of string) {
	console.log(letter);
}

// arguments 객체는 이터러블이다.
(function() {
    iterator = arguments[Symbol.iterator]();
    
    console.log(iterator.next()); { value: 1, done: false }
    console.log(iterator.next()); { value: 2, done: false }
    console.log(iterator.next()); { value: undefined, done: true }
    
    for (const arg of arguments) {
        console.log(arg);
    }
    
}(1, 2));

4) 이터레이션 프로토콜의 필요성

이터레이션 프로토콜은 다양한 데이터 소스가 하나의 순회 방식을 갖도록 규정하여 데이터 소비자가 효율적으로 다양한 데이터 소스를 사용할 수 있도록 데이터 소비자와 데이터 소스를 연결하는 인터페이스의 역할을 한다.

이터러블을 지원하는 데이터 소비자는 내부에서 Symbol.iterator 메서드를 호출해 이터레이터를 생성하고 이터레이터의 next 메서드를 호출하여 이터러블을 순회한다. 그리고 next 메서드가 반환한 이터레이터 리절트 객체의 value 프로퍼티 값을 취득한다.

 

2. for...of 문

for...of 문은 내부적으로 이터레이터의 next 메서드를 호출하여 이터러블을 순회하며 next 메서드가 반환한 이터레이터 리절트 객체의 value 프로퍼티 값을 for...of 문의 변수에 할당한다. 그리고 이터레이터 리저르 객체의 done 프로퍼티 값이 false 이면 이터러블의 순회를 계속하고 true이면 이터러블의 순회를 중단한다.

// 배열
for (const item of ['a', 'b', 'c']) {
	console.log(item);
}

// 문자열
for (const letter of 'abc') {
	console.log(letter);
}

// Map
for (const [key, value] of new Map([['a', '1'], ['b', '2'], ['c', '3']])) {
	console.log(`key: ${key} value: ${value}`); // ke: a value: 1...
}

// Set
for (const val of new Set([1, 2, 3])) {
	console.log(val);
}

for...of 문이 내부적으로 동작하는 것을 for문으로 표현하면 아래와 같다.

// 이터러블
const iterable = [1, 2, 3];

// 이터레이터
const iterator = iterable[Symbol.iterator]();

for (;;) {
    // 이터레이터의 next 메서드를 호출하여 이터러블을 순회한다.
    const res = iterator.next();
    
    // next 메서드가 반환하는 이터레이터 리절트 객체의 done 프로퍼티가 true가 될 때까지 반복한다.
    if (res.done) break;
    
    console.log(res);
}

3. 커스텀 이터러블

1) 커스텀 이터러블 구현

일반 객체는 이터러블이 아니다. 일반 객체는 Symbol.iterator 메서드를 소유하지 않는다. 즉, 일반 객체는 이터러블 프로토콜을 준수하지 않으므로 for...of 문으로 순회할 수 없다.

// 일반 객체는 이터러블이 아니다.
const obj = { a: 1, b: 2 };

// 일반 객체는 Symbol.iterator 메서드를 소유하지 않는다.
// 따라서 일반 객체는 이터러블 프로토콜을 준수한 이터러블이 아니다.
console.log(Symbol.iterator in obj); // false

// 이터러블이 아닌 일반 객체는 for...of 문에서 순회할 수 없다.
// TypeError: obj is not iterable
for (const p of obj) {
	console.log(p);
}

하지만 일반 객체가 이터레이션 프로토콜을 준수하도록 구현하면 이터러블이 된다. 피보나치 수열(1, 2, 3, 5 ...)을 구현한 간단한 이터러블을 만들어보자.

const fibonacci = {
    // Symbol.iterator 메서드를 구현하여 이터러블 프로토콜을 준수
    [Symbol.iterator]() {
        let [pre, cur] = [0, 1];
        // 최대값
        const max = 10;
        
        // Symbol.iterator 메서드는 next 메서드를 소유한 이터레이터를 반환해야 한다.
        // next 메서드는 이터레이터 리절트 객체를 반환
        return {
            // fibonacci 객체를 순회할 때마다 next 메서드가 호출된다.
            next() {
                [pre, cur] = [cur, pre + cur];
                return {
                    value: cur,
                    done: cur >= max
                };
            }
        };
    }
};

// 이터러블의 최대값을 외부에서 전달할 수 없다.
for (const num of fibonacci) {
    // for...of 내부에서 break는 가능하다.
    // if (num >= 10) break;
    console.log(num); // 1 2 3 5 8
}

Symbol.iteraotr 메서드는 next 메서드를 갖는 이터레이터를 반환하여야 한다. 그리고 next 메서드는 done과 value 프로퍼티를 가지는 이터레이터 리절트 객체를 반환한다. for...of 문은 done 프로퍼티가 true가 될 때까지 반복하며 done 프로퍼티가 true가 되면 반복을 중지한다.

이터러블은 for...of 문뿐만 아니라 spread 문법, 디스트럭쳐링 할당, Map과 Set의 생성자에도 사용된다.

// spread 문법과 디스트럭쳐링을 사용하면 이터러블을 손쉽게 배열로 변환할 수 있다.
// spread 문법
const arr = [... fibonacci];
console.log(arr); // [1, 2, 3, 5, 8]

// 디스트럭쳐링
const [first, second, ... rest] = fibonacci;
console.log(first, second, rest); // 1 2 [3, 5, 8]

2) 이터러블을 생성하는 함수

위 fibonacci 이터러블에는 외부에서 값을 전달할 수 없다. fibonacci 이터러블의 최대값을 외부에서 전달할 수 있도록 수정해보자. 이터러블의 최대 순회수를 전달받아 이터러블을 반환하는 함수를 만들면 된다.

// 이터러블을 반환하는 함수
const fibonacciFunc = function(max) {
  let [pre, cur] = [0, 1];

  return {
    // Symbol.iterator 메소드를 구현하여 이터러블 프로토콜을 준수
    [Symbol.iterator]() {
      // Symbol.iterator 메소드는 next 메소드를 소유한 이터레이터를 반환해야 한다.
      // next 메소드는 이터레이터 리절트 객체를 반환
      return {
        // fibonacci 객체를 순회할 때마다 next 메소드가 호출된다.
        next() {
          [pre, cur] = [cur, pre + cur];
          return {
            value: cur,
            done: cur >= max
          };
        }
      };
    }
  };
};

// 이터러블을 반환하는 함수에 이터러블의 최대값을 전달한다.
for (const num of fibonacciFunc(10)) {
    console.log(num); // 1 2 3 5 8
}

3) 이터러블이면서 이터레이터인 객체를 생성하는 함수

이터레이터를 생성하려면 이터러블의 Symbol.iterator 메서드를 호출해야 한다. 이터러블이면서 이터레이터인 객체를 생성하면 Symbol.iterator 메서드를 호출하지 않아도 된다.

// 이터러블이면서 이터레이터인 객체를 반환하는 함수
const fibonacciFunc = function (max) {
  let [pre, cur] = [0, 1];

  // Symbol.iterator 메소드와 next 메소드를 소유한
  // 이터러블이면서 이터레이터인 객체를 반환
  return {
    // Symbol.iterator 메소드
    [Symbol.iterator]() {
      return this;
    },
    // next 메소드는 이터레이터 리절트 객체를 반환
    next() {
      [pre, cur] = [cur, pre + cur];
      return {
        value: cur,
        done: cur >= max
      };
    }
  };
};

// iter는 이터러블이면서 이터레이터이다.
let iter = fibonacciFunc(10);

// iter는 이터레이터이다.
console.log(iter.next()); // {value: 1, done: false}
console.log(iter.next()); // {value: 2, done: false}
console.log(iter.next()); // {value: 3, done: false}
console.log(iter.next()); // {value: 5, done: false}
console.log(iter.next()); // {value: 8, done: false}
console.log(iter.next()); // {value: 13, done: true}

iter = fibonacciFunc(10);

// iter는 이터러블이다.
for (const num of iter) {
  console.log(num); // 1 2 3 5 8
}

아래의 객체는 Symbol.iterator 메서드와 next 메서드를 소유한 이터러블이면서 이터레이터이다. Symbol.iterator 메서는 this를 반환하므로 next 메서드를 갖는 이터레이터를 반환한다.

{
    [Symbol.iterator]() {
        return this;
    },
    next() {
        ...
    }
}

4) 무한 이터러블과 Lazy evaluation(지연 평가)

무한 이터러블(infinite sequence)을 생성하는 함수를 정의해보자. 

// 무한 이터러블을 생성하는 함수
const fibonacciFunc = function () {
  let [pre, cur] = [0, 1];

  return {
    [Symbol.iterator]() {
      return this;
    },
    next() {
      [pre, cur] = [cur, pre + cur];
      // done 프로퍼티를 생략한다.
      return { value: cur };
    }
  };
};

// fibonacciFunc 함수는 무한 이터러블을 생성한다.
for (const num of fibonacciFunc()) {
  if (num > 10000) break;
  console.log(num); // 1 2 3 5 8...
}

// 무한 이터러블에서 3개만을 취득한다.
const [f1, f2, f3] = fibonacciFunc();
console.log(f1, f2, f3); // 1 2 3

이터러블은 데이터 공급자(Data provider)의 역할을 한다. 배열, 문자열, Map, Set 등의 빌트인 이터러블은 데이터를 모두 메모리에 확보한 다음 동작한다. 하지만 이터러블은 Lazy evaluation(지연 평가)를 통해 값을 생성한다.

728x90
반응형

'programming language > ECMAScript6' 카테고리의 다른 글

[ES6] 7번째 타입 심볼(Symbol)  (0) 2021.12.29
[ES6] 프로미스 (Promise)  (1) 2021.12.27
[ES6] 모듈 (Module)  (0) 2021.12.20
[ES6] 클래스(2)  (0) 2021.12.16
[ES6] 클래스(1)  (2) 2021.12.15
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !