본문 바로가기
프로그래밍

👨‍💻 [Go] Go 에서 시그널 이벤트를 처리하는 방법은 어떻게 되나요?

by 밝음의기둥 2025. 1. 15.
반응형

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


👨‍💻 안녕하세요, 윌리 프로젝트의 윌리 입니다.

Go 에서 시그널 이벤트를 처리하는 방법은 어떻게 되는지 간략히 알아보았습니다.


질문 >

Go 에서 시그널 이벤트를 처리하는 방법은 어떻게 되나요?

답변 >

Go에서 시그널(signal) 이벤트를 처리하기 위해 os/signal 패키지와 os 패키지를 사용합니다. 이를 통해 프로세스가 운영 체제에서 전달하는 시그널을 수신하고 처리할 수 있습니다. 이는 프로세스 종료, 인터럽트, 재시작 등을 관리하는 데 유용합니다.


1. 주요 개념

  • 시그널은 운영 체제가 프로세스에 특정 이벤트를 알리기 위해 사용하는 메커니즘입니다.
  • Go의 os/signal 패키지는 시그널을 처리하는 API를 제공합니다.
  • 일반적으로 처리되는 시그널:
    • SIGINT (Ctrl+C): 프로세스 종료 요청.
    • SIGTERM: 시스템이 프로세스를 종료하려고 할 때.
    • SIGHUP: 터미널 연결이 끊어졌을 때.
    • SIGKILL: 강제 종료(처리 불가).

2. 시그널 처리 기본 흐름

  1. 시그널 채널 생성:
    • 시그널은 채널로 전달됩니다.
    • os.Signal 타입의 채널을 생성해야 합니다.
  2. 시그널 알림 등록:
    • signal.Notify를 사용하여 특정 시그널을 채널에 연결합니다.
  3. 시그널 수신 및 처리:
    • 채널에서 수신한 시그널에 대해 처리 로직을 작성합니다.
  4. 프로그램 종료 처리:
    • 종료 시 필요한 정리 작업을 수행합니다.

3. 코드 예제

3.1. 기본 시그널 처리

package main

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

func main() {
	// 시그널 채널 생성
	signalChannel := make(chan os.Signal, 1)

	// 처리할 시그널 등록
	signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM)

	// 시그널 수신 대기
	fmt.Println("Waiting for signals... (press Ctrl+C to exit)")
	sig := <-signalChannel

	// 시그널 처리
	fmt.Printf("Received signal: %s\\n", sig)
	fmt.Println("Exiting gracefully...")
}

실행 결과

  1. 프로그램 실행 후 대기.
  2. Ctrl+C (SIGINT)를 누르면:
Waiting for signals... (press Ctrl+C to exit)
Received signal: interrupt
Exiting gracefully...


3.2. 고루틴을 사용한 비동기 처리

시그널 수신을 비동기로 처리하여 메인 작업과 병렬로 실행할 수 있습니다.

package main

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

func main() {
	// 시그널 채널 생성
	signalChannel := make(chan os.Signal, 1)
	signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM)

	// 시그널 처리 고루틴
	go func() {
		sig := <-signalChannel
		fmt.Printf("Received signal: %s\\n", sig)
		fmt.Println("Performing cleanup...")
		time.Sleep(2 * time.Second)
		fmt.Println("Cleanup complete. Exiting...")
		os.Exit(0)
	}()

	// 메인 작업
	fmt.Println("Application is running. Press Ctrl+C to stop.")
	for {
		fmt.Println("Working...")
		time.Sleep(1 * time.Second)
	}
}


3.3. 특정 시그널에 따른 동작

여러 시그널을 등록하고 각 시그널에 따라 다른 동작을 수행할 수 있습니다.

package main

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

func main() {
	// 시그널 채널 생성
	signalChannel := make(chan os.Signal, 1)
	signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)

	// 시그널 수신 대기
	for {
		sig := <-signalChannel
		switch sig {
		case syscall.SIGINT:
			fmt.Println("Received SIGINT (Ctrl+C). Shutting down...")
			os.Exit(0)
		case syscall.SIGTERM:
			fmt.Println("Received SIGTERM. Terminating...")
			os.Exit(0)
		case syscall.SIGHUP:
			fmt.Println("Received SIGHUP. Reloading configuration...")
			// 설정 다시 로드 로직 추가 가능
		}
	}
}


3.4. 시그널 알림 중지

signal.Stop을 사용하여 특정 시그널 알림을 중지할 수 있습니다.

signal.Stop(signalChannel)


4. 유의사항

  1. SIGKILL과 SIGSTOP은 처리 불가:
    • 이 시그널은 운영 체제가 강제로 처리하며, 애플리케이션에서 이를 가로챌 수 없습니다.
  2. 채널 버퍼 크기:
    • 시그널 채널은 버퍼를 사용해야 하며, 버퍼가 없으면 채널이 블로킹됩니다.
  3. 정리 작업:
    • 종료 시 필요한 작업(예: 파일 닫기, 데이터 저장 등)을 잊지 말고 처리하세요.

5. 결론

Go에서 시그널을 처리하는 것은 서버 애플리케이션과 같은 장기 실행 프로그램에서 필수적입니다. os/signal 패키지를 사용하면 특정 시그널에 반응하거나 프로세스 종료 시 정리 작업을 수행할 수 있습니다. 위 코드를 참조하여 애플리케이션 요구 사항에 맞는 시그널 처리 로직을 구현할 수 있습니다.



🎬 유튜브 채널 🎬

 

위로그@WiLog

📢 안녕하세요, 위로그@WiLog 시청자 여러분, 저는 윌리(Willee) 입니다. 📢 위로그@WiLog 는 자기계발을 목적으로 하는 채널 입니다. 📢 오늘도 즐겁게~ 자신을 위한 계발을 함께 해보아요~ d^_^b 📌

www.youtube.com

🎬 치지직 채널 🎬

 

위로그 채널 - CHZZK

지금, 스트리밍이 시작됩니다. 치지직-

chzzk.naver.com


반응형