810-877-9201

WebP 파일이란?

WebP 파일은 구글이 웹사이트의 트래픽 감소 및 로딩 속도 단축을 겨냥해 개발한 이미지 포맷이다. 기존 웹사이트에서 널리 사용되고 있는 jpeg, png, gif 등을 대체하기 위해 개발되었다. 구글이 이러한 포맷을 개발 및 배포한 목적은 전 세계의 검색 및 사이트 접속 속도가 증가할수록 구글의 광고 수입 또한 증가하기 때문이다.

WebP 파일을 사용해야 하는 이유

WebP 파일은 기존 jpeg 파일 대비 39.8% 압축룰이 개선 되었으며, 압축률 또한 조절 할 수 있다. 항상 페이로드를 줄이기 위해 고민하는 프론트엔드 개발자들에게는 더할나위 없이 좋은 소식이라 할 수 있다 🙂

WebP 파일 적용 방법

안타깝게도, WebP 파일은 IE, Safari 등의 브라우저에서 지원되지 않는다. 때문에 무작정 png파일을 WebP 파일로 변경하면 화면에 제대로 랜더링 되지 않는 낭패를 격을 수 있다.

Can I use WebP ê²°ê³¼
Can I use WebP ê²°ê³¼

HTML에서의 WebP 파일 활용

html 상에서 WebP 파일을 사용하기 위해서는 picture 태그를 이용하는 것이 좋다. picture 태그는 source 태그와 함께 최적화된 이미지 리소스 로딩을 할 수 있도록 한다. 보다 자세한 설명은 링크를 참고하길 바란다.

CSS에서의 WebP 파일 활용

css의 background-image 속성에 WebP 파일을 활용하기 위해서는 javascript의 도움을 받아야 한다. 위에서 언급했듯이 모든 브라우저가 WebP파일을 지원하지 않기 때문이다. 아래 예제를 보면 어떤 식으로 활용이 가능한지 알 수 있다.

See the Pen WebP by armadillo (@armadillo-dev167) on CodePen.0

참고링크

8709076859

855-596-4270

이 문제는 정수로 이루어진 배열(A)이 주어질 때, A에 포함되지 않은 가장 작은 양의 정수를 반환하는 문제이다.

예를 들어,
A = [1, 2, 3] 일 경우 4를 반환한다.
A = [1, 3, 6, 4, 1, 2]일 경우 5를 반환한다.
A = [-1, -3]일 경우 1을 반환한다.

이 문제는 다음과 같은 순서로 풀이 할 수 있다.

  1. 주어진 배열을 Set으로 정의 한 뒤 다시 배열로 반환해서 중복값을 제거한다.
  2. filter 메서드를 통해 양수만 추출한다.
  3. sort 메서드를 이용해 오름차순 정렬 한다.
  4. 정렬된 배열에서 반복문을 실행하며 누락된 수가 있는지 판별한다.
  5. 누락된 수가 있을 경우 해당 값을 반환하고, 없을 경우 배열의 length + 1 값을 반환한다.

이를 코드로 표현하면 다음과 같다.

시간 복잡도 : O(N) or O(N * log(N))

[Electron] Youtube Music desktop application 빌드 경험기

근 1년 전부터 멜론 정기결제를 중단하고 Youtube Premium을 이용하고 있다. Youtube Premium 회원은 Youtube Music이라는 별도 앱을 통해 모바일 기기에서 음원 스트리밍 서비스를 제공받을 수 있다.

그러나, 데스크탑 환경에서는 앱이 존재하지 않아서 인터넷 브라우저에서 웹사이트를 통해 서비스를 제공 받아야 했다. 때문에 항상 여러개의 탭을 열어놓고 웹서핑을 하는 나는 이따금씩 실수로 탭을 닫아 음악이 중간에 끊기는 일이 발생했다. 이러한 불편을 없애기 위해 Electron을 이용해 간단한 데스크탑 앱을 만들기로 했다.

Electron이란?

Build cross platform desktop apps with JavaScript, HTML, and CSS

위의 설명에서 볼 수 있듯이 Electron은 Javascript, HTML, CSS를 활용해 만든 웹사이트를 데스크탑 앱으로 빌드해주는 라이브러리이다. 나는 회사에서 해당 라이브러리를 활용해 제품을 생산하고 있다 🙂

Youtube Music desktop application

Youtube Music의 경우 별도의 API가 제공되지 않고(Youtube API는 제공되고 있다), 이미 웹사이트가 잘 만들어져 있어서 별도의 개발 없이 기존 웹사이트를 감싸기만 해서 데스크탑 앱을 만들기로 했다.

다음 Github 주소에 접속하면 간단한 빌드 방법을 확인 할 수 있다.
770-443-3492

Home
Youtube Music desktop application home
Player
Youtube Music desktop application playlist

개발자가 좋은 이유 중 하나는 필요한 것을 직접 만들어 쓸 수 있다는 점이다 🙂
앞으로도 필요한 것들은 직접 만들어서 공유하려고 한다.

(956) 969-8178

항상 헷갈리는 HTTP 응답 코드를 정리하고자 한다. 전체 코드 보다는 주로 사용 할 것같은 코드 위주로 진행하겠다 🙂 
*물론 주관적인 사용 빈도이다. 

200번대 (성공)

200번대 코드는 클라이언트가 요청한 동작을 수신하여 이해했고 성공적으로 처리했음을 의미한다.

코드구분설명
200성공클라이언트의 요청을 정상적으로 수행함
201작성됨요청이 정상적으로 수행되었으며, 새로운 리소스를 작성함(POST를 통한 게시물 생성 등)

300번대(리다이렉션 완료)

300번대 코드는 클라이언트의 요청을 마치기 위해 추가 동작이 필요함을 의미한다.

코드구분설명
301영구 이동요청된 페이지가 새로운 위치로 이동됨(Location header에 변경된 URI를 작성해주면, 요청이 해당 위치로 전달된다)
302임시 이동요청된 페이지가 임시로 새로운 위치로 이동됨

400번대(요청 오류)

400번대 코드는 클라이언트에 오류가 있음을 나타낸다.

코드구분설명
400잘못된 요청요청이 부적절하여 구문을 인식하지 못함
401권한 없음인증이 필요한 리소스에 인증 없이 접근하고자 함(로그인 하지 않은 사용자가 관리자 페이지에 접근 시도했을 경우)
403금지됨인증 여부에 상관없이 응답하고 싶지 않은 리소스에 접근하고자 함(403보다는 400이나 404를 사용할 것을 권고)
404찾을 수 없음요청한 페이지를 찾을 수 없음
405허용되지 않는 방법서버에서 허용되지 않는 method를 통해 요청함(POST만 허용되는 페이지에 GET으로 요청했을 경우)
410사라짐요청한 페이지가 영구적으로 삭제됨

500번대(서버 오류)

500번대 코드는 서버가 요청에 정확히 대응하지 못했음을 의미한다.

코드구분설명
500내부 서버 오류서버에 오류가 발생해 요청을 수행 할 수 없음
501구현되지 않음서버에 요청을 수행 할 수 있는 기능이 없음(서버가 요청 method를 인식하지 못함)

참고 링크

[javascript]Promise를 보다 잘 활용 할 수 있는 Tip

Promise는 javascript에서 비동기 처리를 위해 사용된다. 개인적으로 es7에 들어서며 async/await로 ê·¸ 사용처가 줄어들었다(Promise로 작성된 코드는 async/await로 작성된 코드에 비해 가독성이 떨어진다). 그럼에도 불구하고 여전히 특정  케이스에서는 Promise를 적극 활용하고 있어 공유하고자 한다.

1. Promise.all을 이용한 병렬 처리

Promise.all는 다수의 비동기 요청을 병렬로 처리 할 수 있도록 도와준다. 예를 들어, 서버에 3명의 회원 정보를 요청해 화면에 출력해야 한다고 가정해보자.  

회원에 대한 정보를 한개씩 얻어올 수도 있지만, 3명의 회원 정보를 한 번에 요청하고 병렬로 처리하면 전체 처리 속도를 단축시킬 수 있다.

Promise 사용 유무에 따른 순차 처리와 병렬 처리
Promise 사용 유무에 따른 순차 처리와 병렬 처리

아래의 코드를 통해 구현 방법을 살펴보자.

위의 예제를 실행하면 차례대로 user1, 2, 3번의 정보를 콘솔 창에 출력한다.

Promise.all은  인자로 전달된 배열의 모든 원소들을 병렬로 요청하고, resolve되기를 기다린다. 모든 인자가 resolve될 경우 Promise.all가 최종 resolve되며, 각 인자의 리턴값이 순서대로 배열에 담겨 리턴된다. 

2. Promise.race를 이용한 timeout 설정

Promise.race는 Promise.all과 마찬가지로 전달받은 배열의 Promise 객체를 병렬로 요청한다. 다만, Promise.all이 모든 요청이 완료 되기를 기다리는것과 달리, 가장 먼저 완료된 요청만 리턴된다.

이러한 특징을 활용해 비동기 요청의 timeout을 설정 할 수 있다.

위의 예제를 실행하면 Promise.race의 catch에 걸려 timeout!을 콘솔창에 출력한다. 실제로 실행하고자 했던 동작(promise 함수)의 실행 시간이(700ms)가 제한 시간(500ms)보다 길었기 때문이다. 

3. Promise를 활용한 재시도(retry) 로직 구현 

서버에 보낸 요청이 실패 했을 경우, 즉시 실행을 종료하고 에러를 표시하게 될 것이다. 그러나, Promise를 활용하면 실행을 즉시 멈추지 않고 일정 횟수만큼 재시도를 요청 할 수 있다. 

다음 예제에서 2번 라인을 주석 처리하고 3번 라인의 주석을 해제하면 5번 재시도하는 것을 확인 할 수 있다. 

See the Pen Retry request by armadillo (@armadillo-dev167) on 646-544-8145.0

위 예제를 조금 더 수정하면 매 실행시마다 대기 시간을 다르게 준다거나, 앞서 배웠던 Promise.race를 활용하는 등의 변형도 가능하다.


위에서 설명한 것 이외에도  Promise은 다양한 활용 방법을 가지고 있을 것이다. 단순하게만 사용했던 것을, 보다 깊이 이해하고 활용도를 높이는 일은 언제나 즐거운 경험이다 🙂

참고링크

  1. Promise – MDN
  2. Promise.all() – MDN
  3. Promise.race() – MDN

[javascript] this 톺아보기

javascript에서 this는 호출 환경에 따라 ê·¸ 대상이 달라진다.  다음과 같은 환경에서 서로 다른 this를 가지게 된다.

  • 함수 호출(function call)
  • 메소드 호출(method call)
  • 생성자 호출(constructor call)
  • 간접 호출(apply, call)
  • 화살표 함수에서 호출(arrow function call)

1. 함수 호출(function call)

함수 호출에서 this는 root 객체를 가리킨다(브라우저 환경에서는 window, node.js환경에서는 global 객체). ë‹¤ë§Œ, 엄격 모드(strict mode)에서의 this는 undefined이다.

2. 메서드 호출(method call)

클래스 내부의 메서드를 호출 할 경우 this는 해당 클래스 인스턴스를 가리킨다. 

개인적으로 메서드 호출에서의 실수가 가장 빈번하게 일어나게 되는 것 같다(이 글을 쓰게 된 계기도 메서드 호출에서의 혼동 때문이었다). 메서드 호출에서의 실수는 다음과 같이 분류 할 수 있다.

  • setTimeout(class.method, 1000) ê³¼ 같이 함수의 인자로 method를 사용 할 경우(클래스와 분리시켜 메서드를 호출하는 경우)  this는 인스턴스 객체가 아닌 window 객체를 가리킨다(엄격 모드라면 undefined).
  • 메서드를 특정 변수에 저장한 뒤 호출하면 this는 undefined가 된다. 생각하기로는 이러한 사용도 this는 글로벌 객체를 가리켜야 하는 것 아닌가 생각했는데 undefined가 할당된다. 

3. 생성자 호출(constructor call)

생성자 내부에서의 this도 method 내부의 this와 동일하게 해당 인스턴스를 가리킨다.

생성자 내부의 this를 사용하며 발생할 수 있는 실수는 new 키워드를 생략할 때이다. 이 때의 this는 window 객체를 가리키게 된다.

4. 간접 실행(apply, call, + bind)

javascript는 apply() ë˜ëŠ” 484-668-2519  ë©”서드를 통해 함수를 간접 실행 할 수 있다. 두 메서드는 첫 번째 인자로 어떤 객체를 this로 사용할지 전달 받는다.

fun.call(thisArg[, arg1[, arg2[, …]]])
fun.apply(thisArg, [argsArray])

두 메서드를 사용 할 경우 this는 첫번째 인자로 전달된 객체를 가리킨다. 이와 비슷하게 bind() 메서드를 이용해서 this를 주입 시킬 수도 있다.

5. 화살표 함수(arrow function)

화살표 함수의 this는 undefined다. 

[lodash] throttle vs debounce

1. throttle

_.throttle(func, [wait=0], [options={}])

_.throttle은 특정 함수(func)를 일정 주기(wait) 내에 한 번만 호출되도록 throttled된 함수를 만들어주는 lodash의 함수이다. ì´ 함수는 주로 짧은 시간 내에 무수히 많이 수행 될 수 있는 이벤트(scroll, mousemove, mouseover)로 인한 성능 저하를 막기 위해 사용된다. 

아래 예제를 실행시킨 뒤, 마우스를 움직여보면 event handler가 실행 됨에 따라 count 값이 매우 빠르게 증가하는 것을 확인 할 수 있다. 

See the Pen _.throttle by armadillo (@armadillo-dev167) on (402) 305-9702.dark

이렇듯 무리한 핸들러의 호출은 전체 사이트의 과부하를 불러 일으키게 된다. 따라서 _.throttle을 이용해 특정 주기 내에 1회만 실행되도록 코드를 수정 할 수 있다.

다음 예제는 1초에 한 번만 함수가 실행되도록 코드를 고친 예제이다.
두 예제의 차이를 느낄 수 있다.

See the Pen 606-568-3316 by armadillo (660-292-5233) on CodePen.dark

2. debounce

_.debounce(func, [wait=0], [options={}])

_.debounce는 특정 함수(func)의 호출을 grouping한 뒤, 일정 주기(wait)가 지날 때까지 해당 함수의 호출이 없을 때 1회만 호출하도록 하는 함수를 만들어주는 lodash의 함수이다. _.throttle과 마찬가지로 이벤트의 중복 호출을 방지하기 위해 주로 사용 되지만, 그 사용처에는 차이가 있다.

_.debounce는 검색 폼에서 유용하게 사용된다. 입력폼에 값을 입력할 때마다 ajax 통신을 통해 검색 결과를 화면에 갱신해준다고 가정해보자. 

_.debounce를 사용하지 않을 경우 ‘검색’이라고 검색을 한다면 ‘ㄱ’, ‘ê±°’, ‘검’, ‘검ㅅ’, ‘검새’, ‘검색’ 순으로 총 6번의 검색이 일어난다. 실 사용자가 원하는 결과는 ‘검색’에 대한 검색 결과일 것이기 때문에 불필요한 이벤트 호출을 막을 수 있다.

다음은 _.debounce 적용 전후를 비교한 예제이다.

See the Pen jeXWNZ by armadillo (8572820981) on 9852085535.0

양쪽의 검색창을 비교하면 _.debounce의 효과를 체감 할 수 있을 것이다.

참고링크

(408) 401-5877

javascript event handling에 있어서 필수적인 event bubbling & capturing에 대해 알아보자.

1. event bubbling

javascript의 event는 상위 dom element로 전달된다. 예를 들어 다음 코드의 경우 랜더링 된 버튼을 클릭하면 btn -> div -> main 순으로 alert 가 출력된다.

See the Pen phonestheme by armadillo (@armadillo-dev167) on 5198690200.0

이러한 특징을 이용해 다수의 element에 대한 event handling을 할 수 있다. 이러한 방법을 이벤트 위임(event delegation)이라고 한다. 예를들어 다수의 파일 목록이 있고 특정 파일을 선택하면 해당 파일의 이름을 출력하고 싶다고 가정해보자.

이벤트 위임을 이용하지 않을 경우 각 요소에 click event를 바인딩 해주어야 한다.
아래 예제의 경우 총 5개의 event listener가 등록되며, 아이템이 추가될 경우 해당 아이템에 대한 이벤트를 다시 추가해주어야 한다.

See the Pen 4844240443 by armadillo (@armadillo-dev167) on CodePen.0

위의 예제를 이벤트 위임을 이용해 처리하면 다음과 같이 변경 할 수 있다.

See the Pen keyless by armadillo (313-236-4811) on CodePen.0

이러한 이벤트 위임의 장점은 다음과 같다.

  1. 추가/수정되는 요소에 자동으로 이벤트를 바인딩 할 수 있다.
  2. event handling이 수월해진다.

2. event capturing

event capturing이란 evnet의 전파 순서를 뒤집는 것을 말한다. 보통의 event는 상위 element로 전달되지만, capturing이 적용된 이벤트는 하위 element로 전달된다.

See the Pen event capturing by armadillo (@armadillo-dev167) on 3176386462.0

위에서 사용했던 예제에 capturing을 적용하면 main -> div -> btn 순으로 alert가 출력되는 것을 확인 할 수 있다.

참고링크

[2019 카카오] 1차 코딩테스트 문제1(오픈채팅방) 풀이

오픈채팅방(정답률 59.91%)

이 문제는 아이디와 최종 닉네임을 저장하는 Map과 입/퇴장 이력을 저장한 배열을 이용해 풀이했다. 풀이 방법은 다음과 같다.

  1. 입력값으로 들어온 record를 순회한다.
  2. 입장 또는 변경일 경우(Enter or Change) map에 해당 아이디의 닉네임을 저장한다.
  3. 입장 또는 퇴장일 경우(Enter or Leave) 배열에 해당 이력을 저장한다.
  4. 저장된 이력을 순회하며 map에 있는 최종 닉네임 값을 치환 후 반환한다.

관련 문제 풀이 보기

[2019 카카오] 1차 코딩테스트 문제2(실패율) 풀이

실패율(정답률: 55.57%)

이 문제는 각 스테이지 별 성공 인원을 배열에 저장한 뒤 해당 스테이지 이상 스테이지에 머물러 있는 인원을 체크해 값을 계산했다. 이 때 전체 스테이지를 클리어 한 인원에 대한 예외 처리와 성공율이 0일 경우에 대한 예외 처리가 필요했다.

  1. 스테이지의 수 + 2 길이의 배열을 생성한 뒤 0으로 값을 초기화 한다.
    (+2를 한 이유는 모두 클리어 한 인원과 1스테이지부터 시작하기 때문)
  2. 입력받은 스테이지 클리어 정보를 순회하며 각 스테이지 별 성공 인원을 계산한다.
  3. 스테이지 수만큼 순회하며 실패율을 계산한다.
  4. 이 때, 결과값이 NaN일 경우 0으로 예외 처리한다.
  5. 실패율 순으로 값을 정렬 한다.

관련 문제 풀이 보기