(번역) 사용 중인 디자인 패턴을 보여주는 11가지 자바스크립트 예제 소스 코드

강엽이·2022년 7월 4일
46
post-thumbnail

원문 : https://medium.com/@jsmanifest/11-javascript-examples-to-source-code-that-reveal-design-patterns-in-use-b24db4b58a32

웹 애플리케이션 코드를 작성하는 동안 우리는 지속적으로 올바른 결정을 내리기 위해 노력합니다. 하지만 시간이 지남에 따라 코드가 방대해지면서 올바른 결정을 내리는 것은 쉽지 않아집니다.

다행히도 복잡한 문제를 해결하기 위해 코드에 적용할 수 있는 몇 가지 기술이 있습니다. 이 기술을 디자인 패턴이라고 부릅니다.

이 글에서는 영감, 정답 혹은 학습 경험을 통해 볼 수 있는 자바스크립트 세계의 여러 소스 코드를 살펴봅니다. 그리고 이를 통해, 독학이라는 느낌 없이 고급 코딩 기술을 빠른 속도로 배울 수 있습니다.

소스 코드에서 사용되는 패턴을 직접 공개하고 청중들에게 알리는 글이 많지 않다는 것을 알았습니다. 저는 여러분에 대해서 잘 모르지만, 제가 처음 프로그래밍을 접했을 때 패턴은 매우 도움이 되었습니다. 제가 도와드릴 테니 걱정하지 마세요.

Builder 디자인 패턴

빌더 패턴의 실례로 제가 가장 좋아하는 라이브러리 중 하나는 spotify-web-api-node입니다.

빌더 디자인 패턴은 복잡한 객체를 구성하는데 도움이 되는 행동(Behavioral) 패턴입니다.

이 라이브러리는 주요 구현부를 빌더로 구성합니다. 예를 들어 대부분의 메서드는 영어를 읽듯이 하나의 빌더를 사용하여 구성됩니다.

이 인터페이스를 제공하는 빌더 없이 이것을 구성하려 하면 빌더의 이점을 알 수 있습니다.

체이닝(Chaining)/플루언트(Fluent) 인터페이스

저희는 마지막 예제에서 이제 막 이 기술을 보았지만, 우리는 jQuery에 대해서도 이야기 할 수 있습니다. jQuery는 메서드를 함께 체이닝해 쉽게 읽을 수 있는 유연한 API를 갖고 있습니다.

이러한 jQuery는 React와 같은 현대적인 프레임워크가 등장하기 전에 자바스크립트 커뮤니티를 빠르게 성장시킨 라이브러리 입니다. 따라서 이 패턴은 프로그래밍에 유용한 것으로 이미 입증되었습니다.

jQuery는 당시 매우 인기 있었기 때문에 프런트엔드 공고에는 jQuery 경험이 있는 사람을 선호했습니다. 예전만큼 인기 있지는 않지만 지금도 여전히 많은 회사에서 사용하고 있습니다.

cheerio는 jQuery 라이브러리에서 크게 영감을 받아 제가 지금도 사용하고 있는 라이브러리이며, 웹 스크랩과 같은 주제가 등장할 때에도 여전히 인기가 있습니다. jQuery와 유사하게 DOM 조작을 위해 체이닝을 사용합니다.

이 글의 교훈은 무엇일까요? 체이닝(Chaining)/플루언트(Fluent) 인터페이스는 효과적이라는 것입니다.

라이프 사이클

여러가지 프로젝트를 구축하다 보면 정확한 시간에 이벤트가 처리되도록 하기 위해, 일부 유형의 라이프사이클의 파이프라인을 통합해야 하는 순간이 있을 것입니다.

이 기능을 사용하면 스타일 속성을 적용한 후 DOM 노드를 조작하는 것과 같은 이벤트의 특정 타이밍을 이용해야 하는 외부 기능에 유용할 수 있습니다.

이 개념을 배울 수 있는 좋은 깃 저장소는 snabbdom입니다. 이 라이브러리는 DOM으로 작업할 때 성능을 향상시키기 위해 단순성, 모듈성 및 강력한 기능에 중점을 둔 가상 DOM 라이브러리입니다.

snabbdom은 개발자들이 메인 patch 기능에 부착할 모듈을 직접 만들 수 있도록 하는 확장 가능한 모듈 API를 제공합니다. 각 모듈의 핵심 구현은 이러한 라이프 사이클을 활용하는 것이며, 이것이 이 라이브러리가 웹 애플리케이션에 대해 작동하는 방식으로 작동하도록 만드는 것입니다.

예를 들어 이 라이프 사이클에 연결되고 각 patch(즉, 각각의 "rerender") 간에 이벤트 핸들러가 올바르게 연결 및 정리되도록 하는 선택적 이벤트 리스너 모듈을 제공합니다.

명령 디자인 패턴

jQuery와 마찬가지로 redux도 인기가 급상승했습니다. 대부분 기본적으로 상태관리가 필요한 모든 react 앱에서 사용하기 때문입니다. 이러한 redux는 실제로 사용되는 명령 디자인 패턴 중에 제가 가장 좋아하는 사례입니다.

Redux의 명령 디자인 패턴은 각 액션이 명령이고, 디스패치 액션 개념을 통해 동작합니다. Redux 문서에는 상태를 바꾸는 유일한 방법은 액션을 디스패치 하는 것이라고 언급되어 있습니다.

이 패턴이 제공하는 이점이 Redux가 React에서 인기를 갖게 된 주요 원인입니다. Redux는 작업을 호출하는 객체와 호출될 때 무엇을 해야 하는지 아는 객체를 구분하여 명령 패턴을 활용합니다. 그렇기 때문에 React와 함께 사용하기에 아주 좋은 조합입니다. React는 대부분 멍청한(Dumb) 컴포넌트와 똑똑한 컴포넌트 간의 관심사의 구성과 분리에 관한 것 입니다. (하지만 똑똑하고 멍청한 컴포넌트의 개념을 활용하지 않는 React 앱을 설계하는 방법은 여전히 다양합니다.)

Redux의 이러한 패턴을 최대한 활용할 수 있도록 강력한 미들웨어들이 만들어졌습니다. 예를 들어, redux devtools와 같은 것들이 있습니다.

모듈성

lodash의 함수들이 어떻게 구성되어 있는지 보기 위해 깃 저장소를 봤을 때 "이 함수가 여기 있는 이유가 뭐지?"라고 자문한 적이 있습니다. flowRight와 같은 함수는 함수를 호출하고 결과를 반환하기 위해 다른 함수를 가져오기 때문입니다.

그러나 시간이 지남에 따라 더 많은 경험을 쌓기 시작하면서 모듈/유틸리티 기능을 이런 식으로 구조화하는 것의 아름다움을 깨달았습니다.

코드를 작성할 때 재사용성, 단일 책임을 갖는 함수, DRY(Do Not Repeat Yourself)의 개념을 생각하는 데 도움이 됩니다. 제가 flowRight 구조에서 얻는 이점은 flow에 의존하여 "flow" 논리를 수행함으로써 flowRight는 단지 "오른쪽으로 흐르게"만 책임지면 된다는 것입니다. 또한 flow 구현에 업데이트가 있는 경우 flow을 가져와서 사용하는 다른 모든 기능 뿐만 아니라 flowRight에도 자동으로 반영된다는 것을 깨달았습니다.

추상 구문 트리(Abstract Syntax Trees, AST)와 컴포지트 디자인 패턴

솔직히 말해서 AST 작업에 익숙해지는 제 접근 방식은 좀 이상하지만, 제게는 효과가 있었습니다. 왠지 모르게 TypeScript AST로 작업한다는 것은 저에게 정말 매력적으로 들립니다. 대부분의 사람들이 TypeScript 컴파일러로 AST를 사용하는 데 익숙해지기 전에 먼저 babel에 대해 자세히 알아볼 것을 권장하지만, 저는 반대로 시작했습니다. 개발자들이 TypeScript 컴파일러로 더 쉽게 작업할 수 있도록 하는 데 중점을 둔 ts-morph라는 훌륭한 라이브러리가 있습니다. 컴파일러 API에 익숙해지면서 ts-morph를 직접 배우면 babel을 건드리지 않고도 babel을 훨씬 더 쉽게 이해할 수 있습니다.

또한 작업하는 많은 객체가 유사한 인터페이스를 공유한다는 것을 알 수 있습니다. 이것은 컴포지트 디자인 패턴을 사용하는 소비자에게 노출되는 인터페이스입니다.

프록시 디자인 패턴

프록시 패턴은 실제 객체로 작동할 placeholder 객체를 제공합니다. 이 객체는 실제 객체에 대한 접근을 제어합니다.

immerproduce 함수에 초기 값을 반환할 때 이 패턴을 사용합니다. 이 패턴을 이용하면 React 앱에 좋은 불변성을 얻을 수 있습니다.

옵저버 / PubSub 디자인 패턴

이 패턴을 많이 사용하는 라이브러리 중에 하나는 twilio-video.js입니다. 거의 모든 객체가 EventEmitter를 직접 확장하거나 상속을 통해 확장합니다.

Participant와 같은 핵심 객체는 이 패턴을 구현하여 API 사용자가 앱에서 이벤트 기반의 영상 채팅을 구현할 수 있도록 합니다.

예를 들어, 사용자(또는 참가자)의 미디어 트랙이 준비되면 (미디어 트랙이 DOM에 연결되고 스트리밍이 시작됨) someParticipant.on('trackSubscribed', () => {...}) 코드를 통해 원격 참가자들에게 미디어트랙이 준비 된 것을 인지시키고 조절할 수 있도록 합니다.

책임 연쇄 디자인 패턴

자바스크립트에서 책임 연쇄를 구현하려면 일반적으로 하나 이상의 요청을 처리할 수 있는 느슨하게 결합된 함수의 파이프라인이 필요합니다.

이 패턴을 보여주는 가장 좋은 예시는 express 라이브러리의 라우팅 개념입니다.

예를 들어 /dogs 라우트 핸들러를 만들고 /dogs?id=3에 대한 핸들러를 만들고 사용자가 dogs?id=3으로 이동했다고 가정해봅니다. 이 때 /dogs를 처리하는 핸들러가 요청을 처리하기로 결정할 수도 있고 두 번째 핸들러로 전달할 수도 있습니다.

방문자 디자인 패턴

툴에 대해 더 깊이 파고들 때까지는 실제로 이 패턴이 구현된 것을 거의 볼 수 없었습니다. 방문자 패턴은 AST 노드를 "방문"하여 AST의 각 객체로 작업하려는 경우에 유용합니다.

방문자 패턴은 확장성, 플러그인, 스키마를 표시 등과 같은 여러가지 이유로 사용됩니다.

Graphql 저장소에 구현되어 있습니다.

프로토타입 디자인 패턴

프로토타입 패턴의 핵심은 객체가 매번 새로운 인스턴스가 되지 않도록 하는 것입니다. 이것은 우리가 add 메소드를 이용하여 MathAdd 객체를 생성하는 경우, 구현은 변경되지 않고 단순히 add를 재사용하여 여러 개의 MathAdd 인스턴스를 생성하는 경우에 사용됩니다. 이것은 성능상의 이점이기도 합니다.

request 라이브러리는 거의 모든 클래스 객체에서 이 패턴을 사용합니다.

결론

이상으로 이번 포스팅을 마치겠습니다. 소중한 것을 발견하셨기를 바라며 앞으로도 많은 관심 부탁드립니다.

🚀 한국어로 된 프런트엔드 아티클을 빠르게 받아보고 싶다면 Korean FE Article(https://kofearticle.substack.com/)을 구독해주세요!

profile
FE Engineer

0개의 댓글