Javascript 동기화 문제

in #kr-dev7 years ago

같은 고통을 당하시는 분이 있는 것 같아서....

자바스크립트의 이벤트 중심 프로그래밍은 어떤 경우에는 매우 편리하지만 어떠한 경우는 지옥을 맛보게 합니다.

  1. 이벤트와 이벤트를 처리하는 이벤트 처리기가 있다.
  2. 이벤트를 받기 위해서는 이벤트 핸들러(콜백함수)를 이벤트에 등록한다.
  3. 이벤트가 발생하면 이벤트 처리기에서는 해당 이벤트에 등록된 핸들러(콜백)을 불러준다.

이것이 이벤트 공장입니다.
좀 더 현실적인 예를 들어 보면 다음과 같습니다.

  1. 버튼을 누른다는 클릭 이벤트가 있다.
  2. 버튼 클릭시 해야할 루틴(콜백)을 등록한다.
  3. 버튼 클릭이 발생하면 이벤트 처리기에서 핸들러를 불러준다.

와~ 더 이해가 안되네요...
코드로 이해하면 좀 나을라나요?

버튼이 눌렸을 경우 hello 알림창을 띄우는 함수를 처리기에 등록하는 과정입니다.

button.on('click', function() { alert('hello') })


이러한 코드는 자바스크립트만 있는 것이 아니고, UI 프로그래밍에서 기본적으로 쓰이는 방식입니다.
안드로이드에서도 비슷한 코딩을 하고 있습니다.

핸들러 함수에서는 전역 변수, 전역 함수등을 불러 쓸 수 있고 그래서 많은 문제가 발생하기도 합니다만, 이건 다른 이야기니까 나중에 하고...

자바스크립트에서는 이러한 이벤트 중심의 프로그래밍이 일반적인 프로그래밍입니다.
네트워크 소켓프로그래밍을 예를 들어 보면

socket.on('message', function(data) {} )

메시지가 오면 나를 불러~~~

그래 놓고는 예제프로그램에서는 console.log(data) 딱 한줄 적어놓고 네트워크 프로그래밍 끝~~~
정말 이런 현실이 싫습니다.

리얼월드에서 네트워크 프로그래밍은 이렇지 않습니다.
A 가 오면, B 를 보내고 기다리고, C 가 오면 D 가 올때까지 기다리고 이런식이죠.

잠깐... 아래코드에서 무엇이 먼저 출력될까요? A or B

socket.on('message', function(data) {console.log('A')})
console.log('B')



첫번째 라인을 수행한 후
컴퓨터가 무지막하게 느려져서 그럼에도 불구하고 빠른 네트웍으로 데이터가 오지 않는한
B 가 먼저 나옵니다.
socket.on 은 핸들러 등록만 하고 끝~~~ 여기서 멈추지 않아 다음 코드를 수행해야지~~
두번째 라인을 수행하고 네트웍에서 데이터가 오면 그제서야 A 가 나오겠지요.

다시 본론으로 돌아가서,
A 를 보내고 B 가 올때까지 기다려~~~ 이걸 프로그래밍 해보지요.

socket.send(A, function() { socket.on('message', function() {}) })



위 코드가 동작할까요?
send 의 인자는 두개입니다. 보낼 내용 그리고 보내고 나면 불리는 콜백 함수
콜백 함수에 이벤트 등록했어~~~
그런데 A 를 보내고 나서 이벤트를 등록하기 전에 B 가 와버렸어...

프로그램의 순서를 맞추는 것을 동기화라고 합니다.
보내고 기다리고 받은거 확인하고, 또 보내고 기다리고 받은거 확인하고...

자바스크립트 라이브러리중에 이벤트 중심으로 짜여진 것들은 이런 것들이 무척이나 어렵습니다.

해결책은 Promise, async library, generator 등이 있습니다만
아직까지 만족스러운 해결책을 얻지 못했습니다.
이짓 할바에야 python 이나 go 를 하고 말지 하지만
브라우저에서는 자바스크립트가 왕이니~~

Sort:  

원하시는 내용을 정확히 이해하지는 못했지만ㅠ 비동기 처리에 Rxjs 등의 Reactive programming paradigm을 적용하면 굉장히 쉽게 처리되는게 많습니다. 한번 살펴보시면 도움이 될 것 같네요!

오래간만이군요~~~ Rx 는 여러번 듣기는 했는데... 써본적이 없어서요~~
잠깐 살펴봤는데 모든 것을 시리즈로 처리한다고 하네요... 도움이 될 것 같습습니다. 감사합니다.

비슷한 고통을 느끼는 1인이 여기 있사옵니다 ㅎㅎ

격하게 공감합니다. 출력의 예제는 양반이고 object return하는 경우는 더 피곤해집니다만, 그래도 쓸수밖에는..전 promise를 애용합니다.

socket.on('message', function(data) {console.log('A')})
console.log('B')

이 코드에서 "컴퓨터가 무지막하게 느려져서 그럼에도 불구하고 빠른 네트웍으로 데이터가 오지 않는한
B 가 먼저 나옵니다." 라고 말씀해주셨는데요.

job queue 뒤에 작업이 등록되기 때문에 PC가 아무리 느려져도.. console.log("B")가 먼저 찍히고 다음에 찍히게 되는걸로 알고 있습니다 ^^;;

예 맞습니다...
A 가 먼저 찍힐일이 없다는 것을 좀 과도하게 표현했네요... ^^