데이터베이스로 데이터를 조회하는 데, 성능을 꾀하기 위해 redis와 연동을 한다. 신규 기능에 적용하는 것은 어렵지 않을 것 같다. 하지만 기존 legacy 코드를 db에서 redis로 변경 한다면 새로운 전략이 필요할 것이다.

이런 경우가 얼마나 많겠냐마는 때때로 미션 크리티컬한 시스템 문제가 발생하면 한 번쯤 고려해 볼 만한 시나리오다.

db에서 redis로 변경한다면

  1. redis client 코드로 db 데이터를 조회하고 redis 데이터를 조회하여 결과 셋을 조합
  2. proxy 객체를 생성하여 db/redis 중 데이터 조회
  3. redis 명령 추가

위의 몇 가지 전략 중 성능이 가장 좋은 것은 3 > 2 > 1 이 될 것이고, 수정해야 할 legacy 코드의 양은 2 > 3> 1 순서가 될 것이라 짐작된다.

필자는 prototyping으로 redis 명령을 추가하는 방법을 구현해 보았다.

이름하여 ’MyRedis’라고 이름을 붙였고, 필자의 github 저장소에 commit 해 놓았다..

MyRedis

기존 Redis에서 ‘mysql’ 명령을 추가하였고, 이 명령은 mysql 데이터베이스에서 query 결과를 반환한다.

테스트로 'temp_table' 테이블을 생성하여 다음과 같은 데이터를 넣었다.

id username age
1 Junil Um 25
2 Coupang 3
3 POWERUMC 35

아래는 MyRedis로 ‘mysql’ 명령을 이용하여 데이터베이스에서 결과를 조회하는 redis-cli 결과 화면이다.

127.0.0.1:6379> mysql "select * from temp_table"  
1) "1"  
2) "Junil Um"  
3) "25"  
4) "2"  
5) "Coupang"  
6) "3"  
7) "3"  
8) "POWERUMC"  
9) "35"  

아직 구현 못한 부분이 있으나 더 구현한다면 이런 모습이 되지 않을까 한다.

127.0.0.1:6379> set mysql.host "localhost"  
127.0.0.1:6379> set mysql.user "umc"  
127.0.0.1:6379> set mysql.password "!@#$%"  
127.0.0.1:6379> set mysql.db "db_name"  

127.0.0.1:6379> mysql query dbresult 3600 "select * from temp_table;"     # key expired query  

127.0.0.1:6379> mysql lock  
127.0.0.1:6379> mysql query "update temp_table set age=1 where ...생략..."  
127.0.0.1:6379> mysql unlock  


Posted by 땡초 POWERUMC

댓글을 달아 주세요

전 세계 인터넷은 OpenSSL의 중대한 버그로 난리다. 이 버그의 주요 요지는 특정 OpenSSL을 사용할 경우 메모리의 64KB를 획득할 수 있고, 이 버그로 서버 인증서의 비밀키(개인키)를 취득하여 서버로 오가는 모든 패킷을 취득할 수 있다. 라는 것인데, 이를 가리켜 Heartbleed(심장출혈) 버그라고 한다.

그 만큼 심각한 버그가 맞는데, 일각의 미디어에서 최악의 시나리오를 너무 일반화시키는 것이 아닌가 싶다.

필자가 보안 전문가는 아닌 만큼 잘못된 부분은 너그러이 지적해 주길 바란다.

- 사용자는 모두 패스워드를 변경해야 하나?

해도 되고 안해도 된다. 어차피 개인정보는 오픈소스. :)

농담이고, 취약성이 있는 OpenSSL을 사용하면 공격자는 클라이언트의 사용자 요청 데이터를 가로챌 수 있다.

공격자가 사용자의 패스워드를 가로채려면, 서버 인증서의 비밀키를 취득한 경우에 해당 된다. 하지만 heartbleed 버그는 인증서의 비밀키가 없이도 서버의 메모리 최대 64KB를 볼 수 있다. 모든 데이터를 가로채는 것은 아니고 64KB에 해당하는 찌꺼기(?) 영역인데, 이 영역에 마지막 클라이언트의 요청 데이터가 저장되어 있다.

그러므로 자주 방문하는 사이트면 비밀번호를 변경하는 것이 좋고, 1년 넘게 방문하지 않은 사이트는 변경하지 않아도 된다.

- 서버 운영자는 인증서를 모두 폐기해야 하나?

취약한 버전의 OpenSSL을 사용하고, 최근 서버를 restart 한 경우가 아니라면 거의 제로(0)에 가깝다.

공격자가 64KB 중에서 인증서의 비밀키를 훔치기 위해서는 대상 서버를 재가동하고 첫 번째 요청인 경우에 이 비밀키를 훔쳐갈 수 있는 가능성이 높아진다고 한다. 이는 Answering the Critical Question: Can You Get Private SSL Keys Using Heartbleed? 에서 실험한 결과이다.

- OpenSSL 업그레이드가 불가능할 경우

소스 코드를 보면 곳곳에 아래와 같이 #ifndef OPENSSL_NO_HEARTBEATS 지시자를 발견 할 수 있다. 그러므로 OpenSSL 을 OPENSSL_NO_HEARTBEATS 옵션과 함께 다시 컴파일 하면 heartbleed 취약성 버그를 해결할 수 있다.

#ifndef OPENSSL_NO_HEARTBEATS  
int  
tls1_process_heartbeat(SSL *s) {  
...  
...  
}  

int  
tls1_heartbeat(SSL *s) {  
...  
...  
}  
#endif  

- OpenSSL 코드 품질

Heartbleed 취약성 버그가 해결된 7e840163 커밋을 살펴보면, 아직도 여전히 코드 리뷰를 통해 이슈가 남아있다.

코드 측면에서 변수의 이름이 'payload 는 payload_length 가 되어야 하지 않느냐' 라는 의견이 있다. 그리고 padding 값이 16으로 초기화가 되었음에도 곳곳에 하드 코딩된 '16' 값을 찾아볼 수 있다.

가장 최신 커밋에는 코드 리뷰가 완료되었는 지 모르겠으나, 당시 취약성 버그로 상당히 급하게 코드를 수정한 것 같다는 느낌을 받을 수 있었다.

OpenSSL 디버깅

Heartbeat 프로토콜 Heartbeat network, Linux-HA에서 알 수 있듯이 클러스터링(clustering) 및 고가용성(high-availability linux)을 위해 서버끼리 주고 받는 메시지라고 한다. active, standby 서버 두 대 중 active 서버가 죽으면 standby 가 가동되어 장애를 최소화 하는데, 이 때 ‘죽었니 살았니’ 빼꼼 찔러보는 걸 heartbeat 라고 한다고 한다.

실제 필자의 클라우드 서버에서 테스트를 진행하려고 했으나 여건이 되지 않아 실제 환경과 유사하게 테스트는 하지 못했다.

먼저, github의 OpenSSL 소스 코드를 받고, 버그가 있는 tag 및 branch를 checkout 한다. 이어 디버그 모드로 컴파일을 하면 테스트 준비는 완료된다. 그리고 heartbeat 패킷을 보내줄 수 있는 github의 pacemaker 클라이언트 코드를 받는다.

호스팅된 openssl, lldb attaching

디버그 모드로 컴파일된 openssl 을 self-hosting으로 실행한다.

$ lldb openssl s_server -www  

그리고 openssl/ssl/t1_lib.c 소스 코드의 tls1_process_heartbeat 함수에 브레이크 포인트를 걸었다.

(lldb) br list  
Current breakpoints:  
1: name = 'tls1_process_heartbeat', locations = 1, resolved = 1, hit count = 3  
  1.1: where = openssl`tls1_process_heartbeat + 21 at t1_lib.c:2484, address = 0x000aff55, resolved, hit count = 3  

이제 pacemarker 를 통해 heartbeat를 보냈다.

$ ./heartbleed.py -p 4433 -t 100000 localhost  

t1_lib.c 로컬 변수

다음의 코드 중 &s->s3->rrec.data[0]는 incoming 데이터가 포함 된다.

int  
tls1_process_heartbeat(SSL *s)  
    {  
    unsigned char *p = &s->s3->rrec.data[0], *pl;  
    unsigned short hbtype;  
    unsigned int payload;  
    unsigned int padding = 16; /* Use minimum padding */  

함수의 매개변수로 SSL *s 구조체의 s3 구조체의 데이터는 다음과 같다. s3->rrec가 클라이언트에서 보낸 데이터가 되겠다. 이 구조체는 다음과 같은 값을 가지고 있다.

(lldb) e *s->s3  
(ssl3_state_st) $58 = {  
  flags = 0  
  delay_buf_pop_ret = 0  
  read_sequence = ""  
  read_mac_secret_size = 0  
  read_mac_secret = ""  
  write_sequence = ""  
  write_mac_secret_size = 0  
  write_mac_secret = ""  
  server_random = "SN\x91ki��E\x82V\x01%E\v[t�7�\x91\x88\x9e[�\x8af\x95\x92iU"  
  client_random = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"  
  need_empty_fragments = 0  
  empty_fragment_done = 0  
  init_extra = 0  
  rbuf = (buf = "\x16\x03\x01\x18\x03\x01", len = 17736, offset = 11, left = 0)  
  wbuf = (buf = "", len = 17584, offset = 12, left = 0)  
  rrec = (type = 24, length = 3, off = 0, data = "\x01��|\x03\x01BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", input = "\x01��|\x03\x01BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", comp = 0x00000000, epoch = 0, seq_num = "")  
  wrec = (type = 22, length = 9, off = 0, data = "\x0e", input = "\x0e", comp = 0x00000000, epoch = 0, seq_num = "")  
  alert_fragment = ""  
  alert_fragment_len = 0  
  handshake_fragment = ""  
  handshake_fragment_len = 0  
  wnum = 0  
  wpend_tot = 4  
  wpend_type = 22  
  wpend_ret = 4  
  wpend_buf = 0x0236c800 "\x0e"  
  handshake_buffer = 0x00000000  
  handshake_dgst = 0x007071e0  
  change_cipher_spec = 0  
  warn_alert = 0  
  fatal_alert = 0  
  alert_dispatch = 0  
  send_alert = ""  
  renegotiate = 0  
  total_renegotiations = 0  
  num_renegotiations = 0  
  in_read_app_data = 0  
  client_opaque_prf_input = 0x00000000  
  client_opaque_prf_input_len = 0  
  server_opaque_prf_input = 0x00000000  
  server_opaque_prf_input_len = 0  
  tmp = {
    cert_verify_md = ""
    finish_md = ""
    finish_md_len = 0
    peer_finish_md = ""
    peer_finish_md_len = 0
    message_size = 124
    message_type = 1
    new_cipher = 0x002ca8d0
    dh = 0x00000000
    ecdh = 0x00706dc0
    next_state = 8576
    reuse_message = 0
    cert_req = 0
    ctype_num = 0
    ctype = ""
    ca_names = 0x00000000
    use_rsa_tmp = 0
    key_block_length = 0
    key_block = 0x00000000
    new_sym_enc = 0x00000000
    new_hash = 0x00000000
    new_mac_pkey_type = 0
    new_mac_secret_size = 0
    new_compression = 0x00000000
    cert_request = 0  
  }  
  previous_client_finished = ""  
  previous_client_finished_len = '\0'  
  previous_server_finished = ""  
  previous_server_finished_len = '\0'  
  send_connection_binding = 0  
  next_proto_neg_seen = 0  
}  

openssl 코드에서 2491: n2s(p, payload);가 클라이언트에서 요청한 payload 인데 이 값은 다음과 같다.

(lldb) fr v payload  
(unsigned int) payload = 65517  

실제 요청된 값과 길이를 체크하지 않은 채 아래와 같이 바로 메모리를 할당하게 되는데

   2505          * message type, plus 2 bytes payload length, plus
   2506          * payload, plus padding
   2507          */  
-> 2508         buffer = OPENSSL_malloc(1 + 2 + payload + padding);
   2509         bp = buffer;
   2510
   2511         /* Enter response type, length and copy payload */  

아래의 코드의 함수가 실행되면서, 위에서 할당된 메모리의 65536 bytes (=1+2+payload+padding) 를 buffer에 쓰면서 클라이언트로 64KB 의 over-read 된 메모리의 데이터까지 클라이언트에 response 된다.

   2516         /* Random padding */
   2517         RAND_pseudo_bytes(bp, padding);
   2518  
-> 2519         r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
   2520
   2521         if (r >= 0 && s->msg_callback)
   2522             s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT,  
(lldb) fr v
(SSL *) s = 0x00469c10
(unsigned char *) p = 0x012f8a0b "|\x03\x01BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
(unsigned char *) pl = 0x012f8a0b "|\x03\x01BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
(unsigned short) hbtype = 1
(unsigned int) payload = 65517
(unsigned int) padding = 16
(unsigned char *) buffer = 0x01301600 "\x02��|\x03\x01BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
(unsigned char *) bp = 0x01301603 "|\x03\x01BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
(int) r = -1

메모리가 확보되는 buffer = OPENSSL_malloc(...)는 함수부 선언의 unsigned char *p = &s->s3->rrec.data[0]&p 메모리 위치 근처에(&p 주소보다 더 높은 주소) 확보가 된다. 위에서 &p는 incoming 데이터가 있다고 언급했다.

그러므로 heartbeat의 response의 값은 가장 최근에 남아 있는 incoming 데이터, 즉 클라이언트 요청 데이터의 찌꺼기가 남아있는데, over-read 버그로 인해 이 영역의 사용자 요청 데이터가 전송되게 된다.

이렇게 공격자가 훔친 데이터는 아래와 같이 클라이언트 요청 정보가 포함된다. 일반적으로 클라이언트가 서버로 요청하는 정보는 HTTP 프로토콜에 포함되는 URI, Header, Cookie 등을 가로챌 수 있다.

아래는 64KB 범위 안에서 클라이언트가 보낸 incoming 찌꺼기가 남은 64KB 메모리 값의 일부분이다.

(lldb) m r p --count 250  
0x0237300b: 7c 03 01 42 42 42 42 42 42 42 42 42 42 42 42 42  |..BBBBBBBBBBBBB  
0x0237301b: 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42  BBBBBBBBBBBBBBBB  
0x0237302b: 42 42 42 00 00 4e c0 30 c0 28 c0 14 00 9f 00 6b  BBB..N�0�(�....k  
0x0237303b: 00 39 00 88 c0 32 c0 2e c0 2a c0 26 c0 0f c0 05  .9..�2�.�*�&�.�.  
0x0237304b: 00 9d 00 3d 00 35 00 84 c0 12 00 16 c0 0d c0 03  ...=.5..�...�.�.  
0x0237305b: 00 0a c0 2f c0 27 c0 13 00 9e 00 67 00 33 00 45  ..�/�'�....g.3.E  
0x0237306b: c0 31 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c 00 3c  �1�-�)�%�.�....<  
0x0237307b: 00 2f 00 41 01 00 00 05 00 0f 00 01 01 2f 32 30  ./.A........./20  
0x0237308b: 31 30 30 31 30 31 20 46 69 72 65 66 6f 78 2f 32  100101 Firefox/2  
0x0237309b: 38 2e 30 0d 0a 41 63 63 65 70 74 3a 20 74 65 78  8.0..Accept: tex  
0x023730ab: 74 2f 68 74 6d 6c 2c 61 70 70 6c 69 63 61 74 69  t/html,applicati  
0x023730bb: 6f 6e 2f 78 68 74 6d 6c 2b 78 6d 6c 2c 61 70 70  on/xhtml+xml,app  
0x023730cb: 6c 69 63 61 74 69 6f 6e 2f 78 6d 6c 3b 71 3d 30  lication/xml;q=0  
0x023730db: 2e 39 2c 2a 2f 2a 3b 71 3d 30 2e 38 0d 0a 41 63  .9,*/*;q=0.8..Ac  
0x023730eb: 63 65 70 74 2d 4c 61 6e 67 75 61 67 65 3a 20 6b  cept-Language: k  
0x023730fb: 6f 2d 6b 72 2c 6b 6f 3b 71 3d                    o-kr,ko;q=


Posted by 땡초 POWERUMC

댓글을 달아 주세요

DeskBoard 앱은 프레젠테이션 등으로 발표를 자주 하는 분들을 위해 필자가 만든 앱입니다. (지난 블로그 글)

이번에 $9.99의 앱 가격을 이달 4월 말까지 $2.99 로 할인합니다.

DeskBoard 앱은 유료/무료 버전 두 가지가 있습니다.
무료 버전도 모든 기능을 지원 하지만 멀티 모니터(두 대 이상 모니터)를 지원하지 않습니다.
그러므로 외부 모니터에 연결하거나 멀티 모니터 지원이 필요한 분만 유료 버전을 구매하시면 됩니다.

자세한 사항은 아래의 AppStore 아이콘을 클릭하면 됩니다.

DeskBoard (유료 $2.99 <- $9.99)
DeskBoard Free (무료)

[동영상] DeskBoard 앱을 사용하는 예

이하 앱에 대한 설명입니다.


여러분의 성공적인 발표나 세미나를 위해 당신에게 더 집중할 수 있도록 DeskBoard 앱을 사용해 보세요.
여러분이 전달하고자 하는 메시지를 다양한 도형을 사용하여 청중들에게 정확하게 전달할 수 있어요.
그럼 청중들은 당신이 무엇을 강조하는지 쉽게 알 수 있답니다.
DeskBoard 앱은 다음과 같은 분들이 사용하는 것을 권장합니다. ^_^

  1. 여러 사람 앞에 발표할 기회가 많은 분
  2. 맥을 프로젝터나 원격으로 공유하여 회의 하시는 분
  3. 강의를 하거나 직업을 가지신 분
  4. 개발자, 프로그래머 중 라이브 코딩을 해야 하는 분


Posted by 땡초 POWERUMC

댓글을 달아 주세요

인터넷 웹 서비스들이 느려졌다

HTML5 구현체가 속속 모습을 보이면서 웹 서비스들은 다양한 시도를 하고 있다. 과거에는 인터넷을 통해 콘텐트를 생산하여 전파를 했고, 이 콘텐트가 사람들을 모이게 했다. 웹을 통해 커뮤니케이션이 이루어 지면서 비슷한 관심사의 유저들에 의해 인터넷 커뮤니티가 속속 등장했다.

이것이 개인화로 이어지면서 개인이 운영하는 블로그가 많은 인기를 얻었다. 블로그를 열심히 잘 운영하면 사회 지위적인 약자도(a weak person), 잘 알려지지 못한 무림속의 전문가도 여러 사람의 관심을 받을 수 있는 발언권을 가질 수 있게 되었다. 웹 서비스가 자신을 PR하고 개인의 비즈니스 모델이 될 수 있음이 증명되었다.. 필자도 그런 부류 따위의 한 사람이다.

하지만 최근 인터넷 웹 서비스는 예전 보다 더 쾌적한 환경을 제공하는 지 의심이 된다. 방문하는 웹 사이트마다 괴롭다. 네트워크 대역은 더 용량은 더 커졌고, 개인 PC와 스마트폰의 CPU는 더 빨라짐에도 여전히 브라우저로 인터넷 서비스를 이용하는 것은 더 느려졌고 더 많이 기다려야 한다.

이런 몇 가지 주요 요인은 다음과 같이 정리된다.

1. Javascript 언어 본질적인 문제라기 보다

브라우저에서 동작하는 Javascript가 주요 원인이다. 브라우저에서 동작하는 Javascript는 운영 체제의 커널(kernel)이나 드라이버(driver)에 접근할 수 없으므로 가장 빠른 네이티브 함수를 사용할 수 없다.

Javascript 에서 thread(스레드)와 process(프로세스)를 그 외에 GPGPU(General-Purpose computing on Graphics Processing Units) 와 같은 네이티브 함수에 접근할 수 있다면, 브라우저는 '터보 엔진'을 장착한 것이다.

2. 또, 브라우저는 인터넷의 리소스를 동시에 다운로드 할 수는 있으나

Javascript는 동시에 처리할 수 없다. 

다운로드 받은 여러 개의 Javascript 파일은 빠르다고 소문난 크롬의 v8 엔진이 제공하는 context 객체에서 순차적으로 실행이 된다. 그 안에서 function을 만나면 scope 가 생성이 되는데, 이 scope을 병렬로 처리할 수 없고 blocking 되어 실행되어야 context안의 scope의 atomicity(원자성)이 보장된다. 풀어서 다시 정리하자면, javascript는 concurrents 일 수는 있으나 parallels 할 수 없다.

3. 이번 것은 필자가 제일 싫어하는 문제다.

HTTP/HTTPS는 stateless protocol 이므로 브라우저가 redirect/submit마다 매번 인터넷 리소스나 Javascript 를 reload 하게 된다. 브라우저 랜더링 성능을 향상시키기 위해 Javascript 파일을 HTML 문서 하단에 두는 추세이다. 그 결과 브라우저에 표현될 요소들은 모두 표시되었으나 자바스크립트 컴파일이 가장 마지막에 수행되므로 마우스나 키보드 동작 이벤트가 바로 발생하지 않는다. 

한 마디로, 굼떠진다. 브라우저의 화면은 다 떴는데, 마우스 휠과 움직임 그리고 클릭 같은 동작이 툭~툭~ 끊기거나 freezing 되어 버린다.

4. 프로그래밍 측면에서 오버 엔지니어링도 문제다.

웹 페이지에서 [AngularJS]와 같은 라이브러리를 사용하는 것도 성능 저하와 밀접한 관련이 있다. (nodejs 제외)

AngularJS 라이브러리는 공식 페이지에서 다음과 같이 소개한다.

HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications.

AngularJS의 가장 best practices 는 정적 페이지다. SPA(single page application)에 최적화 되어 있다. 하지만, 웹 응용 프로그램에 쓴다고 하더라도 문제가 될 것은 없다.

하지만 AngularJS를 MVC 웹 응용 프로그램과 같이 쓰게 되면 동일한 패턴을 관리하는 포인트가 하나 더 생긴다. 웹 응용 프로그램 레벨에서 MVC 패턴과 View 레벨에서 한번 더 AngularJS와 같은 MV(C) 패턴이 추가 된다. 필자 경험으로 웹 페이지에서 controlling이 필요한 view는 자주 보기 힘들다.

웹 페이지에서 model binding이 필요한 건지, view-model, templating이 필요한 건지 controlling이 필요한 건지, 다시 생각해 볼 수 있는 문제다.

결론

우리나라 속담에 '뱁새가 황새 쫓다가 가랑이 찢어진다'가 있다.

웹이 네이티브 쫓다가 가랭이 찢어진다. 인터넷 웹 서비스가 발전하고 있는 경향은 웹 브라우저에서 네이티브 데스크탑 응용 프로그램(desktop application)과 같은 사용자 경험(user experiences)을 제공하고 싶어 한다.

앞으로도 웹의 기술적인 진화는 네이티브 데스크탑 응용 프로그램 처럼 동작하기 위한 요소들이 추가될 것이다.

AJAX(asynchronous javascript and xml), web socket, web db, comet 과 같은 기술은 분명 웹을 진화시켰다. 하지만 웹 다워 졌다가 아니라, 네이티브 처럼 표현하기 위한 수단이 되었다. 그리고 지금은 많은 웹 서비스들이 네이티브 응용 프로그램을 웹 서비스로 그대로 옮겨 놓았다. 혁신적이기는 하지만 굳이 웹을 통해서 이용할 생각은 없다. 가끔 필요할 때 유용하게 이용하긴 하지만... 브라우저라는 sandbox 환경에서는 절대 네이티브와 같은 사용자 경험을 제공하지 못한다.

많은 모바일 네이티브 앱들이 브라우저에서 돌아가도록 갈아 탔고, 다시 네이티브로 귀환하는 경우를 가끔 본다. 모바일 브라우저에서 페이스북을 즐기긴 여간 까다롭지만, 페이스북 전용 앱을 사용하면 더 큰 재미를 얻는 느낌과 비유해도 될 것 같다.

아직 필자도 결론을 내릴 만큼 정리되지 않았다. 그리고 이런 추이를 지켜보는 것도 재미있다. 

다만 인터넷 웹 서비스는 네트워크 응답 속도와 체감 속도의 향상이 전부가 아니다. 사용자 경험 측면에서 좋은 성능을 내야 함이 분명한 결론이 될 것이다.

Posted by 땡초 POWERUMC

댓글을 달아 주세요

  1. muy.kr 2014.04.08 02:11 신고 Address Modify/Delete Reply

    정말 좋은 정보네요.. 잘 보고 갑니다^^

  2. A TearDrop 2014.04.08 03:22 신고 Address Modify/Delete Reply

    잘보고갑니다

  3. 업글 2014.04.08 04:04 Address Modify/Delete Reply

    정말 도움이 많이 되었습니다.
    요즘 추세인 역동적이고 멋진 이펙트들로 느려지는 문제를 제외한다면 요즘 웹은 만들기가 참 편해져갑니다.
    단, 구형브라우저들을 다 버린다는 가정하에 말이지요 ㅋㅋ

  4. 이승근 2014.04.08 12:39 Address Modify/Delete Reply

    AngularJS 의 소개 글은 html은 정적페이지를 위해 최고이지 동적페이지 작성에는 좋지 못하다 따라서 AngularJS를 만들었다 라는 내용인데요.
    정적 페이지가 AngularJS의 best practices라고 말하지 않습니다.

  5. 이승근 2014.04.08 12:58 Address Modify/Delete Reply

    그리고 모든 이벤트 드리븐 기반의 프로그래밍 모델( event loop )에서, 이벤트 핸들러는 event thread에 대해 serialize되어야 합니다.
    이는 모든 UI프로그래밍에서 UI접근은 ui thread(aka main thread/event thread )에서만 수행되어야한다는 제약과 동일합니다. DOM객체를 UI객체로 생각하시면 다른 native 프로그래밍 모델과 크게 다를바는 없습니다.

    그리고 web worker를 제공해서 별도의 thread에서 computing logic을 수행 할 수 있습니다.


    "concurrents 일 수는 있으나 parallels 할 수 없다."
    라는 말은 무슨 의미로 작성하셨는지 이해하기가 어렵네요

    • 땡초 POWERUMC 2014.04.08 17:26 신고 Address Modify/Delete

      읽어 주셔서 고맙습니다.

      '그리고 모든 이벤트 드리븐'은 자바스크립트를 말하시는 건가요?
      이벤트 드리븐이 race condition 하는데, 핸들러가 왜 serialize가 필요한가요?

      그리고 concurrents와 parallels의 의미는 컴퓨터 사이언스의 사전적 의미와 동일합니다.

  6. 이승근 2014.04.08 18:16 Address Modify/Delete Reply

    자바스크립트를 포함 모든 이벤트 드리븐 프로그래밍을 말하였습니다.

    이벤트 드리븐이 race condition이라는 말은 어떤 의미로 하신건지는 모르겠네요,
    race condition은 제가 아는 한에서는,
    같은 자원을 동시에 2개 이상의 thread에서 접근하는 상황인데요,
    이벤트 드리븐 모델에서는 이벤트 자체가 하나의 큐를 통해서 serialize되므로 핸들러간 race condition이 발생하지 않습니다. 그런 의미로, serialize되어야 한다는 말이었구요, 핸들러 안에서 serialize가 필요하다는 말은 아니였습니다.

    그리고, 제가 아는 concurrents는 "동시에 수행 할수 있는"을 의미하고, 자바스크립트의 경우 보통 모두 이벤트 핸들링에 의해서 하나의 thread에 의해서 수행되고, 더구나 DOM이라는 객체 자체가 concurrent한 접근을 허용하지 않기 때문에 concurrent하다고 말하기 어려울듯하네요,

    parallel은 물리적으로 동시에 수행하는 CPU 파이프라인이나,
    물리적으로 여러대의 PC에서 컴퓨팅을 수행하는것에 대해 일컷는 말이라고 알고 있어서, 무엇을 말하려고 하셨는지 잘 이해하기가 어렵습니다.




    • 땡초 POWERUMC 2014.04.08 20:39 신고 Address Modify/Delete

      내용 잘 보았습니다.
      허나 이런 방식으로 논쟁을 계속 해야 할 지 모르겠네요.

      먼저 이벤트 드리븐의 직렬화에 대해서 아래의 링크로 보아도 무방하겠죠?
      https://www.artima.com/weblogs/viewpost.jsp?thread=84958
      같은 메모리 프레임 안에 있는 객체의 포인터 객체를 왜 직렬화 해야 하는지요?
      이벤트는 포인터 함수를 통해 위임을 하고, 이런 방식으로 프로그래밍 하는 것을 이벤트 드리븐으로 알고 있습니다.
      serialize는 네트워크 통신이나 프로세스간, 또는 이기종 간에 데이터를 전송하기 위해 직렬화하는데, 왠 이벤트 드리븐에서 직렬화 얘기가 나오는지 이해가 가지 않네요.
      이것과 관련된 내용이 있으면 링크좀 부탁 드립니다.

      concurrents, 즉 non-blocking을 concurrents로 표현한 것입니다.
      잘못된 비유인가요?

  7. 이승근 2014.04.08 20:47 Address Modify/Delete Reply

    용어 측면에서, synchronization을 썼어야 하는데, serialize를 잘못사용해서 답글을 이해하시는데 혼란을 드린것 같네요.
    결국 event handler는 event thread에 대해 synchronization되며, 이는 모든 event driven기반 프로그래밍 모델에 동일한 사항인데, 자바스크립트의 문제점이라고 하시기에 답글을 달았습니다.

  8. 성현 2014.04.08 20:53 Address Modify/Delete Reply

    잘보구감니다.
    개발당시 요구사항도 요즘은 네이티브처럼 만들어달라는데. 그리하면 정말 검나 느림 ㅡㅡ

  9. Rachel:) 2015.01.22 10:45 신고 Address Modify/Delete Reply

    좋은글 감사합니다! 잘읽고가요~~