티스토리 뷰
컴퓨터 프로그래밍 분야에서 덕 타이핑(duck typing)은 동적 타이핑의 한 종류로, 객체의 변수 및 메소드의 집합이 객체의 타입을 결정하는 것을 말한다. 클래스 상속이나 인터페이스 구현으로 타입을 구분하는 대신, 덕 타이핑은 객체가 어떤 타입에 걸맞은 변수와 메소드를 지니면 객체를 해당 타입에 속하는 것으로 간주한다. “덕 타이핑”이라는 용어는 다음과 같이 표현될 수 있는 덕 테스트에서 유래했다. (덕은 영어로 오리를 의미한다.)
만약 어떤 새가 오리처럼 걷고, 헤엄치고, 꽥꽥거리는 소리를 낸다면 나는 그 새를 오리라고 부를 것이다.
일단 바로 코드로 얘기해보죠
interface Animal {
fun shout()
}
class Duck : Animal {
init {}
override fun shout() {
println("I'm a duck");
}
}
class Tiger : Animal {
init {}
override fun shout() {
println("I'm a tiger");
}
}
class Noiser {
fun makeSomeNoise(animal: Animal) {
animal.shout();
}
}
fun main() {
val noiser = Noiser();
noiser.makeSomeNoise(Duck()); // I'm a duck
noiser.makeSomeNoise(Tiger()); // I'm a tiger
}
코틀린으로 작성한 코드입니다
Animal이라는 인터페이스는 shout라는 메소드를 가지고 있습니다
그리고 이 Animal 인터페이스를 구현한 Duck과 Tiger 클래스를 인스턴스화하여
다형성을 테스트할수 있는 Noiser라는 클래스의 makeSomeNoise 메소드의 매개변수로 넣습니다
당연히 Duck과 Tiger의 인스턴스는 Animal을 구현한 클래스로부터 생성되었기 때문에
Animal 매개변수로 전달될수 있습니다
import Foundation
protocol Animal {
func shout()
}
class Duck: Animal {
func shout() {
print("I'm a duck");
}
}
class Tiger: Animal {
func shout() {
print("I'm a tiger");
}
}
class Noiser {
func makeSomeNoise(animal: Animal) {
animal.shout();
}
}
let noiser = Noiser();
noiser.makeSomeNoise(animal: Duck()); // I'm a duck
noiser.makeSomeNoise(animal: Tiger()); // I'm a tiger
Swift로 같은 코드를 짜봅니다
java의 interface와 비슷한 개념의 protocol을 사용하여 Animal을 정의합니다
그리고 마찬가지로 protocol을 상속받은 Duck과 Tiger 클래스를 생성합니다
마찬가지로 다형성을 테스트하기 위해 Animal을 매개변수로 받는 메소드를 가진 클래스를 만들어서 넣어봅니다
물론 잘동작합니다
모두 같은 protocol을 상속받았기 때문이죠
코틀린, swift로 작성한 코드 모두
Animal과 Duck, Tiger 사이에 부모 자식의 관계로 연결이 되어있고
그렇기 때문에 Animal 타입으로도 전달 될 수 있습니다
interface Animal {
shout() : void
}
class Duck {
shout() : void {
console.log("I'm a duck");
}
}
class Tiger {
shout() : void {
console.log("I'm a tiger");
}
}
class Noiser {
makeSomeNoise(animal: Animal) : void {
animal.shout();
}
}
const noiser = new Noiser();
noiser.makeSomeNoise(new Duck()); // I'm a duck
noiser.makeSomeNoise(new Tiger()); // I'm a tiger
이번엔 같은 코드를 타입스크립트로 작성하겠습니다(자바스크립트로도 물론 가능합니다)
어라? 뭔가 다릅니다
내가 만든 interface Animal을
Duck, Tiger 이 두개 클래스 모두 상속을 받지 않고 아무런 연관성이 없는데
makeSomeNoise 라는 메소드에서 Animal 타입의 매개변수를 받는데 정상동작하는것을 볼수 있습니다
바로 이것이 덕타이핑입니다
덕타이핑은 동적언어의 대표적인 특징이라고 할 수 있습니다
파이썬, 자바스크립트, 타입스크립트, golang 등 많은 언어에서 사용해볼수 있습니다
덕 타이핑에서는, 객체의 타입보다 객체가 사용되는 양상이 더 중요합니다
Animal을 상속받지 않더라도
Animal이 가지고 있는 shout() 메소드를
Duck과 Tiger 모두 가지고 있기 때문에
Animal도 shout()할수 있고, Duck도 할수 있고, Tiger도 할수 있어서
모두 같은것으로 취급해주는 개념입니다
만약 어떤 새가 오리처럼 걷고, 헤엄치고, 꽥꽥거리는 소리를 낸다면 나는 그 새를 오리라고 부를 것이다.
이제 이 말이 좀 더 와닿을까요?
그래서 우리는 이러한 동적언어를 매우 간편하게 사용할수 있습니다
굳이 직접적으로 클래스를 상속받거나 구현을 하지 않아도
같은 역할을 한다면 같은놈(?) 취급을 해주니깐요
axios의 post method는 AxiosRequestConfig라는 타입의 세번째 인자값을 갖습니다
post<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
post 메소드는 이런식으로 생겼습니다
아마 java, kotlin이었다면
우리는 세번째 인자값의 config를 전달하기 위해
AxiosRequestConfig의 인스턴스를 직접 생성하거나 이것을 상속받는 클래스를 생성하여 인스턴스화 한다음에 변수로 넣었을거예요
new AxiosRequestConfig()
new MyAxiosRequestConfig()
AxiosRequestConfig.builder.build()
뭐 이런식으로 말이죠
하지만 덕타이핑의 javascript는 AxiosRequestConfig와 같은 시그니처를 가지고 있다면
그러니깐 같은 프로퍼티를 가지고 있거나, 같은 메소드를 가지고 있거나 한다면
얼마든지 값을 넣을수 있는거죠
export interface AxiosRequestConfig {
url?: string;
method?: Method;
baseURL?: string;
transformRequest?: AxiosTransformer | AxiosTransformer[];
transformResponse?: AxiosTransformer | AxiosTransformer[];
headers?: any;
params?: any;
paramsSerializer?: (params: any) => string;
data?: any;
timeout?: number;
timeoutErrorMessage?: string;
withCredentials?: boolean;
adapter?: AxiosAdapter;
auth?: AxiosBasicCredentials;
responseType?: ResponseType;
xsrfCookieName?: string;
xsrfHeaderName?: string;
onUploadProgress?: (progressEvent: any) => void;
onDownloadProgress?: (progressEvent: any) => void;
maxContentLength?: number;
validateStatus?: (status: number) => boolean;
maxRedirects?: number;
socketPath?: string | null;
httpAgent?: any;
httpsAgent?: any;
proxy?: AxiosProxyConfig | false;
cancelToken?: CancelToken;
}
AxiosRequestConfig는 위와 같은 시그니처를 가지고 있습니다
모든 필드값이 ? 로 표시되어 optional 하기 때문에
{} 빈 object도 AxiosRequestConfig가 될수 있고,
저 많은 필드중에 하나의 필드값만 가져도 AxiosRequestConfig로 간주되어집니다
import axios, {AxiosRequestConfig} from "axios";
// AxiosRequestConfig의 signiture와 매칭된다면 어떤것이든 가능
// 가능
axios.post("/test", {}, {});
// 가능
axios.post("/test", {}, { url : "https://www.naver.com"});
이런식으로 config 옵션을 얼마든지 넣을수 있는거예요
최근 7년간 덕타이핑을 사용하는 동적언어 golang, javascript(typescript)를 주력으로 사용하고 있습니다
이러한 덕타이핑 개념은 정적언어만 사용하시던 분들은 다소 어라??? 이렇게 생각할수 있는 개념이기도하고
그래서 정적->동적언어로 언어스킬이 변경될때 다소 어리둥절할수 있습니다
제가 최대한 쉽게 덕타이핑을 설명드렸는데 도움되셨으면 좋겠어요
'WEB2.0 > 프로그래밍' 카테고리의 다른 글
IAM을 통해 aws codecommit 사용하기 (0) | 2022.05.13 |
---|---|
누가 javascript로 SOLID 지키는 소리를 내었는가 (0) | 2022.05.06 |
M1 맥에서 docker를 빌드 했는데 오류가 발생할때 (0) | 2022.01.31 |
DST Root CA X3 루트 인증서가 만료되었습니다 (8) | 2021.10.01 |
맥에 오라클 설치하기 (0) | 2021.09.01 |
- Total
- Today
- Yesterday
- 아이디어
- Apple
- 창업
- iPhone
- 공모전
- php
- 웹표준
- 트위터
- 스마트폰
- 자바스크립트
- 소프트웨어
- android
- 어플리케이션
- 네이버
- 모바일
- 안드로이드
- 구글
- 벤처
- 애플
- 대학생
- 앱
- 게임
- 아이폰
- 경진대회
- 앱스토어
- AWS
- JavaScript
- CSS
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |