팬아웃과 팬인
작업 분배하고 수집하기
팬아웃과 팬인은(는) CoddyKit의 무료 Go Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Go Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
분산 및 집계
분산은 여러 고루틴을 시작하여 하나의 채널에서 읽고 작업을 나누는 것을 의미합니다. 집계는 여러 고루틴의 출력을 다시 하나의 채널로 합치는 것을 의미합니다.
- 분산은 worker 간에 부하를 나눕니다
- 집계는 소비자가 사용할 수 있도록 결과를 모읍니다
생성기 stage
파이프라인은 생성기로 시작합니다. 생성기는 채널을 반환하고, 자체 고루틴에서 채널에 값을 공급한 다음 채널을 닫는 함수입니다.
func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}분산하기
분산하려면 여러 고루틴을 시작하여 모두 같은 입력 채널에서 읽도록 합니다. 각 고루틴은 같은 처리 함수를 실행하고 자체 출력 채널을 생성합니다.
in := gen(1, 2, 3, 4, 5)
c1 := square(in)
c2 := square(in)처리 stage
square stage는 in에서 읽은 각 값을 제곱하여 새 출력 채널로 보냅니다. 이 stage를 여러 개 실행하면 하나의 입력을 공유합니다.
func square(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n
}
close(out)
}()
return out
}merge를 사용한 집계
집계는 여러 채널을 하나로 합칩니다. sync.WaitGroup은 채널별 고루틴을 추적하고, 닫기 고루틴은 모든 고루틴이 끝날 때까지 기다린 후 합쳐진 출력을 닫습니다.
func merge(cs ...<-chan int) <-chan int {
out := make(chan int)
var wg sync.WaitGroup
for _, c := range cs {
wg.Add(1)
go func(c <-chan int) {
for n := range c {
out <- n
}
wg.Done()
}(c)
}
go func() { wg.Wait(); close(out) }()
return out
}WaitGroup을 사용하는 이유
각 집계 고루틴은 하나의 입력 채널을 out으로 복사합니다. 모든 입력 채널을 비울 때까지는 out을 닫아서는 안 됩니다. WaitGroup은 복사 작업을 수행 중인 고루틴의 수를 세고, 닫기 고루틴은 모든 고루틴이 끝날 때까지 wg.Wait()에서 대기합니다.
반복 변수 캡처
이전 버전의 Go에서는 각 고루틴이 공유 반복 변수가 아닌 자체 채널을 바인딩하도록 클로저가 c를 매개변수로 받아야 합니다. c를 명시적으로 전달하면 고전적인 반복 변수 버그를 피할 수 있습니다.
완전한 분산 및 집계
이 프로그램은 numbers를 생성하고, 두 개의 square stage로 분산한 다음, 결과를 집계하여 합산합니다.
package main
import (
"fmt"
"sync"
)
func gen(nums ...int) <-chan int {
out := make(chan int)
go func() { for _, n := range nums { out <- n }; close(out) }()
return out
}
func square(in <-chan int) <-chan int {
out := make(chan int)
go func() { for n := range in { out <- n * n }; close(out) }()
return out
}
func merge(cs ...<-chan int) <-chan int {
out := make(chan int)
var wg sync.WaitGroup
for _, c := range cs {
wg.Add(1)
go func(c <-chan int) { for n := range c { out <- n }; wg.Done() }(c)
}
go func() { wg.Wait(); close(out) }()
return out
}
func main() {
in := gen(1, 2, 3, 4, 5)
c1 := square(in)
c2 := square(in)
total := 0
for n := range merge(c1, c2) {
total += n
}
fmt.Println("sum of squares:", total)
}순서는 보장되지 않음
두 square stage가 같은 입력을 두고 경쟁하므로 합쳐진 출력의 순서는 비결정적입니다. 순서가 필요하다면 각 항목에 인덱스를 붙이거나 단일 stage를 사용해야 합니다.
분산해야 할 때
어떤 stage가 병목이고 작업을 병렬화할 수 있을 때 분산합니다. 상류 생성기가 느리다면 하류 worker를 더 추가해도 도움이 되지 않으며, worker가 작업을 받지 못한 채 기다리게 됩니다.
역압
버퍼 없는 채널은 자연스러운 역압을 만듭니다. 느린 소비자가 따라가지 못하면 빠른 stage가 차단됩니다. 이를 통해 파이프라인 전체에서 메모리가 제한 없이 증가하는 것을 막습니다.
빠른 확인
집계에 대한 지식을 확인해 보세요.
복습
분산과 집계를 배웠습니다:
- 분산: 여러 고루틴이 하나의 채널에서 읽습니다
- 집계: WaitGroup을 통해 여러 채널을 하나로 합칩니다
- 병렬 stage를 거치면 순서가 유지되지 않습니다
- 버퍼 없는 채널은 역압을 제공합니다
자주 묻는 질문
“팬아웃과 팬인” 강의는 무료인가요?
네 — “팬아웃과 팬인” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Go Academy 강의 전체를 잠금 해제할 수 있습니다. Go Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“팬아웃과 팬인”에서 뭘 배우나요?
작업 분배하고 수집하기 브라우저에서 직접 실행하는 실습 코드로 Go Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Go Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Go Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“팬아웃과 팬인” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Go Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Go Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.