[go] 시그널 처리와 동기식/비동기식 처리의 차이

시그널(signal)은 프로세스에게 외부에서 들어오는 이벤트를 나타내는 것으로, 프로그램이나 프로세스에게 어떤 이벤트가 발생했음을 알리는 데 사용됩니다. 이런 시그널을 처리하는 방식에는 동기식과 비동기식 두 가지가 있습니다.

동기식 시그널 처리

동기식 시그널 처리는 프로그램이 시그널을 받았을 때 해당 시그널을 바로 처리하는 방식을 말합니다. 이때 프로그램은 시그널이 발생할 때까지 대기하거나 시그널을 받을 때까지 다른 작업을 수행하지 않습니다. 이러한 처리 방식은 실시간 이벤트 처리나 중요한 작업의 완료 등 특정한 상황에서 많이 활용됩니다.

package main

import (
	"os"
	"os/signal"
	"syscall"
	"fmt"
)

func main() {
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)

	fmt.Println("대기 중입니다.")
	<-sig
	fmt.Println("시그널을 받았습니다.")
}

위의 예제는 Go 언어의 시그널 처리를 동기식으로 구현한 것입니다. os/signal 패키지를 사용하여 SIGINT와 SIGTERM 시그널을 받도록 하고, <-sig 구문으로 해당 시그널을 대기하다가 받을 때까지 대기하는 것을 볼 수 있습니다.

비동기식 시그널 처리

반면, 비동기식 시그널 처리는 시그널을 받으면 즉시 처리를 하지 않고, 이벤트 큐나 스레드 풀을 통해 별도의 처리 과정을 통해 시그널을 처리하는 방식을 말합니다. 이를 통해 프로그램이 멈추지 않고 계속해서 실행될 수 있으며, 병렬 처리나 대규모 시스템에서 유용하게 활용됩니다.

package main

import (
	"os"
	"os/signal"
	"syscall"
	"fmt"
)

func main() {
	sig := make(chan os.Signal, 1)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		for {
			<-sig
			fmt.Println("시그널을 받았습니다.")
		}
	}()

	fmt.Println("대기 중입니다.")
	select {}
}

위의 예제는 Go 언어의 시그널 처리를 비동기식으로 구현한 것입니다. go 키워드를 사용하여 익명 함수를 고루틴으로 실행함으로써 시그널을 받을 때까지 계속해서 대기하면서 프로그램이 멈추지 않고 실행됨을 볼 수 있습니다.

결론

동기식과 비동기식 시그널 처리는 프로그램이 시그널을 받았을 때의 처리 방식에 있어서 중요한 차이가 있습니다. 어떤 상황에서는 동기식으로 즉시 처리하는 것이 적합하고, 어떤 상황에서는 비동기식으로 별도의 처리 과정을 통해 처리하는 것이 더 유용할 수 있으므로, 실제 상황에 맞게 적절히 선택해야 합니다.

참고 자료: Go 시그널 처리