이챙의 개발 log
어댑터 패턴으로 타입 호환하기
어댑터 패턴
어댑터패턴(Adapter pattern)은 서로 호환되지 않는 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하는 패턴이다.
어댑터 말 그대로 어댑터 역할을 해준다. 다른전압을 가진 나라를 가서 여행용 어댑터를 들고가는 것과 같다.
// 아이폰 충전기
class IphonCharger {
chargeLightning(){
console.log('라이트닝 케이블로 아이폰 충전중');
return '아이폰 충전 완료'
}
}
// 안드로이드 충전기
class AndroidCharger {
chargeUSBC(){
console.log('USBC 케이블로 안드로이드폰 충전중');
return '안드로이드폰 충전 완료'
}
}
class Adapter {
constructor{
this.androidPhone = new AndroidCharger();
}
// 아이폰 충전 인터페이스와 같은 메소드 사용
chargeLightning(){
console.log('라이트닝 -> USBC 변환')
const result = this.androidPhone.chargeUSBC();
return `어댑터 사용 + ${result}`
}
}
function chargePhone(charger){
const result = charger.chargeLightning()
console.log(`충전완료: ${result}`)
}
// 기존 아이폰 충전기 사용
const iphoneCharger = new IphonCharger();
chargePhone(iphoneCharger);
// 어댑터를 사용해 안드로이드기 충전기로 아이폰 충전
const adapter = new Adapter();
chargePhone(androidCharger)
위의 예시는 안드로이드 충전기로 아이폰을 충전하게 해주는 예제이다. [클로드의 도움을 받음 ㅎㅎ!]
안드로이드 USBC 케이블을 라이트닝 포트로 변환해주는 어댑터를 구현하여 호환되지 않는 인터페이스를 연결하여 AndroidCharger의 코드 변화 없이 사용하도록 했다.
- chargePhone함수는 chargeLightning 메소드만 알고있으며
- Adapter내 라이트닝 인터페이스를 연결하여
- 내부에서는 안드로이드의 메소드를 호출했다.
어댑터는 중간에서 인터페이스를 변환하고 기존 코드를 수정하지 않고도 서로 다른 인터페이스를 가진 새로운 시스템을 만들 수 있다.
실제 타입스크립트에서 사용
내가 이 패턴을 알게된건 타입스크립트를 사용하며 생긴 호환성 이슈 때문이었다.
한 컴포넌트내에서 2개의 데이터가 props로 들어오는데 값은 같지만 필드는 달랐다.
const data1 = {
commonId: string;
commonTitle: string;
...
}
const data2 = {
id: string
title: string
...
}
예를 들어 위의 데이터 처럼 사용하고자 하는 값은 같은데 필드가 다른 경우였다. 하나의 필드로 만들어야 했다.
타입을 어떻게 해야 하나 고민을 했었는데 어댑터 패턴을 사용하면 쉽게 해결할수있었다.
interface CommonItems {
id: string;
title: string;
content: string;
category: string;
thumbnailPath: null | string;
}
export const boardAdapter = (item: ContentResponse): CommonItems => ({
id: item.id,
title: item.title,
content: item.content,
category: item.category,
thumbnailPath: item.thumbPath,
});
export const searchAdapter = (item: SearchGallery): CommonItems => ({
id: item.boardContentId,
title: item.title,
content: item.content,
category: item.category,
thumbnailPath: item.thumbnailPath,
});
interface TabListItemProps {
guide: CommonGuideItems;
index: number;
}
const Guide = ({guide, index}: TabListItemProps) => {
...
}
export default Guide;
// 어댑터 사용하는 컴포넌트
<GuideListITem guide={boardAdapter(guide)} key={guide.id} index={index} styles={styles} />
props오는 데이터들이 서로 타입이 다르므로 보낼때 어댑터로 CommonGuide 형태로 변환을 해줬다.
호환되지 않는 인터페이스들을 공통된 인터페이스로 변환하여 한 컴포넌트내에서 일관적으로 사용하게끔 했다.
그런데 데이터들이 계속 늘어날경우엔 이 방법이 맞지 않아보인다. 사실상 타입 자체를 통일해서 내려주는게 제일 베스트이지만 모든 여건이 딱딱 들어 맞을 순 없으니,,이런 패턴들을 알고 있으면 자유롭게 사용할 수 있을거같다.
'javascript > typescript' 카테고리의 다른 글
Property 'oo' does not exist on type 'oo'. 타입스크립트 error 해결 (0) | 2022.12.12 |
---|---|
Typescript 에서 typeof 사용하기 (0) | 2022.08.25 |
typescript 를 써야하는 이유,,! (0) | 2021.11.22 |
이챙(leechaeng)
프론트엔드 개발도 하고 뛰기도 하고