[JS] 순환 의존성에 관하여

이수빈·2023년 1월 10일
1

Html, Css, JS

목록 보기
1/7

JavaScript에서 모듈화와 순환 의존성


SW 엘리스 1차 프로젝트를 하면서 코드구조에 관해 고민했던부분들을 작성하게 되었다.

모듈이란?

  • 재사용 가능한 코드조각임. 일반적으로 파일 단위로 분리함.
  • 모듈이 성립하려면 자신만의 파일스코프를 가질 수 있어야함.

초기의 Javascript는 웹페이지에 단순한 보조기능을 처리하는 용도로 사용되었기 때문에, 모듈시스템을 지원하지 않았다.

하지만, Javascript가 수행하는 역할들이 점점 많아지면서, 파일들이 많아지게 되고, script 태그를 이용해 외부 자바스크립트 파일을 로드하는 방식은 한계를 보이게 되었다.

script 태그를 통해 여러 자바스크립트 파일을 로드하면 분리된 자바스크립트 파일은 하나의 자바스크립트 파일 내에 있는 것처럼 동작한다. 즉 전역환경을 공유하기 때문에 변수명의 중복되는 문제나 의도하지 않은 함수호출등의 Side Effect가 발생 할 수 있다.

모듈화의 등장

이러한 문제를 해결하기 위해 CommonJS, AMD, ES6모듈와 같은 여러가지 모듈화 방법들이 등장하게 되었다. 최근에는 ES6 모듈시스템인 import, export 방식을 많이 사용하는 추세이다.

순환 의존성이란?

모듈화가 된 컴포넌트 끼리 서로를 참조하는 상황이 발생하여, cyclic dependency가 발생한 상황이다. CommonJS, ES6모듈은 순환의존성을 지원하기는 한다.

하지만 순환의존성은 대부분의 상황에서 권장되지 않는다. 기존의 모듈화가 추구했던 파일 스코프 단위의 분리를 막고, 의존성이 생겨버린 여러개의 컴포넌트는 그 자체로 하나의 거대한 컴포넌트가 되어버린다. 따라서, 코드에 에러가 발생했을때 컴포넌트끼리의 의존성이 얽혀있기 때문에 어디서 에러가 발생했는지 찾기 힘들다.

프로젝트 코드에서의 순환의존성 예시

다음은 Dependency Cruiser Extension을 통해 확인한 컴포넌트 의존성이다.

 export function deleteOne(event) {
    const { id } = event.target.dataset;
    const local = getLocal("bookInfo");
    const filtered = local.filter(data => data.ISBN !== parseInt(id));
    setLocal(filtered);
    renderData(filtered);
}

장바구니에서 target Item을 삭제하는 과정에서 삭제후 다시 Data를 Re-Rendering하도록 코드를 설계하였는데, 이 과정에서 컴포넌트끼리 서로 의존을 하는 상황이 발생하였다.

이는 Data를 Re-Rendering 하는 과정이 아니라, 삭제된 UI만 Update하는 식으로 하여 순환 의존성을 해결하였다.

export function deleteOne(event) {
    const { id } = event.target.dataset;
    const targetbox = document.querySelector(`.itembox[data-id="${id}"]`);
    const local = getLocal("bookInfo");
    const filtered = local.filter(data => data.ISBN !== parseInt(id));
    targetbox.remove();
    setLocal(filtered);
}

코드에 구조에 관한 고민들을 통해 1차 프로젝트는 순환참조가 일어나지 않도록
단 방향의 의존성을 가지도록 Component를 설계했고, 기능단위의 모듈화를 진행하였다

ref)

profile
응애 나 애기 개발자

0개의 댓글