
Go를 처음 배우는 개발자들이 자주 하는 질문 중 하나는 바로 "왜 Go에는 삼항연산자(?:)가 없을까?"입니다. C, Java, JavaScript 등 대부분의 언어에 익숙한 사람이라면 이 부재가 다소 불편하게 느껴질 수 있습니다. 하지만 이는 Go 언어의 핵심 설계 철학 — 단순함(Simplicity), 명확성(Clarity), 가독성(Readability) — 을 지키기 위한 의도적인 결정입니다.
목차
- 삼항연산자란 무엇인가?
- Go 언어 설계자들의 공식 입장
- Go의 언어 설계 철학: Less is More
- 삼항연산자가 없는 실질적 이유들
- Go에서의 조건부 표현 대안
- 다른 언어와의 비교 분석
- 커뮤니티 반응과 논쟁
- 결론: 제약이 주는 자유
삼항연산자란 무엇인가?
정의와 기본 문법
삼항연산자(Ternary Operator)는 condition ? value_if_true : value_if_false 형태의 조건부 표현식으로, 간단한 if-else 문을 한 줄로 축약할 수 있는 연산자입니다.
다른 언어에서의 사용 예시
// C/C++
int max = (a > b) ? a : b;
char grade = (score >= 60) ? 'P' : 'F';
// JavaScript
const status = isLoggedIn ? 'Welcome' : 'Please login';
const discount = isPremium ? 0.2 : 0.1;
// Java
String message = (age >= 18) ? "Adult" : "Minor";
int fee = student ? 100 : 200;
Go에서 같은 로직 구현
// Go - if-else 문 사용
var max int
if a > b {
max = a
} else {
max = b
}
var grade rune
if score >= 60 {
grade = 'P'
} else {
grade = 'F'
}
Go 언어 설계자들의 공식 입장
Rob Pike의 설명
Go 언어의 창시자 중 한 명인 Rob Pike는 Go FAQ에서 다음과 같이 설명합니다:
"The reason
?:is absent from Go is that the language's designers had seen the operation used too often to create impenetrable code."
Go 설계자들은 삼항연산자가 불필요하게 복잡한 코드를 양산하는 경향이 있다고 판단했습니다. 즉, 코드의 간결함을 위해 도입한 문법이 오히려 가독성을 해치는 역효과를 낳는다고 본 것입니다.
Go FAQ 공식 문서
Go 공식 FAQ에서는 다음과 같이 명시하고 있습니다:
Go's syntax was designed to be clean and easy to parse, both by
machines and by humans. Ternary operators and their ilk make
code more compact but not necessarily more readable.
핵심 메시지:
- 기계와 인간 모두에게 파싱하기 쉬운 구문 설계
- 삼항연산자는 코드를 압축적으로 만들지만 가독성을 반드시 향상시키지는 않음
Go의 언어 설계 철학: Less is More
1. 단순함 우선 (Simplicity First)
Go는 복잡함보다 단순함을 추구합니다. 이는 다음과 같은 설계 원칙으로 드러납니다:
| 설계 원칙 | 핵심 개념 | 예시 |
|---|---|---|
| 최소주의(Minimalism) | 꼭 필요하지 않다면 과감히 제외 | 삼항연산자, while 루프, (초기) 제네릭 |
| 명확성(Explicitness) | 코드의 의도가 누구에게나 명확해야 함 | 명시적 타입 변환, 명확한 에러 처리 |
| 일관성(Consistency) | 동일한 목적의 문법은 하나만 존재 | if-else, for 루프만 사용 |
2. 인지 부하 감소
// 복잡한 중첩 삼항연산자 (다른 언어)
result = (a > b) ?
((a > c) ? a : c) :
((b > c) ? b : c);
// Go에서의 명확한 표현
var result int
if a > b {
if a > c {
result = a
} else {
result = c
}
} else {
if b > c {
result = b
} else {
result = c
}
}
// 또는 함수로 분리
func max3(a, b, c int) int {
if a > b && a > c {
return a
}
if b > c {
return b
}
return c
}
3. 팀 개발과 코드 리뷰
Go는 구글의 대규모 팀 개발 환경에서 탄생했습니다:
- 신규 팀원 온보딩: 문법이 단순하여 학습 곡선이 완만
- 코드 리뷰 효율성: 이해하기 쉬운 코드로 리뷰 시간 단축
- 유지보수성: 6개월 후에도 이해하기 쉬운 코드
삼항연산자가 없는 실질적 이유들
1. 가독성 저하 사례
중첩 삼항연산자의 문제점
// JavaScript - 읽기 어려운 중첩 삼항연산자
const fee = isPremium
? (isStudent ? 50 : 100)
: (isStudent ? 75 : 150);
const grade = score >= 90
? 'A'
: score >= 80
? 'B'
: score >= 70
? 'C'
: score >= 60
? 'D'
: 'F';
// Go - 명확한 의도 표현
var fee int
if isPremium {
if isStudent {
fee = 50
} else {
fee = 100
}
} else {
if isStudent {
fee = 75
} else {
fee = 150
}
}
정리하자면, 삼항연산자는 간결함을 얻는 대신 가독성과 유지보수성을 희생하게 됩니다.
2. 파싱의 복잡성
// C - 예상과 다른 결과
int result = 1 ? 2 : 3 ? 4 : 5;
// (1 ? 2 : 3) ? 4 : 5 가 아니라,
// 실제로는 1 ? 2 : (3 ? 4 : 5) 로 파싱됨
3. 디버깅의 어려움
// JavaScript - 중단점 설정 어려움
const result = condition1 ? func1() : condition2 ? func2() : func3();
// Go - 각 분기에 중단점 설정 가능
var result int
if condition1 {
result = func1()
} else if condition2 {
result = func2()
} else {
result = func3()
}
Go에서의 조건부 표현 대안
1. 표준 if-else 문
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
func getStatus(isActive bool) string {
if isActive {
return "active"
}
return "inactive"
}
2. 제네릭을 활용한 조건부 함수 (Go 1.18+)
// 간단한 조건부 선택 함수
func Ternary[T any](cond bool, a, b T) T {
if cond {
return a
}
return b
}
// 사용 예
max := Ternary(a > b, a, b)
status := Ternary(isLoggedIn, "Welcome", "Please login")
3. 맵(Map)을 이용한 조건부 로직
// 상태에 따른 메시지 매핑
statusMessages := map[bool]string{
true: "Success",
false: "Failure",
}
message := statusMessages[isSuccess]
// 더 복잡한 조건부 매핑
func getDiscount(customerType string) float64 {
discounts := map[string]float64{
"premium": 0.20,
"regular": 0.10,
"student": 0.15,
"senior": 0.25,
}
if discount, ok := discounts[customerType]; ok {
return discount
}
return 0.0
}
4. 인터페이스 기반 전략 패턴
type PricingStrategy interface {
Calculate(base float64) float64
}
type PremiumPricing struct{}
func (p PremiumPricing) Calculate(base float64) float64 {
return base * 0.8
}
type RegularPricing struct{}
func (r RegularPricing) Calculate(base float64) float64 {
return base
}
func getPricingStrategy(isPremium bool) PricingStrategy {
if isPremium {
return PremiumPricing{}
}
return RegularPricing{}
}
다른 언어와의 비교 분석
언어별 조건부 표현 지원 현황
| 언어 | 삼항연산자 지원 | 대안 구문 | 설계 철학 |
|---|---|---|---|
| C/C++ | ✅ ?: |
if-else | 성능과 표현력 |
| Java | ✅ ?: |
if-else | 객체지향 + 표현력 |
| JavaScript | ✅ ?: |
if-else, &&, || |
유연성 |
| Python | ✅ x if cond else y |
if-else | 가독성 |
| Rust | ✅ if 표현식 | match, if-else expr | 안전성 + 표현력 |
| Go | ❌ | if-else, 함수 | 단순함 + 가독성 |
Python의 접근법
# Python - 읽기 쉬운 조건부 표현
result = value_if_true if condition else value_if_false
grade = "Pass" if score >= 60 else "Fail"
Rust의 접근법
// Rust - if는 표현식
let max = if a > b { a } else { b };
let status = if is_active { "active" } else { "inactive" };
// match 표현식으로 복잡한 조건 처리
let grade = match score {
90..=100 => 'A',
80..=89 => 'B',
70..=79 => 'C',
60..=69 => 'D',
_ => 'F',
};
커뮤니티 반응과 논쟁
찬성 의견 (Go 설계 지지)
// 명확하고 이해하기 쉬운 코드
func getPrice(isPremium bool, basePrice float64) float64 {
if isPremium {
return basePrice * 0.8
}
return basePrice
}
주요 논점:
- 신규 팀원이 빠르게 코드를 이해할 수 있음
- 코드 리뷰 시 논쟁이 줄어듦
- 유지보수 비용 절감
반대 의견 (삼항연산자 필요론)
// JavaScript - 간결함의 장점
const max = (a > b) ? a : b;
const status = isActive ? "ON" : "OFF";
주요 논점:
- 표현식 중심 언어에서는 유용함
- 간단한 조건은 한 줄로 표현 가능
실제 GitHub 이슈와 토론
Go의 핵심 팀은 Issue #20774에서 다음과 같이 정리했습니다:
"삼항연산자를 추가하는 것은 언어를 불필요하게 복잡하게 만들 뿐, 실질적인 이득을 제공하지 않는다." — Go core team
결론: 제약이 주는 자유
삼항연산자가 없는 것은 Go의 결함이 아니라 강점입니다. 이는 "적은 것이 곧 많은 것(Less is More)"이라는 철학의 실천이며, 장기적으로는 더 단순하고, 더 읽기 쉽고, 더 유지보수 가능한 코드베이스를 만들어 줍니다.
Go의 설계 철학이 주는 이익
1. 인지 부하 감소
- 문법을 배우는 시간 단축
- 코드 이해를 위한 정신적 노력 감소
- 팀 내 코딩 스타일 통일
2. 유지보수성 향상
- 6개월 후에도 이해하기 쉬운 코드
- 버그 발생 가능성 감소
- 리팩토링의 용이성
3. 개발 속도 향상
- 문법 논쟁 시간 감소
- 코드 리뷰 시간 단축
- 빠른 온보딩
최종 권고사항
Go를 사용할 때:
- if-else의 명확함을 받아들이세요
- 복잡한 로직은 함수로 분리하세요
- 가독성을 간결함보다 우선시하세요
- 팀의 코드 일관성을 유지하세요
Go에 삼항연산자가 없는 것은 결함이 아닌 특징입니다. 이는 "적은 것이 많은 것(Less is More)"이라는 Go의 핵심 철학을 보여주는 대표적인 사례이며, 장기적으로는 더 유지보수 가능하고 이해하기 쉬운 코드베이스를 만들어줍니다.
참고 자료:
'Golang' 카테고리의 다른 글
| [Golang] Go의 Goroutine과 Channel: 공유하지 말고 소통하라 (0) | 2025.11.10 |
|---|---|
| [Golang] Go의 defer, panic, recover: 예외 없는 오류 제어 메커니즘 (0) | 2025.11.09 |