Skip to content

Files

Latest commit

e38c73d · Jan 13, 2025

History

History
241 lines (168 loc) · 7.87 KB

File metadata and controls

241 lines (168 loc) · 7.87 KB

Go 언어 (Golang) 기본 개념과 활용

목차


Go 언어란?

**Go 언어(Golang)**는 Google에서 개발한 오픈 소스 프로그래밍 언어로, 간결한 문법과 뛰어난 성능, 동시성 처리 기능을 제공합니다.

  • 2009년에 처음 발표되었으며, Rob Pike, Ken Thompson, Robert Griesemer가 설계.
  • 시스템 프로그래밍, 서버 애플리케이션, 클라우드 기반 서비스 개발에 적합.

Go 언어의 주요 특징

  1. 간결하고 읽기 쉬운 문법

    • 복잡한 문법 없이, 직관적인 코드 작성 가능.
    • 포인터, 구조체 등 시스템 프로그래밍 요소를 제공하면서도, 높은 가독성을 유지.
  2. 강력한 동시성 지원

    • GoroutinesChannels를 통해 경량 동시성 처리.
    • 수백만 개의 경량 스레드를 처리 가능.
  3. 정적 타입 언어

    • 컴파일 타임에 타입 검사를 수행하여 안정성을 보장.
  4. 컴파일 속도

    • Go는 빠른 컴파일 속도를 제공하며, 대규모 애플리케이션에서도 효과적.
  5. 배포 편의성

    • 단일 바이너리로 컴파일되어 외부 의존성 없이 실행 가능.
  6. 풍부한 표준 라이브러리

    • HTTP 서버, 파일 처리, 암호화 등 강력한 내장 기능 제공.

Go의 동시성 처리

Go의 동시성은 Goroutines와 Channels를 기반으로 효율적이고 안전하게 구현됩니다. Go의 동시성 모델은 복잡한 멀티스레드 프로그래밍보다 단순하며, 적은 코드로 고성능을 달성할 수 있습니다. 그러나 동시성을 활용할 때는 Deadlock, Race Condition, Goroutine 누수와 같은 문제를 방지하기 위한 적절한 설계가 필요합니다.

동시성과 병렬성의 차이

  • 동시성(Concurrency):

    • 여러 작업이 동시에 진행되는 것처럼 보이도록 설계된 모델.
    • 작업 간의 실행 순서가 유동적이며, 실제 CPU 코어의 개수와는 무관.
  • 병렬성(Parallelism):

    • 여러 작업이 실제로 동시에 실행되는 것.
    • 멀티코어 CPU에서 각 코어가 작업을 병렬로 처리.

Go의 동시성 모델은 작업 간의 협력적인 실행(동시성)을 중점적으로 다루며, 필요에 따라 병렬로 실행될 수 있도록 지원합니다.

Goroutines

Goroutine은 Go의 경량 스레드로, 동시 작업을 효율적으로 처리합니다.

Goroutines의 특징

  • Go의 동시성은 Goroutines로 구현됩니다.
  • Goroutine은 매우 가볍고, 실행 컨텍스트를 공유합니다.
  • 수십만 개의 Goroutines를 생성해도 성능이 뛰어난 이유:
    • Goroutine은 커널 스레드가 아닌 사용자 스레드로 동작.
    • Go 런타임 스케줄러가 Goroutines를 적절히 분배.

Goroutine 생성

Goroutine은 함수 앞에 go 키워드를 붙여 실행합니다.

package main

import (
	"fmt"
	"time"
)

func printMessage(message string) {
	for i := 0; i < 5; i++ {
		fmt.Println(message)
		time.Sleep(500 * time.Millisecond)
	}
}

func main() {
	go printMessage("Goroutine 1")
	go printMessage("Goroutine 2")
	time.Sleep(3 * time.Second)
	fmt.Println("Main function finished")
}

실행 결과:

Goroutine 1
Goroutine 2
Goroutine 1
Goroutine 2
...
Main function finished

Channels

Channel이란?

Channel은 Goroutine 간 데이터를 안전하게 교환할 수 있는 메커니즘입니다. Channel은 데이터 전송과 수신을 동기화하여 공유 데이터에 대한 경쟁 상태를 방지합니다.

Channel 생성

ch := make(chan int) // 정수를 전달하는 Unbuffered Channel 생성

데이터 전송과 수신

go func() {
	ch <- 42 // 데이터를 Channel에 전송
}()

value := <-ch // Channel에서 데이터 수신
fmt.Println(value) // 42 출력

Buffered와 Unbuffered Channel

  • Unbuffered Channel:
    • 송신자는 수신자가 준비될 때까지 대기.
    • 수신자는 송신자가 데이터를 보낼 때까지 대기.
    • 동기화 메커니즘으로 작동.
  • Buffered Channel:
    • 지정된 크기만큼 데이터를 저장 가능.
    • 송신자는 버퍼가 가득 차면 대기.
    • 수신자는 버퍼가 비어 있으면 대기.

Select 문

Select 문은 여러 Channel의 상태를 동시에 감시하여, 준비된 Channel의 작업을 처리합니다.

package main

import (
	"fmt"
	"time"
)

func main() {
	ch1 := make(chan string)
	ch2 := make(chan string)

	go func() {
		time.Sleep(1 * time.Second)
		ch1 <- "Message from Channel 1"
	}()

	go func() {
		time.Sleep(2 * time.Second)
		ch2 <- "Message from Channel 2"
	}()

	for i := 0; i < 2; i++ {
		select {
		case msg1 := <-ch1:
			fmt.Println(msg1)
		case msg2 := <-ch2:
			fmt.Println(msg2)
		}
	}
}

주의사항과 한계

  • Deadlock:

모든 Goroutine이 Channel에서 대기 상태에 빠지면 발생. 해결 방법: Channel의 크기, 송수신 타이밍을 적절히 설계.

  • Race Condition:

여러 Goroutine이 동시에 동일한 데이터를 수정할 경우 발생. 해결 방법: sync.Mutex와 같은 동기화 메커니즘 사용.

  • Goroutine 누수:

종료되지 않은 Goroutine이 메모리를 차지한 상태로 남아 있을 수 있음. 해결 방법: Context 또는 Done Channel을 사용해 종료 신호 전달.


Go의 주요 활용 사례

  • 클라우드 네이티브 개발: Docker, Kubernetes와 같은 클라우드 네이티브 도구는 Go로 작성되었습니다.
  • 웹 서버 및 API: Gin, Echo와 같은 Go 기반 웹 프레임워크를 사용해 고성능 RESTful API를 개발합니다.
  • 네트워크 서비스: Go는 높은 동시성 지원으로, 프록시 서버 및 메시징 시스템 개발에 적합합니다.
  • DevOps 도구: CI/CD 파이프라인, 클러스터 관리 도구 제작에 활용됩니다.

Go 사용 시 주의사항

  • Garbage Collector(GC)의 한계: Go의 GC는 효율적이지만, 실시간 시스템에서는 메모리 관리에 주의해야 합니다.
  • 패키지 관리: Go Modules를 사용하여 의존성을 관리합니다. 과거에는 GOPATH 기반 패키지 관리가 복잡했습니다.
  • 타입 시스템: 강타입 언어이지만, 제네릭이 추가되기 전에는 코드 중복이 발생할 수 있었습니다. Go 1.18 이상에서는 제네릭을 지원합니다.
  • 에러 처리: Go는 예외 처리 대신 명시적인 에러 반환을 사용합니다. 코드가 장황해질 수 있으므로, 적절한 에러 핸들링 패턴을 설계해야 합니다.
  • 경량 동시성의 과도한 사용: Goroutines가 많아지면 디버깅과 관리가 복잡해질 수 있으므로 적절히 관리해야 합니다.

결론

Go 언어는 간결한 문법, 높은 성능, 동시성 지원으로 현대적인 시스템 프로그래밍 및 클라우드 기반 개발에 최적화된 언어입니다. 특히, 클라우드 네이티브 및 대규모 서버 개발을 위해 설계된 Go는 빠른 컴파일 속도와 쉬운 배포로 개발 생산성을 크게 향상시킬 수 있습니다.