Go에서의 덕타이핑

Damon Kwon·2022년 1월 24일
0

Go를 아시나요

목록 보기
3/3
post-thumbnail

어느 날 센세와 카톡을 하다가 이런 이야기를 들었다.

👨‍🏫 대충 어느 유명한 사람의 말

... 저는 프로그래머의 실력은 문법, 알고리즘, 설계 라고 보고 문법은 그중 가장 비중이 낮습니다. 다만 제가 보는건 자신이 하는 언어의 특징을 얼마큼 파악하고 있는가를 봅니다. 예를 들면 자바라면 jit나 GC 옵션을, 어트리뷰트등을 물어볼거 같고, go라면 고루틴 구조, GC구조, 프로파일링, 덕타이핑 등을 물어볼거 같습니다. 중요한건 어떤 언어를 하느냐가 아니라 자신이 쓰는 언어를 얼마큼 하느냐가 중요하다고 저는 생각합니다. 한가지를 깊게 아는 사람은 다른 것도 빨리 배우기 때문입니다.

이렇게 쓴소리 좋은소리 해주시는 분이 계신다는게 얼마나 행복한지 모른다.
학교 다닐 땐 이런 말을 해주는 사람이 주변에 없었다.
물론 내가 농땡이 펴서 못찾았던 걸수도 ㅋㅋ

대학교 때 생각해보니까... 맨날 쉘코드 만들거나 리버싱하면서 변태같은 어셈블리 코드를 보던 나날들이 새록새록 떠오른다.

이렇게 재밌는 개발 놔두고 왜 다른걸 했을까?
거두절미하고 덕 타이핑이 뭔지 알아보자.

🦆 DuckTyping

오리처럼 걷고.. 오리처럼 꽥꽥거리면.. 금마는 오리 맞다!

덕타이핑 하면 가장 많이 나오는 표현인데, 갑자기 오리의 특성을 설명해놓고 이게 덕타이핑이라고 하니 어이가 없었다. 처음 저 문장을 보았을 때, 귀납추리를 통한 삼단 논법(오류를 듬뿍 첨가한)을 보는 기분이었다.

  1. 오리는 꽥꽥거린다.
  2. 오리는 뒤뚱거린다.
  3. 그러므로 저~기 꽥꽥거리고 뒤뚱거리는 물체는 오리다.
`야 사람이 뒤뚱거리고 꽥꽥거려도 오리냐? 오리냐고~!@`

근데, 글을 끝까지 보고 나면 저 문장이 선녀처럼 보일 것이므로 잡설은 그만 늘어놓고 바로 설명 들어간다.

❓ Static Language, Dynamic Language

우리가 프로그래밍을 하다보면 변수나 함수의 반환값에 미리 타입을 지정해놓는 경우가 있고, 타입을 지정하지 않고 사용하는 경우가 있다.

이처럼 변수 또는 함수의 Type을 미리 지정하는 것을 Static Language라 하고, 변수 또는 함수의 Type을 지정하지 않고 사용할 수 있는 경우를 Dynamic Language라고 한다.

예를 들면, C99는 컴파일하기 전에 미리 데이터 타입을 지정해줘야 컴파일 에러가 안난다. 그런데 Python이나 JS는 타입을 지정하지 않아도 런타임에서 타입을 지정해준다. 즉, Dynamic과 Static의 가장 큰 차이점은 "Type 정보를 지정해야 되냐? 아니냐?" 로 볼 수 있다.

Type에 초점을 두고 두 코드를 비교해보자.

데이터 타입을 지정하는 경우 (Static)

a = 1
b = "1"
c = a + int(b)		// 2
d = b + string(a)	// "11"

데이터 타입을 지정하지 않는 경우 (Dynamic)

a = 1
b = "1"
c = a + b		// 2
d = b + a	 	// "11"

이처럼 동적 언어는 코드를 작성함에 있어서 간결하다는 점이 장점이다. 그러나 동적 언어는 컴파일이 과정이 없어서 간단한 문법 오류조차 런타임 에러로 발생하게 된다. (오히려 불편해졌어..)

정적 언어와 동적 언어는 서로 장단점이 존재한다. 동적 언어의 개발 속도와 편리성, 컴파일 기반의 정적 언어의 안정성을 모두 가질 순 없나? 이제 Go가 나설 차례다.

❓ Go는 Static임? Dynamic임?

나는 둘 다 되는데~~

Go는 컴파일 기반 정적 Type 언어이다. 하지만 동적 언어의 특성이 존재하므로, 동적 언어 스타일의 코딩을 할 수 있다. 안정성과 편리함을 둘 다 챙긴 셈... 이를 가능하게 해주는 것이 바로 덕타이핑 방식으로 작동하는 Go의 Interface 이다. (엄밀히 말하면 Go의 덕타이핑은 Runtime에서 돌아가는게 아니라 Compile time에서 실행되므로 structural typing 이라고 부른다)

Go에서 인터페이스는 객체의 동작을 표현하고, 인터페이스에 정의된 동작(메소드)을 가진 객체는 인터페이스를 사용할 수 있다. 코드로 보는게 빠르다.

💻 코드 구현

Duck 인터페이스

type Duck interface{
	Quack()	string
	Walk()	string
}

Chicken 구조체

type Chicken struct{
}
func (c Chicken) Quack() string{
	return "꼬꼬~"
}
func (c Chicken) Walk() string{
	return "닭이 걷는 모습"
}

Pigeon 구조체

type Pigeon struct{
}
func (p Pigeon) Quack() string{
	return "구구구구~"
}
func (p Pigeon) Walk() string{
	return "비둘기가 걷는 모습"
}

인터페이스 활용

func main() {
	ducks := []Duck{
		Chicken{},
		Pigeon{},
		Human{}, // 컴파일에러
	}
	for _, duck := range ducks{
		fmt.Println(duck.Quack(), duck.Walk())
	}
}

컴파일 에러가 나는 이유 : Human은 Quack() 메소드가 없으므로 Duck 인터페이스에 속할 수 없다.

🙄결론

오리처럼 걷고.. 오리처럼 꽥꽥거리면.. 금마는 오리 맞다!

  • 덕타이핑을 알아버렸다.
  • 동적 언어와 정적 언어를 알아버렸다.
  • Go는 인터페이스에 덕타이핑 개념이 들어가있다.
  • 다들 안전 코딩 하세요~




참고자료

profile
👽 DevMyong, 신입 백엔드 개발자 🌊 myong.dev@gmail.com

0개의 댓글