인프런 커뮤니티 질문&답변

gilson님의 프로필 이미지
gilson

작성한 질문수

2시간으로 끝내는 코루틴

single thread에서 여러개의 co-routine ( 각각 서버연동을 수행 ) 을 순차적이 아닌 concurreny 하게 수행하게 할방법은 없나요?

작성

·

848

2

single thread에서 여러개의 co-routine ( 각각 서버연동을 수행 ) 을 순차적이 아닌 concurreny 하게 수행하게 할방법은 없나요?

 

상황

  • Single Thread

     

  • ㄴ co-routine (1) : 서버연동 ( 사용자 정보를 요청 )

  • ㄴ co-routine (2) : 서버연동 ( 회원등급 정보 요청)

     

  •  

테스트 결과

  • co-routine (1)이 실행완료 -> co-routine(2) 수행

     

  • 동시적으로 서버에 요청하지 않음

     

 

CoroutineScope(Dispatchers.Default)로 설정하여 각각 쓰레드를 생성하면 동시적으로 수행되나,

이럴경우 co-routine을 사용해야 되는 의미가 필요한지 의문이 생김

결국 multi thread가 발생했다는건 context swiching이 발생한다는 뜻인데. 오히려 이럴 바에는

co-routine을 사용하지 않고 multi thread만 사용해서 해당 코드를 수행하는것고 어떤 차이가 있는지

잘 모르겠습니다.

제 의문에 대한 명쾌한 대답을 듣고 싶습니다.

답변 1

1

최태현님의 프로필 이미지
최태현
지식공유자

안녕하세요! gilson님! 정말 좋은 질문 남겨주셔서 감사합니다! 😊

 

결론부터 말씀드리면 가능합니다.

 

물론 조건이 두 가지 필요합니다! 👍 아래 다음과 같이 적어주셨는데요!

 

Single Thread 

  • ㄴ co-routine (1) : 서버연동 ( 사용자 정보를 요청 )

  • ㄴ co-routine (2) : 서버연동 ( 회원등급 정보 요청)

     

     

테스트 결과

  • co-routine (1)이 실행완료 -> co-routine(2) 수행

     

  • 동시적으로 서버에 요청하지 않음

     

 

위 내용을 토대로 설명드리면, 두 가지 조건은 다음과 같습니다! 😊

  1. (1) 서버연동과 (2) 서버연동이 각각 독립적일 것

    1. (1) 서버 연동의 결과물이 (2)에서 필요하면 안됩니다. 예를 들어 회원등급 정보를 알기 위해서는 먼저 사용자 정보를 알야아 한다면, 사용자 정보가 있어야만 회원등급 정보를 알 수 있으니 무조건 blocking이 발생할 수 밖에 없게 됩니다.

    2. 동시적으로 (concurrently) 서버에 접근하려면 각 요청이 독립적이어야만 합니다!

  2. 외부 자원를 호출하는 코드가 non-blcoking 코드일 것

    1. 혹시 스프링을 사용하신다면, RestTemplate 대신 WebClient의 non-blocking API를 사용해주셔야 합니다. (다른 non-blocking API를 사용하셔도 괜찮습니다)

    2. 만약 DB에 접근하시는거라면, DB에 접근하기 위해 기술이 blocking이 아닌지 역시 확인해보아야 합니다.

    3. 클라이언트에서 서버에 직접 접근하시는 경우도 마찬가지로, 사용하고 있으신 HTTP 호출 코드가 non-blocking 코드여야 합니다.

 

이 두 가지 조건을 만족시키면, 하나의 스레드에서 2개의 코루틴이 concurrently 돌아가는 것을 확인하실 수 있을겁니다!

 

즉, 하나의 스레드가

  1. 1번 API에 요청을 하고

  2. 놀지 않고 (blocking 되지 않고) 2번 API에 요청을 해 둔 다음

  3. 반환된 1번 결과 처리

  4. 반환된 2번 결과 처리

하는 것을 보실 수 있을 겁니다.

 

답변이 도움이 되었으면 좋겠습니다! 🙂 감사합니다! 🙇

gilson님의 프로필 이미지
gilson
질문자

답변 감사드립니다.

  • 당연히 blocking입니다. non-blocking 메소드를 사용했다면.. block되지 않고 바로 반환되었겠죠..제 의도는 blocking 메소드를 사용했을경우에는 co-routine 에서 제공되는 delay() 나 yield()를 호출한것처럼 자동으로 co-routine이 중단되지 않는지에 대한 물음 이었습니다.

  • 결론은 single thread에서는 아무리 여러개의 co-routine을 사용해도 blocking을 수행하는 기능이라면 co-routine 사이에 switching 이발생하지 않고 순차적으로 실행된다 .즉 co-routine을 사용하지 않고 일반적인 순차적인 code 를 사용하는것에 차이가 없다 라고 봐도 되는지요?

최태현님의 프로필 이미지
최태현
지식공유자

아하! blocking API를 사용하셨군요!

"결론은 single thread에서는 아무리 여러개의 co-routine을 사용해도 blocking을 수행하는 기능이라면 co-routine 사이에 switching 이발생하지 않고 순차적으로 실행된다 .즉 co-routine을 사용하지 않고 일반적인 순차적인 code 를 사용하는것에 차이가 없다"

라고 말씀해주신 부분이 정확히 맞습니다.

  • "blocking" 코드인 경우, 해당 코드가 thread를 blocking 하고 있기 때문에

  • 코루틴이 아무리 여러개 있더라도 코루틴을 실행시켜줄 유일한 하나의 thread는 blocking 되어 결국 순차적으로 (thread의 blocking이 해제된 다음) 실행된다

라고 봐주시면 될 것 같습니다! 🙏

 

굳이 굳이 따지면, blocking API를 여러개 호출해야 해서 결국 멀티스레드를 사용해야 한다면

코루틴을 이용한 멀티스레드 코드가 순수 Java concurrent API 보다 (사람에 따라) 조금 더 쉽고 간결하게 느껴질 수도 있다 정도의 차이가 있을 것 같습니다.

 

감사합니다 😊

gilson님의 프로필 이미지
gilson

작성한 질문수

질문하기