기본 콘텐츠로 건너뛰기

Moment.js 소개 (시간에 대한 라이브러리)

 Moment는 시간을 다루기 편안한 라이브러리 입니다.  1. 여기 아주 간단한 요청이 있습니다. 현재 시간을 YYYY-MM-DD HH:mm:ss로 표현을 해달라고 합니다. 자 이걸 Date와 Moment를 비교하여 보여드리겠습니다. const current = new Date () console . log ( getFormattedDate ( current ) ) function getFormattedDate ( date ) { return ` ${date. getFullYear ()} - ${ lpad ( date. getMonth () + 1 )} - ${ lpad ( date. getDate () )} ` + ` ${ lpad ( date. getHours () )} : ${ lpad ( date. getMinutes () )} : ${ lpad ( date. getSeconds () )} ` } function lpad ( val , length = 2 , char = '0' ) { let valStr = val && val. toString () ? val. toString () : '' for ( let i = valStr. length ; i < length ; i++ ) { valStr = char + valStr } return valStr }  위 처럼 포맷팅 한번 하기 위해서 포매팅을 하기 위한 함수와, 한자리로 나오는 함수들을 강제로 두자리수로 만들어 주기위한 함수도 구현하여야 원하는 포매팅을 할 수 있기에 매우 불편하다.  Moment.js의 표현으로는 아래와 같다. moment(). format ( 'YYYY-MM-DD HH:mm:ss' )  위의 코드를  https://momentjs.com/  해당 사이트에 접근하여 디버거 창에서 실행해보면 아래와 같이 포매팅된 날짜 형식을 구할 수 있다.  2. 2015년 ...

아이콘 폰트 (icomoon 사용법)

 장난감 프로젝트를 만들다 보면, 아이콘이 필요한 경우가 있다. 간단하게 아이콘을 인터넷에서 검색하여, 이미지로 넣어두고 이미지 태그를 이용하여, 사용하는 경우가 일반적이였지만...  요즘에는 대부분 폰트를 이용하여 아이콘을 노출 한다. 나 같은 경우에도 기본적으로  https://material.io/resources/icons 를 참고하여 아이콘 폰트를 이용할 수 있도록 처리하고, 추가적으로 필요한 아이콘이고, 일상적으로 사용 되지 않는 아이콘의 경우에는  https://icomoon.io 에서 제작하여, 아이콘 폰트로 이용 하곤 한다.  그래서 이번에는 아이콘  https://icomoon.io 의 사용법을 간단히 공유하고자 한다.   들어가자 마자 위의 icoMoonApp버튼을 누르면 아래와 같은 화면이 나타난다.  icomoon에서 무료로 제공하는 아이콘들이 보이면 위에 파란색으로 표시 되어있는 집 모양 세가지를 선택한 후, 아래의 빨간색으로 표시되어있는 Generate Font를 눌러보자.  그리고 나서 바로 다운로드를 요청해보자. icomoon.zip이 다운로드가 될텐데, 압축을 해제해 보면, 아래의 폴더 및 파일들이 있다. 아래에서 중요한 것은 font 폴더와 style.css이다. demo-files fonts demo.html Read Me.txt selection.json style.css <!doctype html > <html> <head> <link rel ="stylesheet" href ="style.css" ></head> </head> <body> <span class ="icon-home" ></span> <span class ="icon-home2" ></span> <span class ="icon-hom...

this는 누구인가

 this... 객체지향 프로그래밍을 배우다 보면 객체 자기 자신을 지칭하는 키워드 이다. 즉 한번 결정 되면 객체 자기 자신만 지칭을 하고 변하지 않는데...  과연 자바스크립트에서도 그럴까? function Person (name) { this . name = name } Person . prototype . introduce = function () { console . log ( `My name is ${ this . name } ` ) }  위와 같이 적당히 객체지향 언어처럼 Person클래스를 만들고 메소드로 introduce를 추가해줬다. this.name이 어떻게 행동되는지 보시면 되겠다.    여기까지는 예상하는봐와 같이 각각을 잘 소개 하는 것을 볼수 있다.  자 상황을 바꾸어 보자 객체가 생성되고 최소 2초가 지난 후에 자기소개를 하는 코드를 만들어 보자.    코드를 보면 위와 다른 점이라고는 setTimeout을 통해서 호출 하는 것만 바뀌었지만... 둘다 이름을 잃어 버린걸로 보인다.  setTimeout에 introduce 바로 넣어 주는가와 함수를 한번 감싸서 넣어 주는 것과의 차이이다.  왜 그럴까?  첫번째 예제는 setTimeout에 sejiWork.introduce 함수 그 자체를 인자로 넘겨 주었다. 코드로 보면... setTimeout ( function () { console . log ( `My name is ${ this . name } ` ) } , 2000 )  위와 같은 코드로 볼 수 있다. 하지만 그 아래의 코드는 sejiWork객체가 introduce함수를 실행 시키는 코드이다.  즉 this는 호출자에 의해 결정 된다고 볼 수 있다.

클로저

 클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다.  클로저를 어휘적 환경이 무엇인지 알아야 하는데 무엇인가? 1.  어휘적 범위 지정(Lexical scoping) function foo() { var test = 'test' function bar() { console.log(test) } bar() } foo()  예상 하였겠지만, 'test'라는 문자열이 출력이 된다. 위의 예시는  어휘적 범위 지정(lexical scoping)의 한 예이다.   중첩된 함수는 외부 범위(scope)에서 선언한 변수에도 접근할 수 있다는 것을 알 수있다. 2. 클로저 function foo () { var test = 'test' function bar () { console . log (test) } return bar } var fooOfBar = foo () fooOfBar ()  위의 코드는 어떠한가?  이것또한 예상 한것처럼 "test"문자열을 출력을 한다. 자 그렇다는 말 뜻은 foo함수가 실행 되는 동안 생성된 " test "문자열을 넣은 test변수가 foo 함수가 실행 된 이후에도 존재 한다라는 것이 된다.   자바스크립트는 함수를 리턴하고, 리턴하는 함수가 클로저를 형성하기 때문이다. 클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다. 3. 간단한 활용 법 function makeAdder (x) { return function (y) { return x + y } } var add5 = makeAdder ( 5 ) var add10 = makeAdder ( 10 ) console . log ( add5 ( 5 )) console . log ( add5 ( 10 )) console . log ( add10 ( 20 ))  클로저의 특성을 이용하여 위처럼 특정값에 항상 5를 더하는 함수를 만들거나 10...

setTimeout은 항상 늦다.

 자바스크립트를 공부하게 되면, setTimeout, setInterval은 특정 시간 이후에 어떤 일을 실행 하거나 반복 하기위하여 책에서 다루는 것을 볼 수 있다. 그러한 책들에는 설명이 ms를 지정하면, 해당 시간에 특정 함수를 실행 혹은 반복 해준다는 것으로 설명을 하지만.... 실제로 설정한 ms 실행이 되는가?  처음에 공부할 때는 대부분의 개발자, 학생분들이 해당 의문을 가지기에는 힘들고, 실제로 추후에 사용 할 때에, 당하고 나서야... 아, 실제로는 ms설정 한 것이 최소 대기시간이구나 하고 느끼는 분들이 많을 것이다.  그렇다면 왜 그럴까? 자바스크립트는 왜 해당 시간에 실행을 해주지 않는 것일까?  이것을 설명하기 위해서는 자바스크립트 런타임과 이벤트루프를 살펴볼 필요가 있다.   위의 그림을 보면 힙, 스택, 큐라고 적혀 있는데, 각각을 설명 해보면  힙: 노란 네모로 표시 된 네개가 객체라고 보면 되고, 회색은 메모리 영역이라고 보면 된다.  스택: 초록색 네모로 그려져있는 것이 함수 호출이라고 보면 된다. 보통 콜스택이라고 부르는데 크롬 디버거에서 쉽게 확인 할 수 있다.  위 처럼 함수 호출하게 되면 foo가 bar를 실행 하게 되었을 시 위와 같이 함수 들이 스택에 쌓이며 당연하게도 선입후출(First In, Last Out)의 구조이다.  큐: 노란색 영역은 메시지 대기열이며, 빨간색은 메시지 이다. 메시지는 할 일 정도로 보면 편안하다. (일반적으로 이 큐는 태스트 큐라고 불린다.)  메시지들은 이벤트 루프 중에 먼저 들어온 메시지 부터 처리가 된다. 문제는 메시지의 처리가 아무때나 되는 것이 아니라, 스택이 모두 비워지고 나서, 메시지를 처리한다.  ***A메시지가 실행 되면 끝날때까지 실행 되고 나서 B메시지가 실행 된다.  => C언어 처럼 A쓰레드가 foo함수를 실행중에 중단 하고 B쓰...

비동기 코드를 처리 하자

 이번 포스트에서는 비동기처림에 대한 간단한 처리만 해보고 넘어 가고자 한다. callback, promise, async await을 모르는 분만 읽기를 바라며 그저 간단하게 사용법을 소개 하는 포스트이다.  웹 개발뿐만 아니라 네트워크로 통해서 들어오거나 외부 레거시 코드를 실행하는 경우, 즉시 값이 리턴을 받지 않고, 해당 네트워크 혹은 레거시에서 처리후 callback을 통하여 실행 되는 경우가 많다.  이러한 경우를 처리를 해보자. function getDir ( path , callback ) { if ( typeof callback === 'function' ) { setTimeout ( () => { callback( [ 'Documents' , 'Download' , 'Etc' ] ) } , 1000 ) } }  위 처럼 해당 path에 있는 폴더들을 확인 하고 그 폴더들가지로 callback을 호출해주는 코드이다.  우린 위처럼 콜백 함수를 넣어서 순회를 할 수 있다.  예전에 구현해둔 map을 이용해서 적절하게 순회도 가능하다.  자 그렇다면 test 폴더안에서 Etc 폴더를 찾아서 그 안의 폴더인 Donwload 폴더를 찾아보면 어떤 코드가 될까?  위와 같이 표현이 될 수 있다. 그렇다면 점점 더 상세한 폴더가 필요 하게 되면 어떻게 될까?  즉 test/Etc/Download/Download/Download/Download/Download/Download 처럼 말이다.  코드는 점점 안쪽으로 들어가서 코드가 파악하기가 점점 복잡해진다. 위는 그나마 간단한 요구 조건이라서 덜 복잡해보이는 감이 있다.  getDir에다가 Promise를 입혀보자. function getDirPromise ( path ) { return new Promise (resolve => { ...

1000만 개 중에 2개 주세요(게으른 평가)

 요구조건으로 이런것이 왔다고 쳐봅시다.  서비스 개발한 서비스의 사용자의 데이터에서 포인트의 누적을 자신의 가족 수를 곱하고 그 값이 1000점 이상인 사람들 중에서 해당 포인트의 제곱근이 소수점을 버리고 홀 수 인 사람 중에 두사람의 마지막 계산된 포인트를 뽑아달라는 요청이 왔다.  ( 말도 안되는 시나리오지만 아 그렇구나 하고 넘어가자. )  일단 저 2명을 뽑기 위해서 take라는 함수를 구현해봅시다.   const take = ( count , iter ) => { const res = [] for ( const item of iter ) { res. push ( item ) if ( res. length === count ) return res } return res } 잘 동작 합니다. 고객 정보가 없기 때문에 적당히 고객정보를 구현 할 수 있도록 range도 구현을 해봅시다. const range = ( limit ) => { const res = [] let count = 0 while ( count < limit ) { res. push ( count++ ) } return res } 이제 샘플로 사용 할 고객 정보를 임의로 만들 수 있도록 함 수 하나를 만들겠습니다. 위 시나리오상 가족수랑 포인트만 있으면 되겠네요. const genMember = () => { return { family : Math . ceil ( Math . random () * 8 ) , point : Math . ceil ( Math . random () * 8000 ) } } 적당히 만들었습니다. 그러면 이제 1000만명을 만들어서 위의 로직을 돌려보도록 하죠. 저의 PC가 못버티는 관계로... 10만명으로 하겠습니다. const members = go ( range ( 1000000 ) , map ( genMember ) )...

map, filter, reduce (go, curry)

 간단하게 map, filter, reduce를 구현해보자. 1. map은 인자를 두개를 받으며, 첫번째 인자를 받아서 두번째 인자로 평가 후 배열로 리턴해준다. const map = ( iter , func ) => { const ret = [] for ( const item of iter ) { ret. push ( func( item ) ) } return ret }  위와같이 간단하게 짤 수 있다. 2. filter를 구현해보자 map과 두개의 인자를 받으며, 첫번째 인자를 받아서 두번째 인자로 평가 후 값이 있다며 배열로 리턴을 해준다. const filter = ( iter , func ) => { const ret = [] for ( const item of iter ) { if ( func( item ) ) { ret. push ( item ) } } return ret }   3. reduce는 세개의 인자를 받으며, 첫번째 인자를 받아서 두번째 인자로 받은 함수로 평가하며 축적된 값을 리턴을 한다, 이때에 세번째 인자를 초기값으로 이용한다. const reduce = ( iter , func , acc ) => { for ( const item of iter ) { acc = func(acc , item) } return acc }  이와 같이 표현 할 수 있지만, 초기값을 안넣은 경우에는 iter의 첫번째 값을 초기값으로 사용하게 변경 해보자. const reduce = ( ...args ) => { let iter = args[ 0 ] const func = args[ 1 ] let acc = args[ 2 ] if ( args. length < 3 ) { iter = iter[ Symbol . iterator ]() acc = iter. next (). value } ...

for of (feat.iterable)

 ES6부터 새로 생겨난 for of에 대해서 궁금증이 생겨서 학습안 내용을 포스트에 남깁니다. const arr = [ 1 , 2 , 3 , 4 ] for ( const value of arr ) { console . log ( 'value' , value ) } const set = new Set ([ 1 , 2 , 3 , 4 ]) for ( const value of set ) { console . log ( 'value' , value ) } const obj = { 0 : 1 , 1 : 2 , 2 : 3 , 3 : 4 } for ( const value of obj ) { console . log ( 'value' , value ) } Array, Set은 for of 문장으로 반복이 되지만, Object는 반복이 되지 않는가? obj is not iterable 인데, 반복할 수 없다 정도록 해석이 가능 할 것 같다. for of구문을 확인해보면 아래와 같다. iterable이 무엇인가? 간단하게 말하면 iterator를 생성할 수 있는 모든객체를 말 할 수 있다. 그러면 iterator는 무엇인가? 반복자를 말한다. 저 단어는 많은 개발자들이 많이 들어 보셧을 것이기 때문에 이하 생략한다. 여기서 더 중요한것은 for of는 무엇을 반복자로 받아 들이는가? 이다. 이에 대한 내용은 ES6에 추가된  protocol인   iterable protocol 과 iterator protocol을 확인 할 필요가 있다. 이 기준에만 충족을 한다면 자바스크립트의 for of에 적용 할 수 있다. protocol 두가지는 아주 심플하다. iterable protocol: 내용을 살펴 보면 Object 혹은 prototype chain 의 오브젝트 중 하나가 Symbol.iterator key의 속성을 가지며 값이  iterator protocol을 충족 시킬수 있는 값을...