본문 바로가기
언어/Java

[Java]동기와 비동기 방식(Asynchronous processing model)

by Geunny 2020. 7. 26.
반응형

출처 - https://poiemaweb.com/js-async

 

취업을 준비하던 중

서버 비동기 연동 경험 이란 문구를 보게 되었다.

 

맨날 동기 비동기 연동이라는 단어를 많이 들어 봤으나

막상 개념을 머릿속에서 꺼내 보자니 확실하게 아는 것이 없는 것...

 

이번 글을 계기로 동기와 비동기 방식에 대하여 정리해 보자 한다.

 

구글에 동기와 비동기식을 검색해 본 결과

가장 많이 비유를 다음 드는 것이 은행 업무에 관한 예시가 있었다.

 

출처 - https://poiemaweb.com/js-async

동기식 처리는 은행 업무를 한 줄로 서 순서대로 업무를 진행하는 것과 같고,

비동기식은 여러 업무 창에서 일을 분업해서 진행하는 것과 같다고 볼 수 있다.

 

 

그럼 정확하게 업무 처리에 대해 확인해 보자.

 

 

동기식 처리 (Synchronous)

동기식 처리 모델(Synchronous processing model)은 직렬적으로 태스크(task)를 수행한다.

즉, 태스크는 순차적으로 실행되며 어떤 작업이 수행 중이면 다음 작업은 대기하게 된다.

 

 

동기식 처리방식

 

아래는 동기식으로 동작하는 코드이다. 순차적으로 실행된다.

package Synchro_Asynchro;

public class Synchro {
	public static void main(String[] args) {
		
		method1();
		method2();
		method3();
		
	}
	
	public static void method1() {
		System.out.println("method1");
	}
	public static void method2() {
		System.out.println("method2");
	}
	public static void method3() {
		System.out.println("method3");
	}
	
}

순차적으로 실행된다.

프로그램을 몇 번을 다시 시작해도 위의 순서는 변하지 않는다.

자바의 특성으로 위에서 아래로 내려오면서 코드가 main문 (Main Thread)에서 작성한 순서대로 메서드를 실행하게 된다.

 

그렇다면 다음은 비동기식을 알아보자.

 

비동기식 처리 (Asynchronous)

비동기식 처리 모델(Asynchronous processing model 또는 Non-Blocking processing model)은 병렬적으로 태스크를 수행한다.

즉, 태스크가 종료되지 않은 상태라 하더라도 대기하지 않고 다음 태스크를 실행한다.

비동기식 처리방식

 

예를 들어 서버에서 데이터를 가져와서 화면에 표시하는 태스크를 수행할 때,

서버에 데이터를 요청한 이후 서버로부터

데이터가 응답될 때까지 대기하지 않고(Non-Blocking) 즉시 다음 태스크를 수행한다.

 

이후 서버로부터 데이터가 응답되면 이벤트가 발생하고

이벤트 핸들러가 데이터를 가지고 수행할 태스크를 계속해 수행한다.

 

자바에서는 대표적으로 Multi Thread의 동작이 비동기식으로 작동한다.

다음 코드를 보고 이해해보자.

 

package Synchro_Asynchro;

public class Asynchro {
	public static void main(String[] args) {
	
	
		Thread t = new Thread(()->{
			method1();
		});
		Thread t2 = new Thread(()->{
			method2();
		});
		Thread t3 = new Thread(()->{
			method3();
		});
		
		
		t.start();
		t2.start();
		t3.start();
		
	}
	
	public static void method1() {
		System.out.println("method1");
	}
	public static void method2() {
		System.out.println("method2");
	}
	public static void method3() {
		System.out.println("method3");
	}
}

 위의 코드는 각 메서드를 각각의 Thread 객체에 담아 start 매서드 (Thread 실행 매서드)를 통해

각각의 메서드를 수행하게 된다.

 

동기식 처리의 경우 위의 코드에서

method1

method2

method3

의 순서로 결과가 나타날 것 같지만 실제로 수행되는 결과를 보면 다음과 같다.

예상과는 달리 method3이  method2 보다 먼저 출력된 것을 알 수 있다.

또한 이것은 항상 이런 순서가 아닌 실행 할 때마다 순서가 계속 바뀌게 된다.

이는 자바의 Thread 스케쥴러에 의해 제어되는데 이는 나중에 정리해 보도록 하겠다.

아래는 위에 같은 코드를 실행했을 때 서로 다른 결과 나온 상황이다.

이 처럼 자바의 Multi Thread 처리는 비동기식으로 처리되며,

처리 순서는 보장이 안 되는 것을 알 수 있다!

 

추가내용..

오늘 면접본 곳에서 이러한 질문이 들어왔다.

서버를 비동기 처리하면 어떤 장점이 있나요?

 

(음.. 어... 음.. 네! 렉이 안걸려요! ㅇㅈ...ㄹ...)

 

비동기 처리시 장점을 정리한다.

 

장점 : 요청에 따른 결과가 반환되는 시간 동안 다른 작업을 수행할 수 있습니다.
단점 : 동기식보다 설계가 복잡하고 논증적입니다.

 

그럼 서버에서는 어떻게 장점을 이용할 수 있을까? 예시를 들어보자.

 

1. 시간이 오래 걸리는 로직의 경우 동기처리시 한 청의 처리를 끝낼때 까지 다른 요청을 받을수 없지만

비동기로 처리시 다수의 요청을 동시에 받을 수 있다.

 

하지만 대부분의 서버 개발자들 사이에서 비동기 처리는 지양되고 있다...만약 DB에 데이터를 다루는 로직을 비동기로 처리할 시 데이터의 정합성이 맞지 않을수 있다.

(비동기를 직접 스레드로 구현할때 이야기 인거 같음..)

 

 

추가정리!

 

비동기식 사용 방식을 찾던 와중..

MSA 아키텍처에서 사용되는 MQ 를 이용한 비동기식 처리를 알게 되었다.

스프링(또는 백엔드) 에서 입력에 대한 처리후 

Kafka 또는 RabbitMQ 등을 이용하여 

메시지 큐에 이벤트(?)를 보낸후 백엔드 에서는 해당 처리를 완료 처리하고

해당 메시지에 대한 응답을 MQ를 통해 다시 해당 백엔드 서비스로 받아 처리하는 방식으로 비동기 처리가 가능하다.

 

이러한 기능을 이용한다면 백엔드 처리후 MQ~백엔드로 다시 받는 결과처리 로직을 기다리지 않고

백엔드로 들어오는 인풋 처리를 모두 단순히 메시지 큐로 요청 이벤트를 보내는 형식의 비동기 전송이 가능하다.

메시지 큐에 대한 정리는 나중에 더 자세하게 따로 정리가 필요할 듯 싶다.

(제가 이해한 방식으로 작성했습니다. 틀렸을 경우 댓글 부탁드립니다.)

댓글