외부코드, 외부라이브러리, 외부.. 등과 같이 가져와서 붙여서 사용하는 것들은 우리에게 정말 많은 편의를 제공한다. 머리아프게 생각해야했던 로직들을 라이브러리단에서 모두 해결해주고 시간단축까지 해주며, 개발의 편의성을 높여준다.
하지만, 이런 외부코드를 사용하는 것은 늘 위험에 따른다.
우리는 외부코드를 "잘" 고를 수 있어야 하고, "똑똑하게" 사용할 줄 알아야한다.
"잘" 고르기
세상에는 수많은 라이브러리가 있으며, 어떤 기능을 수행하는 라이브러리가 필요할 때, 같은 기능이 있는 라이브러리를 여러 개 찾을 수 있을 것이다.
그러나 선택지가 너무 많으면 우리 같은 웹 개발자는 혼란에 빠지게 된다. 제일 좋은 것이 무엇인지 어떻게 알 수 있을까? 만약 잘못된 선택을 한다면 어떡할까?
웹 개발을 할 때 단 한 개의 "최고의 선택"은 없는 경우가 많다. 그러나 어떤 선택이 다른 선택보다 나은 경우는 있다. 아래의 두 입장을 고려해서 라이브러리를 선택하는 것은 중요하다.
💻 개발자 입장
잘 정리된 문서
유연성 (내가 원하는 방향과 잘 접목이 되는가)
활발한 유지 보수
미래지향성
테스트
깨끗한 코딩:
활발한 커뮤니티
그 외에 내가 개인적으로 보는건,
fork 횟수
issue의 개수, 분위기
스타 개수
👥 사용자 입장
파일 사이즈
성능
브라우저 지원
접근성(다양한 사용층 고려)
반응(모바일)
"똑똑하게" 쓰기
외부라이브러리를 쓰다보면 편리성과 별개로 사용법을 제대로 익히지 못한채로 사용한다던가,
코드 자체에 버그가 있다던가, 코드의 기능이 변경되어 이슈를 발생시킬 수도 있다.
따라서 외부코드에 지나치게 의존하는 것은 좋은 선택지가 아니다.
외부 라이브러리를 사용할 경우 시간 단축에 효과가 있지만 잘못 사용함에 있어서 발생하는 영향도가 얼마나 있을지 알지 못하기 때문에 학습 테스트를 통해 외부 api에 대한 테스트를 미리 진행한다.
외부 라이브러리에 대한 학습 테스트를 진행하여 사용하면 해당 라이브러리의 버전이 올라갔을 때 우리가 사용하는 목적에 맞게 정상적으로 돌아가는지 쉽게 테스트를 해볼 수 있어서 좋다.
Adapter pattern을 이용하여 변경의 요지가 있는 인터페이스를 방어할 수 있다.
인터페이스 호환성 문제 - Adapter pattern*
기존에 있던 구조를 새 구조로 유연하게 전환하거나 새 구조에서 기존의 구조로 전환하는 데 사용하는 패턴
한국에서는 220V를 쓰는데, 일본은 110V를 사용한다. 그렇다면 220V모양으로 만들어진 전자제품을 일본에서 쓰려면 어떻게 해야 할까? 110V로 변환해주는 무언가를 사용해주면 된다(돼지코라 불리는 변압기/어댑터를 사용한다).
const Printer = (function() { function Printer() { this.textArr = []; }; Printer.prototype.pushText = function(text) { this.textArr.push(text) }; Printer.prototype.print = function() { return this.textArr.join(' '); } return Printer; }())
const printer = new Printer(); printer.pushText('Hello'); printer.pushText('Design'); printer.pushText('Pattern'); const result = printer.print(); console.log(result); // Hello Design Pattern
여기까지는 문제가 없다. 그러나 문제는 주로 변화에서 발생하며, 현실 세계는 끝임없이 환경이 변화한다. 만약 우리가 이 코드를 3개월간 사용하다가
해시태그(#)를 붙여서 출력하는 프린터* 가 출시하여, 우리는 그 프린터로 교체를 해야한다고 가정해보자.
설상가상으로 우리가 받은 새로운 프린터의 명세(Interface)는 현재와 미묘하게 다르다 고 한다.
const HashTagPrinter = (function() { function HashTagPrinter() { this.textArr = []; }; HashTagPrinter.prototype.pushText = function(text) { this.textArr.push(text) }; HashTagPrinter.prototype.printWithHashTag = function() { return this.textArr.map(text => `#${text}`).join(' '); } return HashTagPrinter; }())
이제 메인 함수의 코드를 새로운 프린터로 교체해 보도록 하자.
const printer = new HashTagPrinter(); HashTagPrinter.pushText('Hello'); // HashTagPrinter printer로 교체 HashTagPrinter.pushText('Design'); HashTagPrinter.pushText('Pattern'); const result = HashTagPrinter.print(); // printer는 명세가 맞지않아 에러가 발생한다. console.log(result);
좋은 코드는 최소한의 변경으로 변화에 대응할 수 있어야 한다.
일단 새로운 HashTagPrinter 객체를 생성해서 printer에 할당하는 부분은 필수로 변경해 줘야 한다.
그러나 그 아래의 실질적인 비즈니스 로직에서는 불필요한 변경은 최소화하고 싶다.
위 코드에서는 마치 220V로 만든 가전기기를 110V에서 사용할 수 없듯이, HashTagPrinter에는 print()가 아닌 printWithHashTag()를 사용하고 있어서 컴파일 에러가 발생한다. 그렇다면 방법은 두 가지다.
const result = printer.printWithHashTag()로 변경해 주던가,*
아니면 변압기 역할을 하는 어떤 무언가를 만들어 주던가.*
첫번째 방법이 쉬어 보일 수 있으나, 실제 코드에서는 저 부분만 수정한다는 보장이 없을뿐더러, 만약 우리가 다시 이전 프린터를 사용한다고 하면 또다시 같은 곳을 수정해줘야 한다. 따라서 두 번째 솔루션인 돼지코(Adapter)를 만들어 보도록 하자.
어댑터(Adapter)를 만드는 방법은 간단하다. 명세가 맞지 않는 부분을 맞춰주기만 하면 되는 것으로, 위 프린터 예제에서는 printWithHashTag()가 printer()를 호출했을 때 동작하도록 만들어 주면 된다.
const HashTagAdapter = (function() { function HashTagAdapter(hashTagPrinter) { this.printer = hashTagPrinter; }; HashTagAdapter.prototype.pushText = function(text) { this.printer.pushText(text) }; HashTagAdapter.prototype.print = function() { return this.printer.printWithHash(); } return HashTagAdapter; // 220V -> 110V 변환! }())
const printer = new HashTagAdapter(new HashTagPrinter()); printer.pushText('Hello'); printer.pushText('Design'); printer.pushText('Pattern'); const result = printer.print(); console.log(result); // #Hello #Design #Pattern
어댑터 패턴은 한번 익혀두면, 웬만한 인터페이스 호환성 문제는 쉽게 해결할 수 있을 것이다.
'javascript' 카테고리의 다른 글
리팩토링 해보자 with JS - 1 (0) | 2021.12.01 |
---|---|
추석하루 간단하게 본 NEST JS (0) | 2021.09.22 |
lodash 유용하게쓰기 (응용해서 쓰기) (0) | 2021.06.25 |
롤업과 웹팩의 차이점 (rollup vs webpack) (2) | 2021.04.22 |
자바스크립트 클로저가 아직도 난해한 개념으로 다가오는 사람들 모여라! (6) | 2021.03.05 |