go 언어를 처음 배우는 분들께 고루틴과 그 활용에 대해 아주 기초적인 설명을 한다고 가정하고 설명합니다.
반응이 있으면 응용편 심화편도 만들 계획이에요.
지적 및 질문은 댓글 달아주세요. 댓글 환영합니다!
고 루틴 (go routine)이 대체 뭘까?
go 언어를 배우기 시작한 분이라면, 한번쯤은 들어보았을 것이 고 루틴(go routine)입니다.
그럼 이 고 루틴이라는 것이 대체 뭘까요?
스레딩
고 루틴을 알려면 스레딩을 먼저 이해해야 합니다.
쉽게 설명해보자면, 예시를 한번 들어볼 수 있겠네요. 혼자 그림을 그려야하는 웹툰작가가 있다고 해봅시다. 이 작가는 일을 마치기까지 매우 힘들어할 뿐더러 작업 속도가 오래 걸리겠죠.
이때 작업을 보조해주는 어시스턴트 일꾼들이 들어오면요? 동시에 일을 진행하므로 진행 속도도 빨라지고 아주 좋을 거에요.
이게 바로 스레딩입니다.
내가 실행하는 프로그램에서 여러 개의 흐름(스레드)가 생겨 동시에 일을 처리할 수가 있는 것이죠.
참고로, 스레드를 제대로 이해하려면 운영체제라는 과목을 통해 프로세스와 스레드 개념을 제대로 학습해야합니다. 그렇지만 지금은 고 루틴을 설명해야하니 자세한 개념 설명은 생략할게요.
예시 : 고루틴 없는 코드
일단 위 프로그램을 실행해볼까요? 그럼 위와 같은 결과가 나올 겁니다.
루프 0 시작 → 3초 대기 → 루프 0 종료 → 루프 1 시작 → 3초 대기 → 루프 1 종료 … 이런 방식으로 순차적으로 루프를 실행하게 되니까요. 하나의 루프가 종료되고 다음 루프가 시작되는 것이죠. 실행 시간이 루프 10개 x 3초니까 총 30초 걸리는 코드네요.
그런데 이 '고 루틴'이라는 것을 사용하면, 저것과 완전히 다른 결과를 내줍니다.
대체 어떤 결과가 나오길래요?
앞선 코드를 수정해 적절히 고루틴을 사용했을 때, 다음과 같은 결과를 얻을 수 있습니다.
모든 루프를 동시에 실행한 뒤, 3초를 대기하고, 그 뒤 모든 루프가 종료됩니다. 실행 시간이 3초 정도면 된다는 거죠.
앞선 코드는 30초, 지금 코드는 3초... 지금 코드가 월등히 좋지 않나요?
앞선 코드에서는 3분 라면을 10개 끓일 때 한번에 하나씩만 끓여 총 30분이 걸리는데, 이건 모든 라면을 동시에 끓여 총 3분만에 끝내는 셈이니까요
(물론 반드시 하나씩 순서대로 처리해줘야하는 경우에는 go routine을 활용할 필요가 없습니다)
아무튼 이렇게, 함수의 각 루프를 개별적인 프로세스마냥 '동시에' 돌게 할 수 있습니다.
go언어에서는 이 고 루틴이라는 것을 통해 그렇게 일종의 스레딩으로 별개의 흐름을 만들어 줄 수 있어요.
그 방법은 너무너무 간단한데, go 라는 키워드를 붙여서 함수를 호출하기만 하면 되는 거에요!
go test(i)
끝입니다. 말도 안되게 간단하죠.
그런데 이때, 한 가지 주의해야할 점이 있어요!
메인함수에서 고 채널 수신을 기다리지 않을 경우, 메인 함수가 먼저 종료될 수 있다는 거에요. (ㅠㅠ)
예를 들면, loop의 종료 메시지가 하나밖에 안나왔는데 중간에 프로그램이 종료될 수도 있다는 거죠. loop 10개가 동시에 돌고 그것들 모두가 종료하는 모습까지 보고 싶은데, 저렇게 중간에 종료되면 문제가 생겨요.
그러니 우리가 원하는 결과를 제대로 얻으려면, 모든 고루틴이 종료될 때까지 main함수에서 대기하는 방법을 써야 합니다.
메인함수에 sleep()을 줘서 특정 시간동안 기다리게 만들 수도 있겠지만, 언제 고루틴 함수가 끝날 지 모르니 그렇게 기다리는 건 좋지 않겠죠. 그럼 이제 그 방법들이 무엇인지 알아봅시다.
고루틴을 대기하는 간단한 방법 (2가지)
main함수에서 고루틴을 대기하는 간단한 방법에는 2가지가 있습니다.
바로, 1. waitGroup 또는 2. channel(작업 종료 메시지 받기) 입니다.
waitGroup 사용
먼저 다음과 같이 wait을 통해 고루틴의 종료를 기다려 볼게요.
WaitGroup을 생성해서 내가 정한 개수의 고루틴을 기다려주는 거에요.
이렇게 하면 앞서 보여드린 고루틴 결과와 동일한 결과를 얻게 됩니다.
channel 사용
또 다른 방법으로는 간단히 channel을 사용하는 방법이 있습니다.
메인함수에서 go루틴으로 test() 함수를 실행한 뒤 종료할 때마다 채널에 메시지를 보내요. 그렇게 메인에서 채널의 메시지 수신을 10번 하게 되면, 10개의 함수 호출이 모두 종료될 때까지 기다려 종료하는 것과 같은 효과가 생깁니다.
작업 종료 메시지가 올때까지 기다려주기 때문에, 일종의 wait를 거는 것과도 효과가 같아요.
두 방법 중 하나를 사용하기도 하고, 두 방법 모두를 사용하여 go routine을 대기하기도 합니다.
그 방식은 개인의 선택에 달려있습니다.
참고로 기초적인 프로그래밍 단계에서는 멀티스레딩이 필요한 일이 많지 않아요. 주로 응용적인 작업으로 갈수록 멀티스레딩의 필요성이 증가하고는 합니다. 따라서 저런 동시병렬 처리를 통해 시간을 줄이고 여러 실시간 작업을 동시에 처리할 수 있습니다.
저는 예전에 처음 go언어의 기초와 go루틴을 공부할 때에, 다음의 링크를 통해 공부하였는데요.
고루틴에 대한 설명이 매우 잘되어있고, 실습을 통해 바로 체화하도록 유도해줍니다.
무료 코스인데 퀄리티가 아주 좋습니다. 매우 추천합니다.
구름EDU - 모두를 위한 맞춤형 IT교육
구름EDU는 모두를 위한 맞춤형 IT교육 플랫폼입니다. 개인/학교/기업 및 기관 별 최적화된 IT교육 솔루션을 경험해보세요. 기초부터 실무 프로그래밍 교육, 전국 초중고/대학교 온라인 강의, 기업/
edu.goorm.io
'IT > go 언어' 카테고리의 다른 글
[golang] 왕초보 grpc 튜토리얼 - 간단한 서버-클라이언트 메시지 교환 (0) | 2022.03.28 |
---|---|
[golang] protocol buffer 왕초보 실습 (0) | 2022.03.28 |