자바스크립트에서 웹 워커라는 것이 있다. 단순히 웹 페이지만을 띄우는 것을 넘어 다양한 작업을 하는 웹 앱이 나타남에 따라 작업의 양은 늘고 반응 속도는 빨라져야 한다. 그 일환 중의 하나로 사용할 수 있는 "웹 워커(Web Worker)"를 소개하려고 한다.


우선 이번 글에서는 웹 워커의 필요성 및 개념 소개 정도로 하고 사용법은 다음에 올리려고 한다.



시간이 오래 걸리는 작업

기본적으로 웹페이지는 자바스크립트 실행과 UI 반응(클릭, 스크롤 등)이 한 스레드에서 돌아간다. 그래서 자바스크립트에서 짧은 시간에 끝나지 않는 계산, 혹은 무한루프를 돌려보면 사이트 자체가 응답하지 않는다. 그래서 자바스크립트에서 실행하는 데 시간이 필요한 요청(AJAX)등은 비동기 이벤트를 이용한다.


스크립트 실행 순서도, 한 번에 한 가지 작업만 실행한다. 장시간 스크립트를 실행하면 사용자의 요청을 처리하지 못해 "렉"이 발생하므로(왼쪽의 "대기" 부분) 스크립트는 짧게, 비동기적으로 실행할 수 있는 작업은 비동기로 실행하는 것이 좋다.


그러나 비동기화할 수 없는 작업, 예컨데 데이터 파싱이나 물리엔진 연산 같은 경우도 있다. 일반적인 웹페이지라면 스크립트가 많지 않거나 적당히 빠르게 실행되어 상관없지만, 위와 같은 작업들이 많아지면 사이트의 반응이 느려지고, 사용자는 불편해 할 것이다. 이것을 해결하기 위해 "웹 워커"라는 표준이 만들어져 웹 브라우저들이 지원하고 있다. 안드로이드, 아이폰 등 모바일 환경에서도 지원하고 IE도 10 이상이면 가능한 등 대부분의 브라우저에서 사용할 수 있다고 한다.



웹 워커란?

웹 워커는 "스레드(Thread)" 기능을 웹 상으로 구현한 것이다. 위에서 설명한 내용대로 일반 자바스크립트는 "UI 스레드"라 부르는 기본 스레드 상에서 함께 돌아가서, 화면 처리와 스크립트 실행 등은 서로 기다려가면서 차례대로 실행한다. 이 방법은 DOM 관리 같은 기능을 복잡하게 설계할 필요가 없다는 장점이 있지만, 한 작업이 길어지면 나머지 작업들은 그게 끝날 때까지 기다려야 한다.


앞서 그림에서 흰색 화살표 하나가 UI 스레드를 의미한다. 한 스레드에서는 하나의 작업만 실행할 수 있는데, 웹 워커는 저 화살표를 하나 더 만드는 것이라고 생각하면 된다. 스크립트가 UI 스레드에서 실행되는 시간(주황색 선)이 줄면 사용자 입력에 반응하는 시간(파란색 선)이 늘어나고 더 빠릿빠릿한 페이지를 볼 수 있을 것이다.


웹 워커가 적용된 페이지의 흐름. 오래 걸리는 작업은 따로 빼내어 실행하고 결과만 받아서 표현한다. 만약 저 작업을 그냥 실행한다면 나머지 작업들은 하나도 실행되지 못해서 유저는 멈춰있는 화면만 멍하니 바라보아야 할 것이다. 웹 워커를 이용하면 이런 점에서 이득을 취할 수 있다.


실제로 코드 상에서 이용하는 법은 다음 글에서 보여줄 것이다.



단, 계속 진행하기 전에, 웹 워커가 만병통치약은 아니라는 점을 알아두어야 한다. 페이지가 무겁다고 느낄 경우, 우선은 스크립트로 진행하는 작업들 때문인지 확인하는 것이 우선이다. 단순히 이런 문제가 아닌, 리소스가 너무 많다던가 하는 것일 수도 있으며, 자바스크립트로 물리엔진을 돌리거나 웹페이지를 몇 개씩 받아와서 파싱하는 것처럼 많은 작업이 아니라면 속도 향상이 많지 않을 수도 있다.(심지어 이것들도 잘 처리하면 웹 워커 없이도 자연스럽게 사용할 수 있다.)

'소프트웨어 > JS, Node.js' 카테고리의 다른 글

웹 워커(Web Worker) - 2. 사용법  (0) 2017.02.23
웹 워커(Web Worker) - 1. 개요  (0) 2017.02.03
블로그 이미지

예비컴공돌이

각종 프로젝트 진행중! 생각날때마다 블로그 업데이트합니다.

외국 웹을 돌아다니다 보면 i18n이나 l10n 등의 표현을 종종 발견할 수 있다. leet체 같은건가 싶었는데 실제로는 조금 달랐다.

영단어를 보면 꽤 단어들이 몇몇 있다. 세상에서 제일 긴 단어 같은걸 언급하자는 건 아니고, 위의 것들도 긴 단어를 축약해서 표현한 것이다.


i18n은 internationalization(국제화), l10n은 localization(현지화)을 각각 첫 글자와 마지막 글자 사이의 글자수를 적어 표현한 것이다. 한국어로는 3글자로 끝나는데 영어로 표현하자니 아득하다. 저걸 몇번씩 타자로 치다 보면 키보드가 다 닳아버릴 것만 같다. 그래서 영어권 사람들은 더 간략하게 쓰기 위해 글자수 표현법을 만들어냈다.


이 두 단어는 번역 이야기에 자주 등장하는 단어들이다. 다른 나라에도 맞게 한다는, 얼핏 보면 비슷한 의미인 것 같다. 그 둘의 차이는 무엇일까?

전문적으로 배운 것은 아니지만 내가 이해한 바로는 이렇다.

i18n, 국제화는 한 언어를 여러 언어들에 대응시켜 다른 국가의 사람들에게도 읽힐 수 있게 만드는 작업이다.

반면 l10n, 현지화는 그것보다 좀 더 심화적으로, 단순히 내용이 읽히는 것에 더해서 지역명이나 인물을 바꾸거나, 숙어와 속담, 문화와 생활 양식 등을 대상 국가에 맞춰 치환해서 현지화라는 이름에 걸맞게 해당 문화권에 거부감 없게 다가갈 수 있도록 만드는 작업이라고 생각한다.


궁극적으로는 현지화를 하는 게 이상적이겠지만, 어찌 보면 당연하게도 인력, 지식, 시간, 예산 등 여러 한계가 있을 테니..

일반 스마트폰 앱이나 웹사이트 같은 경우는 i18n 번역 정도로도 충분히 접근성을 확보할 수 있다. 현지화는 게임이나 광고 등 사용자에게 더 감성적으로 다가가고자 하는 경우에 적합할 것이다.

블로그 이미지

예비컴공돌이

각종 프로젝트 진행중! 생각날때마다 블로그 업데이트합니다.

AVR을 프로그래밍할 때 주로 C를 사용하지만, 다른 부품들과 시간을 맞추기 위해 어셈블리를 써서 최대한 성능을 뽑아내야 할 때가 있다.

그 과정 중 자주 사용하는 동작인, 레지스터 하나의 값을 0으로 만드는 방법 34개가 정리된 글을 발견했다. 특정 조건/값에서만 되는 경우도 있고, 할 수 있다는 것에 의의를 두고 굳이 이렇게 쓸 필요는 없겠다 싶은 방법도 있어서 이 글에서 34가지 전부는 아니고 중요한/쓸만한 방법 5개만 추려보았다.


우선 시작하기에 앞서 사실 첫번째 방법이 가장 많이 쓰인다. 나머지 방법들은 상태 레지스터 결과가 다르니 경우에 따라서는 유용할 수도 있다.


지우고자 하는 레지스터의 이름은 "reg"로 표현한다.


1. CLR / EOR

clr reg

r0~r31까지 모든 레지스터에 대해 사용할 수 있는 가장 단순하고 쉬운 방법이다. CLR 명령어는 기본적으로 아래의 EOR(배타적 논리합, XOR)과 동일하다.

eor reg, reg

위 두 가지 명령은 실행하면 상태 레지스터를 변화시킨다. S(부호), V(오버플로우), N(음수) 비트는 0으로 설정하고, Z(제로) 비트는 1이 된다. 나머지 H(절반 캐리), C(캐리) 비트는 전에 설정된 대로 유지된다.


2. LDI

ldi reg, 0

처음에 CLR과 LDI의 차이를 찾아보다가 이 글을 쓰는 계기가 되었다. reg에다가 0 값을 넣는 명령인데, LDI는 CLR과 달리 r16~r31까지 상위 16개의 레지스터에만 사용할 수 있다. 그리고 상태 레지스터는 변하지 않는다! 전에 설정된 상태 그대로 유지되므로 분기 명령 전 레지스터 초기화 상황에는 유용할 듯 하다.


3. SUB

sub reg, reg

자기 자신을 빼서 0으로 만드는 방법이다. 이 방법은 r0~r31까지 모든 레지스터에 대해 사용할 수 있다. 1번과 비슷한데, 결과로 설정되는 상태 레지스터가 살짝 다르다.

S, V, N, Z 비트는 1번과 동일하게 설정되는데, EOR에서는 설정되지 않았던 H, C 비트까지도 SUB을 사용하면 0으로 설정된다.


4. MOV

mov reg, r1

x86 어셈블리를 사용해봤다면 mov reg, 0의 형태에 친숙할 것이다. 그러나 AVR에서는 레지스터간 복사는 MOV, 즉시값은 LDI로 분리되어 있다.

이 방법은 MOV 명령을 이용해 값이 0인 레지스터를 복사해오는 것인데, r0~r31까지 모든 레지스터에 대해 사용할 수 있고, LDI와 마찬가지로 상태 레지스터를 변화시키지 않는다.


r1 레지스터를 사용한 점도 눈여겨볼 수 있다. 순수 어셈블리로만 프로그램을 작성했다면 모를까, avr-gcc를 사용해 C 프로그램을 작성하고 인라인 어셈블리를 사용한다면 r1은 항상 0으로 되어있기 때문이다.(참고) C 인라인 어셈블리에서 r0 레지스터는 아무렇게나 사용해도 되며, r1 레지스터는 사용한 후에 반드시 0으로 돌려놓아야 한다.

물론 어셈블리 코드 내에서는 자유롭게 r1을 사용해도 되고, 중간에 인터럽트가 발생해도 r1에 저장된 값을 유지해주므로 코드가 끝날 때 r1을 0으로 돌려둘 것만 기억하면 된다.(인라인 어셈블리 문법으로 r1을 사용한다고 표시하면 알아서 된다.) 단, 이 MOV 명령 사용 전 r1을 0이 아닌 값으로 바꿨다면 이 방법은 쓸 수 없을 것이다.


5. MUL ([F]MUL[S[U]])

mul r0, r1

여기서도 4번과 마찬가지로 값이 0인 r1 레지스터를 사용했다. 이 방법의 기본적인 원리는 레지스터의 값에 0을 곱해서 0으로 만드는 것이다. 그런데 reg 대신 r0으로 사용한 것을 볼 수 있는데, MUL 계열 명령어의 특성상 곱셈 결과가 r1:r0에 저장되기 때문이다. 따라서 r0을 초기화할 때에만(reg=r0) 사용할 수 있다.


그리고 곱셈 명령어는 2 사이클만큼 소요되고, 상태 레지스터의 H, S, V, N 비트는 전 상태 그대로 유지한다. Z, C 비트는 0으로 설정될 것이다.

'하드웨어 > AVR·Arduino' 카테고리의 다른 글

레지스터를 지우는 방법 5가지  (0) 2017.01.23
블로그 이미지

예비컴공돌이

각종 프로젝트 진행중! 생각날때마다 블로그 업데이트합니다.