티스토리 뷰

동기(Synchronous)와 비동기(Asynchronous)

시간이 동일시 되는가의 여부(함께 시간을 맞춤)

 

동기는 대상간에 동시에 진행되는 느낌이다. 함수는 보통 결과값을 return 해주기 때문에 그 결과값을 동일하게 가져가는지 여부도 판단의 요소가 되는 듯 하다. 동기는 하나의 시간을 가지며 진행된다. 동기적으로 작성된 것은 하나의 시간을 가지고 흐른다. 하지만, 비동기로 작성된 것은 하나의 메인 시간이 흐르는 동안 비동기 함수의 시간도 흐른다. 

Block과 Non-Block

제어권의 여부

 

하던 일의 진행의 막히냐 그렇지 않냐의 여부이다. 다른 함수를 호출할 때, 내 일이 막히면 block 상태이고, 호출한 뒤 제어권이 바로 넘어와서 계속 진행된다면 non-block 상태이다. non-block으로 처리할 땐, 그 작업이 끝나면 어떻게 처리해 줄 것인지를 고민해 주어야 할 듯 하다. 메인으로 사용되는 스레드가 non-block으로 다른 함수를 호출했다면, 그 결과 값을 기다려주는 스레드가 없기 때문에 non-block 메소드의 후처리 여부가 중요한 듯 하다. 따라서 이벤트를 발생시키면, 발생시킨 이벤트를 핸들러가 받아 처리해주는 것과 비슷하다고 생각했다.


보통의 경우 sync&block, asycn&non-block이 세트가 된다. 하지만 꼭 그런 것 만은 아니고, sync&non-block, async&block의 경우도 있다. 옆에 첨부한 블로그(참고할만한 블로그링크)에 그 차이에 대한 내용이 자세히 설명되어 있다. 스스로 생각해 본 것은 sync&non-block의 경우가 데몬 스레드라고 생각했다. 데몬 스레드는 스레드 자체로 따로 일을 하지만, 메인 스레드가 종료될 때 같이 종료된다. 따라서 시간은 동일시 되지만, non-block인 경우이다.

 

 

어떤 상황을 나눌 때, 동기냐, 비동기냐, block이냐, non-block이냐를 단정지어 나눌 수 없다. 이 개념들이 섞여 있는 경우가 많기 때문이다. Promise의 then으로 연결되는 함수를 본다면, 비동기 함수를 동기적인 표현으로 작성했다고 볼 수 있다. 이와 비슷하게 함수형 프로그래밍에서 메소드 체이닝도 비동기 함수들의 동기적 표현이다. 

 

사람은 보통 사고방식의 흐름인 동기적 순서대로 이해하는 것이 편하기 때문에 비동기 함수들의 동기적 표현이 많이 사용된다고 한다. 비동기, Non-Block과 관련된 내용은 데이터의 동기화를 맞춰주는 것이 매우 중요하다. 각각의 흐름이 따로 진행되기 때문에 동기화 문제가 항상 뒤따른다.

 

 

JS에서는 진정한 단일 스레드일까?

수업을 하면서 학생들끼리 궁금증이 생겼다. JS는 단일스레드로 비동기방식으로 처리한다. 이런 비동기 방식을 도와주기 위해 이벤트 루프가 존재한다. 이벤트 루프는 계속 돌면서 비동기 방식으로 처리되는 함수를 확인한다. 그렇기 때문에 비동기 처리 방식을 도와주는 다른 스레드가 존재한다. 스크립트 자체는 단일 스레드이지만, JS 실행환경까지 놓고 보면 단일 스레드가 아닐 것이라는 결론을 내렸다. (얘기하면서 내린 결론일 뿐, 정답이 아닐 수 있다.)

 

이 문제를 생각해보면서 진정한 단일 스레드에서는 비동기 처리가 불가하다는 생각이 들었다. JS도 이벤트 루프가 작동하는 또 다른 스레드가 존재하기 때문에 단일 스레드에서 비동기 처리가 가능한 것이다.

 

비동기 처리를 위해 사용한 Java의 API

- concurrent package의 executorService, Executors, CompletableFuture, Future 등이 있었다. 공부하면서 몇 가지 알게 된 사실들이 있다.

 

- Runnable, Callable : Runnable은 return 값을 가지지 않으나 Callable은 예외처리 및 return 값을 가질 수 있다.

- Executors에서 ThreadPool을 고정하여 생성할 수 있다. ThreadPool이란 스레드를 계속 생성하는 것이 아니라 지정한 스레드 풀을 사용해서 그 그룹의 노는 스레드를 활용하여 일을 시키는 방식이다. 

- CompletableFuture.runAsync 는 소모한다. return 값을 가지지 않는다. CompletableFuture.suppleAsync는 return 값을 가진다. 

 

이 기능들을 일부 사용하여 비동기 처리 프로그램을 만들었지만, 사실 잘 이해하지 못 하고 사용법을 찾아보며 코드를 구성했다. 비동기 처리를 위해 이런 것들이 존재함을 알고있자..😅

 

단일책임

객체지향 프로그래밍에서 사용되는 단일책임 이라는 의미가 나에게는 상당히 모호했다. 이런 저런 이야기를 통해 내린 결론은 메소드의 단일책임이 중요하다. 단일책임을 가진 메소드가 하나의 클래스를 구성하고 그것이 객체가 되는 것이기 때문에 객체는 비슷한 책임이 가진 메소드의 집합이라는 생각이 들었다. 객체는 더 큰 단위의 책임으로 메소드가 가진 책임을 묶어서 생각하자.

 

정리

Java로 이벤트를 가지는 비동기 프로그램을 만드는 것이 쉽지 않았다. 내 생각엔 비동기 프로그래밍을 위해서는 스레드가 적어도 2개이상 필요했다. 각 스레드간의 상황을 조율하는 것이 쉽지 않았고, 익숙하지 않은 메소드를 사용한 구현 방식 또한 어려웠다. 내가 만든 것은 비동기 방식으로 작성했지만, 이벤트 방식이었냐를 묻는다면 아닌 것 같다.

 

동기, 비동기, block, non-block을 단정지어 구분할 수 없으며 각 상황에 대한 이해가 필요하다. 비동기, non-block의 후처리 방식을 동기적인 사고로 풀어가는 것이 (현실적으로 사용되는) 프로그래밍에서 필요하다고 생각했다. 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함