Huny's Dev Blog

Golang term.MakeRaw를 사용하여 c의 fgetc(stdin) 구현하기

Hun Jang
Hun JangMar 19, 2025
Golang term.MakeRaw를 사용하여 c의 fgetc(stdin) 구현하기

C 언어에서는 fgetc(stdin) 또는 getc() 함수를 사용하면 사용자가 키를 누르는 즉시 해당 입력을 처리할 수 있다. 이는 엔터키를 입력할 때까지 기다리지 않고 즉각적인 반응을 요구하는 콘솔 애플리케이션이나 게임 개발에서 특히 유용하다.

반면 Golang에서 os.Stdin을 이용하여 표준 입력을 읽으면 기본적으로 사용자가 엔터키를 누를 때까지 기다리는 라인 버퍼링(Line Buffering) 모드로 동작한다. 이 때문에 키 입력 즉시 이벤트를 처리하기가 어렵다. 하지만 Golang에서는 golang.org/x/term 패키지의 term.MakeRaw() 함수를 사용하여 터미널의 입력 모드를 Raw 모드로 변경할 수 있다. Raw 모드에서는 입력 버퍼링이 비활성화되어 키 입력 즉시 문자를 읽을 수 있다.

다음은 Golang으로 키 입력 즉시 읽는 예제 코드이다.

package main

import (
	"bufio"
	"fmt"
	"log"
	"os"

	"golang.org/x/term"
)

func main() {
	state, err := term.MakeRaw(int(os.Stdin.Fd()))
	if err != nil {
		log.Fatalf("터미널 모드를 Raw로 전환하는 데 실패했습니다: %v", err)
	}
	defer term.Restore(int(os.Stdin.Fd()), state)

	reader := bufio.NewReader(os.Stdin)
	for {
		r, _, err := reader.ReadRune()
		if err != nil {
			log.Printf("입력 읽기 실패: %v", err)
			break
		}
		fmt.Printf("입력된 키: %q\r\n", r)
		if r == 'q' {
			fmt.Println("프로그램을 종료합니다.")
			break
		}
	}
}
go

중요한 주의사항으로, term.MakeRaw()를 호출했다면 반드시 프로그램 종료 시 term.Restore()를 호출하여 터미널 상태를 복구해야 한다. 이를 지키지 않으면, Linux의 경우 터미널에서 입력이 화면에 표시되지 않는(echo되지 않는) 문제가 발생할 수 있다.

요약

  • Golang은 기본적으로 입력 버퍼링을 사용하여 즉각적인 입력 처리에 제한이 있다.
  • term.MakeRaw()term.Restore()를 통해 입력을 즉각적으로 처리할 수 있다.
  • 콘솔 기반 인터페이스(TUI)나 간단한 콘솔 게임 개발에 유용하다.