게시글
질문&답변
2024.11.17
코루틴이 멀티스레드의 단점을 해결했다는 부분에 대해 질문드립니다.
1. 우선 아래의 정리가 맞는지 여쭤보고 싶습니다.코루틴은 스레드를 점유하는 형태로 동작하므로, 반대로 코루틴이 blocking될때 스레드를 점유하지 않음으로써 다른 코루틴이 해당 스레드를 점유하게 되고 결과적으로 스레드가 blocking되는 일이 없어진다.답변: 코루틴은 스레드를 사용하지 않을 때 blocking 될 수도 있지만, 일반적으로 스레드를 사용하지 않을 때는 양보하는 방식으로 동작합니다. 이와 관련된 부분은 강의 섹션 11. 코루틴의 이해 에서 조금 더 자세한 설명을 확인하실 수 있습니다.2. 그런데 blocking이 되는 현상이 언제발생하나요?강의에서 말씀해주신 내용에 따르면, 다른 스레드 혹은 코루틴의 결과가 필요할 때 blocking되는 상황에 놓여지는 것 같은데 맞을까요?답변: blocking이라기 보다는 "스레드를 양보하고 결과가 올 때까지 대기하는 상황에 놓여진다"라고 표현하는 것이 좋을 것 같습니다. blocking은 일반적으로 스레드를 사용하지 못하게 만들 때 사용하는 경우가 많아서요.결국 그렇다고하면 이전 코드의 완료를 보장하는, 그러니까 sync한 방식으로 코딩을 해야할 때 스레드가 놀지 않으면서 & completableFuture처럼 콜백지옥이나 예외처리가 어렵지 않게 하는 것이 코루틴의 장점이 맞을까요?답변: 넵 비동기 코드를 동기 코드 처럼 작성할 수 있는 것도 코루틴의 장점 중 하나입니다. 3. 일반적인 IO상황도 위에서 얘기한 blocking이 맞을까요?다르게 말하면, Dispatcher IO에서 [요청을 보내고 기다려야만 하는 상황]에서도 코루틴은 스레드의 점유권을 내려놓음으로써 해당 스레드가 다른 작업을 처리할 수 있게 되는걸까요?예를 들면, A스레드가 코루틴의 DIspatcher IO에 의해 관리되는 IO전용 스레드고 IO스레드는 해당스레드하나만 존재할때(가용가능한 다른 스레드가 없는 상황)c코루틴은 서버에 호출을 보내서 4초가 걸리고, d코루틴은 서버에 호출을 보내서 5초가 걸리면 A스레드에서 c코루틴과 d코루틴을 병렬적으로 처리할 수 있는건가요?답변: 병렬성은 일반적으로 여러 스레드에서 동시에 작업이 처리되는 경우를 뜻하기 때문에 이런 경우는 스레드가 하나이기 때문에 병렬적으로 처리한다고 하기보다. 비동기적으로 처리한다고 표현하는 것이 맞을 것 같습니다. 일반적인 IO 를 처리할 때 코루틴은 스레드를 양보하는 방식으로 비동기적으로 처리하기 때문에 blocking이 일어나지 않습니다. 단순히 다른 스레드를 하나 생성해서 두가지 작업을 다 맡겼더라면 해당 스레드에서 4초 + 5초해서 9초가 걸렸을텐데, 코루틴기반의 A스레드에서는 약 5초정도밖에(조금 더 길수는 있겠지만) 안걸리는 게 맞을까요?답변: 일반적인 작업(루틴)은 해당 작업이 끝날 때까지 스레드를 점유(스레드 블로킹) 하는 방식으로 동작하기 때문에 9초가 걸리는 것이 맞습니다. 하지만, 작업을 코루틴으로 만들면 스레드를 사용하지 않을 때는 양보하기 때문에 5초가 걸릴 수도 있습니다. 더욱 자세히 말씀드리면 이 경우는 상황이 두가지로 나뉠 수 있는데요. 만약 각 작업이 CPU 집약적인 작업이라면 스레드 양보가 일어나지 않기 때문에 작업을 코루틴으로 만들더라도 4+5 = 9 초가 걸리게 됩니다. 하지만 각 작업이 I/O 작업이라면 코루틴으로 만들게 되면 스레드 양보가 일어나기 때문에 5초만 걸리는 것이 맞습니다. 4. 3번에 이어지는 질문인데요, 만약 3번이 맞다고 하면 IO작업의 응답이 왔을 때 콜백같은 게 적용이 되어서 Dispatcher에 새로운 작업으로 추가되는걸까요?그러면, IO요청을 보낸 스레드와 IO응답을 처리하게 되는 스레드가 왠지 다를 수도 있을 것 같은데 맞을까요?답변: 넵 정확합니다. 코루틴이 일시 중단될 때는 Continuation이라는 실행 정보가 저장되고 코루틴 작업이 재개될 때 이 Continuation을 사용해 작업을 복구하는 상황을 거칩니다. 이 때문에 IO 요청이 시작된 스레드와 처리하는 스레드가 다를 수 있습니다. 좋은 질문 남겨주셔서 감사합니다. 궁금한점이 해결되셨으면 좋을 것 같습니다! 저도 코루틴을 처음 접했을 때 정말 아릅답다고 느꼈는데요ㅎㅎ 코루틴의 세계로 오신 것을 환영하고, 이 강의에서 필요하신 모든 지식을 가져가실 수 있으시길 바라겠습니다!
- 2
- 1
- 22
질문&답변
2024.11.13
Dispatcher.IO의 동작원리
chhong님 안녕하세요. 지식 공유자 조세영입니다.먼저 강의를 재밌게 봐주셔서 감사하다는 말씀 드립니다.질문에 답변을 드리면 Dispatchers.Default나 Dispatchers.IO의 스레드는 성능에 차이가 없습니다. 그럼에도 이 둘을 나눠놓은 이유는 각 디스패처는 작업의 특성에 맞게 스레드풀의 크기가 다르고 특정 작업을 위해 다른 작업이 방해받는 상황을 방지하기 위함이 큽니다. Dispatchers.IO는 IO 작업의 특성에 맞게 최대한 많은 작업을 병렬로 실행할 수 있어야 되면서, 각 스레드는 실행되지 않는 상태에 놓이는 시간이 길기 때문에 64개의 스레드를 사용할 수 있게 하고, Dispatchers.Default는 스레드가 아무리 많아도 실제로 CPU에서 동시에 처리할 수 있는 작업의 개수는 제한이 있기 때문에 프로세서의 수만큼으로 스레드를 제한한다고 이해해주시면 좋을 것 같습니다.답변이 도움이 되었다면 좋을 것 같습니다. 감사합니다.
- 0
- 2
- 27
질문&답변
2024.11.13
실무에서 runBlocking 와 CoroutineScope 실무 사용에 대해
아무도_모를_아이디님 안녕하세요. 지식 공유자 조세영입니다.해당 부분 안드로이드의 CoroutineScope 경우 인프런 AI인턴이 잘 답변해준거 같습니다. Activity의 경우 lifecycleScope에서, ViewModel에서 코루틴을 실행하는 경우 viewModelScope에서 코루틴을 실행해 생명주기별로 관리를 할 때 사용되고, runBlocking은 동기 코드와 코루틴의 연결점 역할이 필요할 때 사용됩니다.서버에서도 runBlocking은 마찬가지이고, CoroutineScope의 경우 별도로 구조화되어야하는 작업이 있는 경우, 혹은 작업이 특정 생명주기 별로 관리되어야 하는 경우 사용하면 될 것 같습니다. 스프링을 예로 들자면 특정 Bean이 파괴될때 취소돼야 하는 작업이 CoroutineScope 있는 경우 @PreDestroy와 함께 사용하면 되지 않을까 합니다.서버의 경우는 제가 개인적으로 공부했던 부분이고 실무를 경험해보지 않았다보니 답변이 부족할 수 있는점 양해 부탁드립니다.
- 0
- 2
- 38
질문&답변
2024.11.09
Code3-6에서 imageProcessingDispatcher가 inline으로는 동작하지 않는 이유가 궁금합니다
azsxd34님 안녕하세요. 지식 공유자 조세영입니다.다음 코드에서 Dispatchers.Default.limitedParallelism(2) 가 repeat 블록 안(launch 함수의 인자)으로 들어갈 경우 repeat 블록이 반복될 때마다 Dispatchers.Default.limitedParallelism(2)가 새로 생성되서 그렇습니다. 즉, Dispatchers.Default.limitedParallelism(2)을 repeat 블록 안에 넣으면 Dispatchers.Default.limitedParallelism(2)가 1000개 생성됩니다.fun main() = runBlocking { val imageProcessingDispatcher = Dispatchers.Default.limitedParallelism(2) repeat(1000) { launch(imageProcessingDispatcher) { Thread.sleep(1000L) // 이미지 처리 작업 println("[${Thread.currentThread().name}] 이미지 처리 완료") } } } 답변이 도움이 되면 좋을 것 같습니다!감사합니다.
- 1
- 2
- 24
질문&답변
2024.11.06
공유 스레드 풀 질문드려요!
아무도_모를_아이디 님 안녕하세요. 지식 공유자 조세영입니다.말씀 주신대로 강의에서 사용한 코루틴 라이브러리 버전을 기준으로 Dispatchers.Default는 프로세서 개수와 2중 큰 값만큼 스레드를 만들 수 있도록 되어 있으며, Dispatchers.IO는 64와 프로세서 개수 중 큰 값만큼 스레드를 만들 수 있도록 되어 있습니다.이 부분은 현재 이렇게 되어있더라도 추후 버전에서 바뀔 수 있습니다. 참고 부탁드립니다.감사합니다.
- 1
- 2
- 34
질문&답변
2024.10.29
코루틴 이름 출력관련해서 질문이 있습니다!
해당 부분 Hello Coroutines 섹션의 콘솔 로그, IntelliJ IDEA를 사용한 코루틴 디버깅에서 확인 하실 수 있는데요.코드 실행 시의 Run configuration의 VM options에 -Dkotlinx.coroutines.debug 옵션을 넣어 실행하면 코루틴의 이름이 같이 표기가 됩니다.(사진) 글로 확인하고 싶으시다면 다음 글에서 확인하실 수 있습니다!https://kotlinworld.com/381감사합니다.
- 2
- 1
- 58
질문&답변
2024.10.27
coroutineScope에 대해 질문 있습니다.
liltjay님 안녕하세요. 지식공유자 조세영입니다.일시중단 함수에서는 별도 처리 없이 CoroutineScope 객체에 접근이 불가능해 CoroutineScope의 확장 함수로 정의된 launch 나 async의 호출이 불가능하기 때문에 새로운 코루틴을 만들기 어렵습니다. 하지만 coroutineScope 일시 중단 함수를 사용하면 새로운 CoroutineScope 객체를 만들 수 있고, 이 객체를 사용해 launch나 async 함수를 호출 할 수 있게 되는데요.따라서 "coroutineScope 함수를 사용하면, 일시중단 함수 내부에 coroutineScope 객체를 만들 수 있다." 라는 문구는 이에 대한 설명을 위해 넣은 것으로 이해해주시면 감사하겠습니다.감사합니다. 혹시 추가적으로 궁금하신 점이 있으시다면 질문 부탁드리겠습니다!
- 1
- 2
- 56
질문&답변
2024.10.17
공유 스레드풀에 대하여 질문 있습니다
liltjay님 안녕하세요. 질문 남겨주셔서 감사합니다. 궁금하신 부분에 대해 답변 드립니다. 1) 미리 정의된 CoroutineDispatcher 중 IO 디스패처와 Default 디스패처는 공유 스레드풀을 사용하면서도 서로가 사용하는 스레드는 나눠져 있다는 것을 알려 드리기 위함이었습니다. 멀티스레드 프로그래밍을 할 때 사용되는 스레드가 어떤 스레드풀에서 생성되는지는지, 해당 스레드풀은 어떻게 동작하는지 이해하는 것은 매우 중요해서 이 부분을 설명에 넣었습니다. 2) limitedParallelism 함수를 IO 디스패처에 적용했을 때는 기존 IO 스레드의 개수에 영향을 받지 않는 별도의 스레드 집합을 사용하는 디스패쳐가 만들어집니다. 이런 디스패처는 다른 작업에 영향을 받지 않아야 하는 작업을 할 때 사용돼야 합니다. limitedParallelism 함수를 Default 디스패처에 적용했을 때는 기존 Default 디스패처의 스레드들 중 일부를 제한적으로 사용하는 디스패처가 만들어집니다. 이런 디스패처는 특정 작업이 모든 스레드를 사용하는 것을 방지해야 할 때 사용됩니다. 즉 limitedParallism 함수는 위와 같이 매우 특별한 상황에만 사용되며, 대부분의 경우에는 Dispatcher.IO나 Dispatchers.Default만 사용해도 문제가 없습니다. 3) IO 디스패처에 코루틴이 실행 요청되면 스레드가 부족하다고 판단될 경우 스레드가 생성되는데요. 이때 부족한 개수 만큼만 생성되는 것이 아니라 일부 여유를 두고 생성한 다음 해당 스레드들 중 하나에 코루틴을 보내는 것으로 알고 있습니다. 따라서 코루틴을 3개만 실행 요청하더라도 5개가 생성될 수 있고, 4개만 실행 요청하더라도 7개가 생성될 수 있습니다. 5,2,1 이나 1,2,4 같이 분배 되는 이유는 이렇게 생성된 스레드 중 하나에 코루틴이 보내지기 때문입니다. Executor 프레임웍도 스레드 생성과 관련된 내부 구현이 계속 바꼈고, 이 부분도 코루틴 라이브러리 내부의 최적화 정책에 따라 달라질 수 있어서 이 정도까지만 답변 드리는 것을 양해 부탁드리겠습니다. 좋은 질문 남겨주셔서 감사합니다! 답변이 도움이 되었으면 좋을 것 같습니다. 좋은 하루 되세요.
- 1
- 2
- 130
질문&답변
2024.10.09
강의와 책을 통해 학습한 내용을 출처를 남기고 기술 블로그 등에 공개해도 될까요?
pearl님 안녕하세요. 지식 공유자 조세영입니다.먼저 제 강의를 들어주셔서 감사하다는 말씀 드립니다ㅎㅎ저도 기술 블로그를 운영하고 있어서 pearl님이 궁금하신 부분이 어떤 부분인지 어떤 목적으로 사용하고 싶으신지 답변 드릴 수 있을 것 같습니다.학습하신 내용을 바탕으로 이해하신 내용을 블로그에 출처와 함께 남겨주시는 것은 괜찮습니다. 시각 자료들도 출처만 남겨 주신다면 모두 활용 가능하십니다.다만 학습자료를 모두 그대로 복사 붙여넣기 하시는 것은 허용되지 않습니다. 개인적으로는 기술 블로그에 자신이 이해한 내용을 바탕으로 글을 작성하고 공유하는 것이 공부한 내용에 대한 이해도를 높이는데 정말 도움이 많이 되기 때문에 권장하고 있습니다.*이 부분은 아마 다른 분들도 궁금해하실 수 있을 것 같아서 조금 자세히 답변 드렸습니다. 감사합니다.
- 1
- 2
- 109
질문&답변
2024.10.07
Coroutine과 VirtualThread의 차이점에 대해질문드립니다
태준님 안녕하세요. 조세영입니다.코루틴이 Virtual Thread와 비교했을 때 어떤 장점이 있을지에 대해 질문 주셨는데요. 먼저 제가 Java를 사용한 지 시간이 조금 지나서 JDK 21에 도입된 Virtual Threads에 대해서는 개념적으로만 알고, 실제로는 사용해 보지 않았기에 답변이 다소 부족할 수 있음을 양해 부탁드립니다.먼저 Virtual Threads는 가상 스레드를 생성해, 스레드 블로킹이 발생할 때 실제 스레드를 블로킹하는 대신 가상 스레드가 블로킹되며, 이를 통해 스레드 전환 비용을 줄이는 방식으로 동작합니다. 반면 코루틴은 일시 중단 지점을 가질 수 있는 작업 단위로, I/O 작업 같이 스레드가 계속해서 점유되지 않아도 되는 경우에는 스레드를 점유하지 않는 방식으로 작업을 최적화해 두 개념이 유사하게 느껴지실 수 있습니다.하지만 이 둘은 다소 차이가 있습니다. Virtual Threads는 JVM 수준에서 제공되는 기본적인 기능인 반면, 코루틴은 더 높은 수준의 추상화를 제공하고, 안정적인 비동기 코드를 작성할 수 있는 다양한 기능을 갖추고 있습니다.따라서 저는 이 둘이 상호 보완적으로 사용할 수 있다고 생각합니다. 예를 들어 Virtual Threads를 사용하여 경량 스레드를 관리하고, 그 위에 코루틴을 활용하여 구조화된 동시성이나 범위 기반의 작업 관리 같은 기능을 사용해 더 복잡한 비동기 처리 흐름을 유연하고 안정적으로 관리할 수 있을 것 같습니다.또한, 코루틴은 Kotlin에 특화된 도구이기 때문에, Kotlin이 JVM을 넘어 다양한 환경에서 동작하는 점을 고려하면 계속해서 비동기 프로그래밍에 중요한 역할을 할 것으로 보입니다. 반면, Virtual Threads는 더 범용적인 Java 생태계에서 활용도가 높아질 것으로 보입니다. 따라서 저는 두 기술이 각자의 장점을 살려가며 함께 발전할 가능성이 크다고 생각합니다.부족한 답변이지만 도움 되셨으면 좋을 것 같습니다. 감사합니다.
- 1
- 1
- 135