
왜 지금 Go 자료형을 완벽히 이해해야 할까요?
분명히 머릿속으로는 완벽한 로직을 짰다고 생각했는데, 막상 코드를 실행하면 컴파일 에러가 화면을 가득 채운 경험이 있으신가요? 특히 Go 언어를 처음 접하면 “왜 숫자를 더하는데 에러가 나지?” 혹은 “문자열이랑 이 문자는 왜 다른 거지?” 같은 의문이 끊임없이 생기곤 해요.
이런 문제는 단순히 문법을 몰라서 발생하는 것이 아니라, Go가 가진 엄격한 타입 시스템을 충분히 이해하지 못했기 때문이에요. Go는 다른 언어에 비해 타입에 대해 매우 보수적이고 깐깐한 편이에요. 하지만 이 깐깐함이야말로 대규모 시스템에서 버그를 미리 잡아내고 성능을 극대화하는 Go만의 강력한 무기랍니다.
오늘 이 Go 자료형 치트시트를 통해 여러분은 더 이상 컴파일러와 싸우지 않고, 오히려 컴파일러를 활용해 안정적인 코드를 짜는 법을 배우게 될 거예요. 자료형의 경계를 명확히 이해하면 메모리 효율성까지 챙길 수 있는 수준 높은 개발자로 성장할 수 있어요.
- 정수, 실수, 문자열 등 필수 기본 자료형의 특징
- 메모리 효율을 높이는 자료형 선택 기준
- 실전에서 바로 쓰는 데이터 타입 활용 스니펫
- 초보자가 가장 자주 저지르는 타입 관련 실수와 해결책
Go 자료형 학습을 위한 사전 준비와 선택 기준
Go 언어는 정적 타입(Static Typing) 언어예요. 이는 프로그램이 실행되기 전, 컴파일 단계에서 모든 변수의 타입이 결정되어야 한다는 뜻이에요. 파이썬처럼 변수에 아무 값이나 넣었다 뺐다 할 수 있는 유연함은 부족할지 몰라도, 그만큼 실행 속도가 빠르고 예상치 못한 타입 오류를 방지할 수 있어요.
자료형을 배우기 전에 반드시 기억해야 할 개념이 있어요. 바로 제로 값(Zero Value)이에요. Go에서는 변수를 선언하고 값을 할당하지 않아도 쓰레기 값이 들어가지 않아요. 대신 각 타입에 정해진 기본값이 자동으로 들어갑니다. 이 개념을 모르면 초기화되지 않은 변수를 다룰 때 논리적 오류를 범하기 쉬워요.
또한, 어떤 자료형을 선택하느냐는 단순히 ‘데이터를 담는다’는 의미를 넘어 메모리 설계의 문제와 직결돼요. 아래 표를 통해 상황에 맞는 자료형을 어떻게 골라야 하는지 비교해 보세요.
| 선택 기준 | 권장 자료형 | 사용 사례 |
|---|---|---|
| 정밀한 소수점 계산 | float64 | 과학적 계산, 일반적인 실수 처리 |
| 대규모 정수 배열 | int8 / uint8 | 메모리 절약이 중요한 센서 데이터 등 |
| 텍스트 데이터 처리 | string | 이름, 메시지, 설명글 등 일반 텍스트 |
| 참/거짓 상태 표시 | bool | 조건문 분기, 활성화 여부 확인 |
무조건 가장 큰 자료형(예: int64)을 쓰는 것이 정답은 아니에요. 처리해야 할 데이터의 범위와 사용 가능한 메모리 용량을 고려해서 가장 적절한 크기를 선택하는 연습이 필요합니다. 이것이 바로 Golang 전문가로 가는 첫걸음이에요.
실전에서 바로 쓰는 Go 자료형 핵심 가이드
이제 본격적으로 Go의 자료형들을 하나씩 파헤쳐 볼게요. 단순히 종류를 외우는 것이 아니라, 각 타입이 실제 코드에서 어떤 모습으로 구현되고 활용되는지 살펴보는 것이 중요해요.
STEP 1. 숫자 데이터를 다루는 정수와 실수형
Go에서 숫자는 크게 정수(Integer)와 실수(Floating-point)로 나뉩니다. 정수형은 다시 부호가 있는 타입(int)과 없는 타입(uint)으로 구분돼요. 여기서 주의할 점은 범위(Range)입니다. 예를 들어 `int8`은 -128부터 127까지만 담을 수 있어요. 이 범위를 넘어서는 값을 넣으려고 하면 오버플로우(Overflow)가 발생해 엉뚱한 값이 저장될 수 있으니 조심해야 해요.
실수형의 경우, Go는 대부분 `float64`를 사용하도록 권장합니다. `float32`보다 훨씬 정밀한 계산이 가능하기 때문이죠. 금융권 애플리케ks와 같이 아주 미세한 오차도 허용되지 않는 환경에서는 별도의 고정 소수점 라이브러리를 쓰기도 하지만, 일반적인 개발에서는 `float64`만 잘 써도 충분히 훌륭한 코드를 짤 수 있어요.
`int` 타입은 플랫폼에 따라 크기가 달라져요. 64비트 컴퓨터에서는 64비트, 32비트 컴퓨터에서는 32비트 크기로 동작합니다. 특정 크기를 보장해야 한다면 `int32`나 `int64`를 명시적으로 사용하는 것이 안전해요.
STEP 2. 텍스트의 마법, 문자열과 룬(Rune)
Go에서 문자열은 `string` 타입을 사용하며, 기본적으로 UTF-8 인코딩을 따릅니다. 여기서 입문자들이 가장 많이 헷갈리는 개념이 바로 룬(Rune)이에요. 문자열은 사실 바이트(byte)들의 나열일 뿐이라서, 한글처럼 한 글자가 여러 바이트를 차지하는 경우 단순 인덱스로 접근하면 글자가 깨질 수 있어요.
이때 필요한 것이 바로 `rune` 타입입니다. 룬은 하나의 유니코드 코드 포인트를 나타내는 32비트 정수형이에요. 한글 한 글자를 온전히 하나의 단위로 다루고 싶다면 반드시 문자열을 `rune` 슬라이스로 변환해서 작업해야 합니다. 이 차이를 아는 것만으로도 문자열 처리 실력을 한 단계 높일 수 있어요.
STEP 3. 논리적 판단을 위한 불리언과 제로 값
조건문에서 핵심 역할을 하는 `bool` 타입은 `true`와 `false` 두 가지 값만 가집니다. 아주 단순해 보이지만, Go에서는 타입 변환에 매우 엄격해서 `0`이나 `1`을 `true`나 `false`로 자동으로 바꿔주지 않아요. 반드시 명시적으로 변환하거나 논리 연산자를 사용해야 합니다.
또한, 앞서 언급한 제로 값을 다시 한번 확인해 보세요. `int`는 `0`, `float64`는 `0.0`, `bool`은 `false`, `string`은 `””`(빈 문자열), 그리고 포인터나 슬라이스 같은 참조 타입은 `nil`이 기본값입니다. 이 기본값들을 정확히 숙지해야 초기화되지 않은 변수를 사용할 때 발생하는 런타임 에러를 막을 수 있어요.
STEP 4. 데이터의 묶음, 슬라이스와 맵(Map)
단일 변수만으로는 복잡한 데이터를 관리하기 어렵죠. 이때 사용하는 것이 컬렉션 타입입니다. Go의 꽃이라고 할 수 있는 슬라이스(Slice)는 배열과 비슷하지만 크기가 동적으로 변할 수 있어 훨씬 강력해요. 내부적으로는 배열을 가리키는 포인터, 길이(length), 용량(capacity)으로 구성되어 있어 매우 효율적으로 동작합니다.
데이터를 ‘키-값(Key-Value)’ 형태로 저장하고 싶다면 `map`을 사용하세요. 예를 들어 사용자의 ID를 키로 하고 이름을 값으로 저장하는 식이죠. 다만, 맵은 생성할 때 반드시 `make` 함수를 사용해 메모리를 할당해야 해요. 할당하지 않은 맵에 값을 넣으려고 하면 프로그램이 즉시 종료(panic)될 수 있으니 꼭 주의하세요!
STEP 5. 타입 변환(Type Conversion) 실전 스니펫
Go는 타입이 다르면 산술 연산조차 허용하지 않는 아주 깐깐한 친구예요. 아래 코드를 통해 어떻게 안전하게 타입을 변환하는지 살펴보세요.
var integerVal int = 42 var floatVal float64 = 3.14 // 에러 발생: integerVal + floatVal // 해결: 타입을 하나로 통일해야 해요 result := float64(integerVal) + floatVal fmt.Println(result) // 45.14
이처럼 명시적 형변환을 생활화하는 습관을 들이면, 컴파일러가 주는 에러 메시지를 훨씬 더 유연하게 받아들일 수 있게 됩니다.
자주 하는 실수와 해결법
Go를 배우면서 누구나 한 번쯤은 겪게 되는 당혹스러운 상황들을 모아봤어요. 에러 메시지를 보기 전에 이 리스트를 먼저 체크해 보세요.
- ❌ 실수: `int` 변수와 `int64` 변수를 서로 더하려고 함
➡️ 왜 발생하는가: Go는 타입이 다르면 값의 크기가 같더라도 서로 다른 타입으로 간주해요.
✅ 해결법: `int64(variable)`를 사용하여 타입을 명시적으로 맞춰주세요. - ❌ 실수: 선언만 하고 초기화하지 않은 `map`에 값을 추가함
➡️ 왜 발생하는가: 맵은 `nil` 상태일 때 메모리 공간이 없어 값을 저장할 수 없어요.
✅ 해결법: 반드시 `m := make(map[string]int)`처럼 `make`로 초기화하세요. - ❌ 실수: 한글이 포함된 문자열의 인덱스로 글자 추출 시도
➡️ 왜 발생하는가: 문자열 인덱스는 글자 단위가 아닌 바이트 단위이기 때문이에요.
✅ 해결법: 문자열을 `[]rune`으로 변환한 뒤 인덱스에 접근하세요. - ❌ 실수: 매우 큰 숫자를 `int8`에 담으려고 시도함
➡️ 왜 발생하는가: `int8`의 표현 범위를 초과하여 오버플로우가 발생해요.
✅ 해결법: 데이터의 예상 범위를 미리 파악하고 `int32`나 `int64`를 선택하세요. - ❌ 실수: `float` 연산 결과가 정확히 일치할 것이라고 가정함
➡️ 왜 발생하는가: 부동 소수점은 미세한 정밀도 오차가 발생할 수 있어요.
✅ 해결법: 두 실수를 비교할 때는 `==` 대신 차이값이 아주 작은 값보다 작은지 확인하세요.
자주 묻는 질문
Q. int와 int32, int64의 차이는 정확히 무엇인가요?
int는 실행 환경(32비트 또는 64비트 시스템)에 따라 크기가 결정되는 유동적인 타입이에요. 반면 int32나 int64는 어떤 환경에서도 크기가 고정되어 있어요. 시스템 간 데이터 교환이 중요하다면 고정 크기 타입을 쓰는 것이 더 안전해요.
Q. Go에서 문자열을 숫자로 바꾸려면 어떻게 하나요?
표준 라이브러리인 `strconv` 패키지를 사용하면 돼요. 예를 들어 `strconv.Atoi(“123”)`을 사용하면 문자열을 정수형으로 쉽게 변환할 수 있습니다.
Q. 슬라이스와 배열은 어떤 점이 다른가요?
배열은 생성할 때 정해진 크기를 절대 바꿀 수 없는 고정형 데이터 구조예요. 반면 슬라이스는 내부적으로 배열을 참조하면서 크기를 자유롭게 늘리거나 줄일 수 있는 유연한 구조입니다. 대부분의 경우 슬라이스를 사용하는 것이 훨씬 편리해요.
Q. 제로 값(Zero Value)이 왜 중요한가요?
Go는 안전성을 위해 변수를 선언하면 자동으로 기본값을 할당해요. 개발자가 실수로 초기화하지 않은 변수를 사용할 때, 예측 불가능한 쓰레기 값 대신 정해진 기본값이 들어있음으로써 프로그램의 안정성을 높여주기 때문이에요.
Q. rune 타입은 꼭 써야 하나요?
영어만 다루는 프로그램이라면 필요 없을 수도 있어요. 하지만 전 세계 사용자를 대상으로 하는 서비스라면 한글, 한자, 이모지 등을 정확하게 처리하기 위해 `rune` 사용은 선택이 아닌 필수입니다.
핵심 요약과 다음 단계로 나아가기
오늘 배운 내용을 바탕으로 Go 자료형의 핵심을 다시 한번 정리해 볼게요. 이 내용만 머릿속에 넣어두어도 기본적인 타입 에러는 거의 다 방지할 수 있어요.
- 정수와 실수는 범위와 정밀도를 고려해 적절한 크기를 선택하세요.
- 문자열 내 한글/유니코드를 다룰 때는 반드시
rune타입을 활용하세요. - 모든 변수는 선언 시 자동으로 제로 값(Zero Value)을 가집니다.
- 타입이 다른 변수 간의 연산은 반드시 명시적 형변환이 필요해요.
- 맵(Map)과 슬라이스(Slice)는 사용 전 반드시 초기화(make)를 확인하세요.
이제 이론은 충분히 익히셨어요. 이제 직접 손을 움직여 코드를 짜볼 차례입니다!
🚀 오늘 바로 할 일: Go Playground에서 정수와 실수형을 섞어 더하는 코드를 작성하고, 의도적으로 에러를 발생시켜 보세요.
📅 이번 주 할 일: 다양한 크기의 정수형(int8~int64)을 사용해 보며 오버플로우가 발생하는 지점을 직접 찾아보세요.
🛠 실행 직전 할 일: 문자열을 []rune으로 변환해 한글 한 글자씩 출력하는 작은 프로그램을 만들어 보세요.
오늘 내용 중 이해가 가지 않거나 궁금한 점이 있다면 언제든 댓글로 남겨 주세요. 함께 고민하고 답변해 드릴게요! 여러분의 Go 공부를 진심으로 응원합니다.
/programming/golang/go-data-types-complete-guide/ 글과 함께 읽으면 더 깊은 이해가 가능해요.