Javascript, Object 이 놈을 알아야 그 놈을 잡는다.

Javascipt에서 Object는 모든 객체의 슈퍼 타입(최상위 타입)입니다. Object를 더 많이 알수록 이 놈을 통해 파생된 그 놈들을 더 잘.. 알 수 있습니다. 이 글은 Object의 내용중 유용한 정적 매서드 몇가지를 살펴봅니다.

먼저 객체의 키(key)만을 배열로 가져오는 keys입니다.

const obj = {
    "key0": "value0",
    "key1": "value1",
    "key2": "value2"
}

const keys = Object.keys(obj)
console.log(keys) // ["key0", "key1", "key2"]

다음은 값(Value)만을 배열로 가져오는 values입니다.

const obj = {
    "key0": "value0",
    "key1": "value1",
    "key2": "value2"
}

const values = Object.values(obj)
console.log(values) // ["value0", "value1", "value2"]

그럼 키와 값 모두를 배열로 가져오기 위해서는? 바로 entries 정적 매서드를 사용하면 됩니다.

const obj = {
    "key0": "value0",
    "key1": "value1",
    "key2": "value2"
}

const entries = Object.entries(obj)
console.log(entries)
/*
[
    ["key0", "value0"],
    ["key1", "value1"],
    ["key2", "value2"]
]
*/

이제 반대로 위의 entries 정적 매서드로 가져온 결과를 통해 다시 원래의 객체를 만들고자 한다면? 바로 fromEntries 정적 매서드를 사용하면 됩니다.

const arr = [
    ["K1", "V1"], 
    ["K2", "V2"]
];

const obj = Object.fromEntries(arr);
console.log(obj); // {K1: "V1", K2: "V2"}

다음 예제는 지금까지와는 다른 흐름인데요. 객체를 복사하기 위한 Javascript 적인 방법은 여러가지가 있는데요. 그 중 Object의 assign 정적 매서드를 사용하는 방법이있습니다.

const a = {}
b = Object.assign(a, obj)
console.log(b, a === b, a === obj) 
// {key0: "value0", key1: "value1", key2: "value2"} true false

fetch API를 이용한 REST API 호출

2개 REST API를 순차적으로 호출하는 코드는 아래와 같습니다.

const url1 = "http://localhost:8080/Xr?qryHub|0004259886";
const url2 = "http://localhost:8080/Xr?qryHub|0002097186";

fetch(url1).then(response => {
    return response.json();
}).then(json => {
    console.log("First", json);
    return fetch(url2);
}).then(response => {
    return response.json();
}).then(json => {
    console.log("Second", json);
}).catch(function (error) {
    console.warn(error);
});

url1에 대한 REST API의 호출이 성공하면 url2에 대한 REST API가 호출됩니다. 이 두 개의 REST API가 문제가 없다면 결과가 호출된 순서대로 아래처럼 콘솔에 표시됩니다.

위의 코드를 보면 2개의 REST API는 그 결과에 종속적이지 않으므로 순차적으로 호출하지 않고 동시에 호출하는 것이 효율적입니다. 아래의 코드는 이 2개의 REST API를 동시에 호출하여 2개의 결과를 취합해 출력하는 코드입니다.

const url1 = "http://localhost:8080/Xr?qryHub|0004259886";
const url2 = "http://localhost:8080/Xr?qryHub|0002097186";

Promise.all([fetch(url1), fetch(url2)]).then(responses => {
    return Promise.all(responses.map(response => {
        return response.json();
    }));
}).then(json => {
    console.log(json);
}).catch(error => {
    console.log(error);
});

결과는 다음과 같습니다.

지금까지 살펴보면 REST API는 GET 방식인데요. POST 방식을 fetch API로 호출하는 코드의 예는 다음과 같습니다.

const url = "http://localhost:8080/Xr?sql|postgis|1";
fetch(url, {
    method: "POST",
    //headers: { 'Content-Type': 'text/plain;charset=UTF-8' },
    body: `
        SELECT 0 as project_id, zone_id, hub_id
        FROM zone_hub_map
        WHERE zone_id
        IN (
            SELECT zone_id FROM project_zone_map WHERE project_id = 0
        );
    `
}).then(response => {
    return response.text();
}).then(text => {
    console.log(text);
});

결과는 다음과 같습니다.

웹에서 Binary Data를 파일로 저장하기

웹에서 ArrayBuffer를 파일로 저장하기 위한 코드에 대한 내용입니다.

웹에서는 PC에 저장된 파일을 읽거나 쓸때 반드시 사람의 행위가 수반되어야 합니다. 즉, 버튼과 같은 UI를 사람이 의도하여 클릭을 해야만 한다는 것입니다. 이를 위해 필요한 UI에 대한 DOM 요소를 아래처럼 생성해 둡니다.

<button id="exportFile">Export To File</button>

그리고 위의 버튼에 대한 클릭 이벤트에 대한 코드는 다음과 같이 지정하구요.

const exportButton = document.getElementById( 'exportFile' );
exportButton.addEventListener( 'click', exportFile );

위의 exportFile 함수에 대한 코드는 다음과 같습니다.

function exportFile() {
    const buffer = createData(); /* ArrayBuffer 형식의 데이터를 생성하는 함수 */ 
    const blob = new Blob( [ buffer ], 
        { type: 'application/octet-stream' } )
    link.href = URL.createObjectURL( blob );
    link.download = 'file.dat';
    link.click();
}

위의 코드에서 link는 다음처럼 동적으로 생성된 a 테그 요소입니다.

const link = document.createElement( 'a' );
link.style.display = 'none';
document.body.appendChild( link );

결과적으로 사용자가 버튼을 클릭하면 a Tag가 클릭한 것으로 처리되어 파일 저장이 진행됩니다.

여기서 추가로 만약 저장하고자 하는 데이터가 바이너리가 아닌 텍스트라면 위의 코드 중 변경해야할 부분은 어딜까요? exportFile 함수에 대한 코드 중 3,4번의 buffer가 단순한 문자열 값이며 type: ‘text/plain’로 지정해 주면 됩니다.

GLSL를 이용한 그래픽 효과

3차원 그래픽에서 특수 효과는 쉐이더를 통해 대부분 구현됩니다. 이 글은 간단한 GLSL 쉐이더 코드를 통해 물과 불에 대한 효과를 소개합니다.

먼저 불에 대해 구현하고자 하는 모습은 다음과 같습니다.

다음은 물에 대한 결과입니다.

전체 소스코드는 아래 링크를 통해 다운로드 받으실 수 있습니다. 웹기반에서 구현된 코드이므로 js와 css, html 파일로 구성되어 있으며 WebGL 2.0으로 쉐이더 코드가 실행됩니다.