2026년 기준, Go 프로그래밍 완전 정복 가이드 (입문부터 Concurrency까지 한 번에)
처음 Go를 마주했던 날이 아직도 선명하다.
모니터엔 딱 한 줄이 떠 있었다.
package main
그 순간 묘하게 조용했다. 프레임워크도, 복잡한 설정도 없이 그냥 시작점 하나. 순간 이런 생각이 스쳤다.
“이 언어, 생각보다 단순한데?”
그런데 단순하다는 건 얕다는 뜻이 아니었다. 오히려 반대였다. 군더더기를 걷어낸 구조. 본질에 집중한 설계.
이 글은 단순한 요약이 아니다. Go를 처음 설치하는 단계부터 goroutine, channel, mutex, generics까지—말 그대로 처음부터 끝까지 전부 다 담는다.
그리고 최대한 쉽게 풀어간다.
어려운 개념도, 생활 속 비유로 설명한다.
“Go는 복잡함을 줄이고, 사고를 선명하게 만드는 언어다.”
이 문장이 오늘의 핵심이다.

Go란 무엇인가?
Go(또는 Golang)는 Google에서 만든 programming language다.
왜 만들었을까?
당시 Google 내부 개발자들은 C, C++을 쓰고 있었다. 성능은 최고였다. 하지만 코드가 점점 거대해지면서 유지보수가 힘들어졌다. 읽기 어렵고, 복잡했고, 협업이 부담스러웠다.
그래서 방향을 정했다.
- C/C++ 수준의 performance는 유지한다.
- 문법은 훨씬 단순하게 만든다.
- 대규모 backend system에 적합하게 설계한다.
그 결과물이 Go다.
Go의 특징을 간단히 정리하면 이렇다.
- statically typed language
- compiled language
- backend 중심 언어
- network service, cloud infrastructure, DevOps tooling에 강함
- concurrency를 언어 차원에서 지원
UI를 예쁘게 꾸미는 language는 아니다.
대신, 수백만 명이 쓰는 service의 엔진을 만드는 데 특화되어 있다.
JavaScript가 무대 위 배우라면,
Go는 그 뒤에서 조용히 돌아가는 발전기 같은 존재다.
Compiled Language vs Interpreted Language
우리가 작성하는 코드는 source code다. 사람은 읽을 수 있다.
하지만 CPU는 그걸 이해하지 못한다.
그래서 두 가지 방식 중 하나를 거친다.
1. Compiler
전체 코드를 한 번에 machine code로 변환한다.
그리고 CPU가 그 결과물을 실행한다.
Go는 compiled language다.
장점은 명확하다.
- 실행 속도가 빠르다.
- compile 단계에서 error를 잡는다.
- 최적화가 가능하다.
2. Interpreter
코드를 한 줄씩 읽으며 바로 실행한다.
JavaScript가 대표적이다.
유연하지만, runtime에서야 error가 터질 수 있다.
Go는 “미리 다 확인하고 가자”는 쪽에 가깝다.
엄격하다. 대신 안정적이다.
처음엔 귀찮게 느껴질 수 있다.
하지만 대규모 backend를 만들다 보면—이 엄격함이 고맙게 느껴진다.
Static Typing vs Dynamic Typing
JavaScript에서는 이런 코드가 가능하다.
let x = 1;
x = "hello";
아무 문제 없다.
하지만 Go에서는 불가능하다.
Go는 statically typed language다.
변수의 type은 compile 시점에 결정되고, 이후 바꿀 수 없다.
왜 이런 설계를 했을까?
CPU가 “이 변수는 항상 int다”라고 확신할 수 있으면, 더 빠르게 처리할 수 있다.
메모리 구조도 단순해진다.
비유하자면 이렇다.
- static typing은 상자에 물건을 담기 전에 라벨을 붙인다.
- dynamic typing은 일단 담고 나중에 라벨을 붙인다.
Go는 첫 번째 방식을 선택했다.
Go 설치와 개발 환경 설정
시작은 간단하다.
- https://go.dev 접속
- 자신의 OS에 맞는 installer 다운로드
- Windows → MSI
- Mac (M1/M2) → Arm64
- Intel Mac → Intel 버전
- Linux → 해당 installer
- 설치 진행
설치 후 terminal에서:
go
정상적으로 출력이 나오면 성공이다.
만약 안 된다면 PATH 설정 문제일 가능성이 높다. 이 경우 “add Go to PATH + 운영체제명”으로 검색하면 해결 방법을 찾을 수 있다.
대부분은 별 문제 없이 지나간다.
첫 번째 Go 프로그램
package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}
구조를 하나씩 보자.
- package main → 실행 가능한 program임을 의미
- func main() → entry point
- fmt.Println → console 출력
실행:
go run demo.go
또는 executable 생성:
go build demo.go
compiled language의 장점은 여기서 드러난다.
생성된 executable 파일은 Go가 설치되지 않은 PC에서도 실행 가능하다.
이게 생각보다 큰 차이를 만든다.
Binary Fundamentals (왜 bit를 알아야 할까?)
컴퓨터는 0과 1만 이해한다.
이걸 binary라고 한다.
각 자리는 2의 거듭제곱을 의미한다.
예를 들어:
10010 (binary) → 18 (decimal)
이걸 왜 알아야 할까?
Go의 type system은 bit 수에 따라 표현 범위가 달라지기 때문이다.
- 8 bits = 1 byte
- 8 bits → 256개 값 표현 가능
Unsigned 8-bit:
0 ~ 255
Signed 8-bit:
-128 ~ 127
bit 수가 늘어나면 표현 가능한 범위도 커진다.
이 개념을 이해하면 int8, int16, int32가 왜 존재하는지 자연스럽게 이해된다.
Go의 기본 Data Type
Integer 계열
- int8, int16, int32, int64
- uint (unsigned)
Unsigned는 음수를 허용하지 않는다.
Float
- float32
- float64 (일반적으로 사용)
기타
- bool
- string
- byte (int8 alias)
- rune (int32 alias)
- nil
변수 선언 방식
명시적 선언
var x int = 10
암시적 선언 (가장 많이 사용)
x := 10
Go가 type을 자동 추론한다.
단, 값을 아직 정하지 않을 경우에는 명시적 선언을 사용한다.
var number int
Type Casting
Go는 자동 형 변환을 거의 허용하지 않는다.
float64(x)
int(y)
주의해야 할 점은 overflow다.
큰 type을 작은 type으로 바꾸면 값이 깨질 수 있다.
경고 없이 잘못된 값이 나올 수 있다.
조심해야 한다. 진짜로.
Console Output과 Formatting
- fmt.Println → 줄바꿈 포함 출력
- fmt.Printf → formatting 지원
- fmt.Sprintf → 문자열 생성
자주 쓰는 format specifier:
- %d → integer
- %f → float
- %.2f → 소수점 2자리
- %T → type
- %v → value
연산자와 math package
기본 연산자는 JavaScript와 거의 동일하다.
-
-
-
- /
-
-
- %
- ++ --
Exponent는 operator가 없다.
math.Pow(x, y)
이렇게 사용한다.
조건문과 반복문
if
괄호 없이 사용 가능.
if x > 5 {
}
switch
- 자동 break
- fallthrough 지원
- naked switch 가능
반복문
Go에는 while이 없다.
모든 반복은 for로 처리한다.
Array vs Slice
Array
고정 길이.
길이가 type의 일부다.
[3]int
크기 변경 불가.
Slice
동적 구조.
[]int
append 가능.
Slice는 내부적으로 다음을 가진다.
- pointer
- length
- capacity
capacity를 초과하면 Go는 새로운 underlying array를 만들고, 크기를 두 배로 늘린다.
이 동작을 이해하면 성능 최적화도 가능하다.
Map (Key-Value 구조)
map[string]int
값 추가:
mp["a"] = 1
삭제:
delete(mp, "a")
존재 여부 확인:
value, ok := mp["a"]
Function의 다양한 형태
Go의 function은 꽤 유연하다.
- multiple return
- anonymous function
- function as parameter
- function returning function
- variadic parameter (...)
- named return value
예시:
func add(x int, y int) int {
return x + y
}
Struct (Go의 Class 대체 개념)
type Person struct {
Name string
Age int
}
필드 접근:
p.Name
Method 정의:
func (p Person) GetName() string {
return p.Name
}
Interface (추상화의 핵심)
type Shape interface {
GetPerimeter() int
}
struct가 해당 method를 구현하면 자동으로 interface를 만족한다.
“implements” 같은 키워드가 없다.
암묵적 구현.
이게 Go의 매력 중 하나다.
Error Handling
panic
runtime crash 발생
defer
함수 종료 시 실행
recover
panic 복구
권장 방식
error를 return 값으로 처리한다.
result, err := divide(10, 0)
Go는 명시적 error handling을 선호한다.
Generics
func Add[T int | float64](x, y T) T
T는 generic type parameter.
재사용 가능한 code 작성 가능.
function, struct, custom type 모두 generic 적용 가능.
Pointer와 Reference
주소 얻기:
&x
역참조:
*x
Pointer를 사용하면 function 내부에서 원본 값을 수정할 수 있다.
struct와 함께 자주 사용된다.
Concurrency 개념 이해
CPU는 여러 core를 가진다.
각 core는 thread를 실행한다.
Parallel은 동시에 실행.
Concurrency는 번갈아 가며 실행.
Go는 goroutine이라는 lightweight thread를 제공한다.
Goroutine
go myFunction()
새로운 goroutine 생성.
동시에 실행된다.
Channel
ch := make(chan int)
값 전달:
ch <- 10
값 수신:
x := <- ch
send와 receive는 blocking operation이다.
Buffered channel은 제한된 수만큼 값 저장 가능.
Select
여러 channel을 동시에 대기.
select {
case x := <-ch1:
case y := <-ch2:
}
먼저 도착한 channel 처리.
Mutex
여러 goroutine이 동일 자원에 접근할 때 race condition 발생 가능.
sync.Mutex
- Lock()
- Unlock()
공유 자원 보호.
WaitGroup
sync.WaitGroup
- Add()
- Done()
- Wait()
여러 goroutine 종료 대기.
왜 2026년에 Go를 배워야 할까?
화려하지 않다.
대신 견고하다.
Kubernetes?
Go.
Docker?
Go.
Terraform?
Go.
Cloud ecosystem의 중심에 있다.
대규모 backend system을 만들고 싶다면,
Go는 여전히 강력한 선택이다.
FAQ (2026 기준)
1. Go는 초보자에게 적합한가?
문법은 단순하다. concurrency는 연습이 필요하다.
2. Go는 Python보다 빠른가?
compiled language이므로 일반적으로 빠르다.
3. Go는 OOP를 지원하는가?
struct와 interface 기반으로 부분 지원한다.
4. Web 개발에 적합한가?
backend API 개발에 매우 적합하다.
5. 2026년에 Go를 배워야 하는가?
backend, cloud, DevOps를 목표로 한다면 추천한다.
6. Go는 Java보다 나은가?
프로젝트 목적에 따라 다르다. Go는 단순함이 강점이다.
7. Multithreading을 지원하는가?
Yes, goroutine으로 가능하다.
8. Goroutine은 실제 thread인가?
Go runtime이 관리하는 lightweight thread다.
9. Deadlock이란?
goroutine들이 서로를 기다리며 멈춘 상태.
10. Go는 어렵나?
기초는 쉽다. concurrency는 깊다.
마무리
Go는 화려한 언어는 아니다.
대신 묵직하다.
Hello World로 시작해서,
분산 시스템까지 확장된다.
그리고 이 한 문장이 모든 걸 설명한다.
“Go는 복잡함을 줄여 사고를 맑게 만든다.”
여기까지 읽었다면,
이제 문법을 아는 수준을 넘어
언어의 철학을 이해한 것이다.
그건 꽤 큰 차이다.
'일상 > IT' 카테고리의 다른 글
| Redis란 무엇인가? 구조, 동작 원리, Persistence 전략까지 한 번에 정리 (0) | 2026.03.14 |
|---|---|
| 2026년 게임 핵 사용 현실: Kernel-Level Anti-Cheat와 Hardware Ban 때문에 정말 어려워졌을까? (0) | 2026.03.10 |
| Postgres에서 Elasticsearch 없이 고급 검색 구현하는 방법: BM25 기반 PG Text Search 완전 정리 (0) | 2026.02.18 |
| .NET이란 무엇인가? 2025년 기준으로 쉽게 정리한 최신 .NET 입문 가이드 (0) | 2026.02.12 |
| Interview Coder 논란 정리: 익명성을 판다는 서비스가 사용자 신원을 공개해버린 순간 (0) | 2026.02.05 |