💡 소프트웨어 설계에서
기능단위로 분해하고 추상화되어 재사용 및 공유가능한 수준으로 만들어진 단위
를 모듈이라고 하고,소프트웨어의 성능을 향상시키거나 시스템의 디버깅, 시험, 통합 및 수정을 용이하도록 하는 소프트웨어 설계 기법
을 모듈화라고 한다.
통상적으로 구조가, 여러 기능들을 하나로 모으고, 이들이 공유하는 데이터들로써 구성되어 있다.
패키지, 모듈 등은 파일 단위로 정의되어 import 방식이 대부분이다.
모듈
은 계층적인 소프트웨어 구조를 설계할 때, 한 계층의 부분을 차지하는 단위가 된다. 즉, 계층화를 통해 제공해야할 인터페이스와 자신이 의존하고 있는 인터페이스를 명확히 분리해 내야한다. 모듈은 상위 계층에 제공하는 인터페이스, 실제 자신이 담당하고 있는 역할을 처리하는 부분, 제공되는 인터페이스를 사용하기 위한 의존성을 가지는 부분 등 3개의 작은 계층으로 나누어질 수 있으며, 이렇게 만들어진 모듈은 이식성(Portability)과 호환성(Compatibility)이 높다. 분리된 계층을 가지지 못한 모듈들은 내부 구조의 변경이 상위 모듈에 영향을 줄 수 있으며, 이러한 형식의 구현은 구체적인 부분을 외부로 노출하게 된다.
모듈
도 함수와 마찬가지로 하나의 역할만 해야한다. 즉, 하나의 책임을 가지고 있다. 그 책임의 폭이 달라질지는 몰라도, 정확히 정의되는 하나의 역할을 맡고 있어야 하며, 그것 외에 다른 일을 해서는 안된다. 역할이 많아지면 해야하는 일이 많아지며, 다양한 역할은 제대로 하나의 역할도 수행하지 못하도록 만든다.
모듈의 내부 자료구조가 외부로 드러나는 것은 모듈에 대한 통제 권한을 다른 모듈에 넘기는 것과 같은 일이다. 그 말은 즉슨, 모듈의 책임이 약화되는 결과를 낳게 되며, 내부의 변경에 대해서 외부의 코드 변경을 유발할 가능성이 높다. 따라서, 모듈
은 전역적인 자료구조에 대한 사용을 가능한 줄여야 하며, 그러한 자료구조에 대한 접근 방법도 모듈에서 제공하는 인터페이스만을 사용해야 한다. 모듈이 외부에 공개하는 인터페이스들은 구조를 표현하는 것이 아니라, 요청을 받아들이는 창구 역할을 해야한다. 즉, 창구에서 받은 요청을 내부의 자료구조와 함수들을 이용해서 처리한 후, 결과를 알려주는 것이어야 한다. 만약, 구체적인 자료구조의 필드에 대한 접근을 허가한다면, 그것을 이용해서 처리해야할 일이 모듈 이외의 부분으로 전파될 가능성이 높다. 이러한 부분들은 모듈의 역할을 외부를 빼내는 결과가 될 것이다.
간단한 덧셈 뺄셈 모듈을 만들어보았다.
다음은 html문서인데, 여태까지 자바스크립트를 삽입하기 위해서는 <script>
태그의 type속성에 text/javascript
를 지정해주었던 것과 다르게, module
이라고 명시를 해준다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ModuleTest</title>
</head>
<body>
<script type="module" src='../js/index.js'></script>
</body>
</html>
html문서의 준비가 끝나면 자바스크립트 모듈을 만들어볼 차례다. 함수나 변수 앞에 export
키워드를 붙이면 해당 함수, 변수를 모듈로 내보낼 준비가 완료된다.
// ./src/lib/arithmeticOperation.js
export const add = (num1, num2) => {
return num1 + num2;
}
모듈로 내보내고 싶은 함수, 변수 앞에는 반드시 export
키워드를 붙여야지만, 외부에서 해당 함수, 변수에 접근할 수 있다.
외부에서 모듈
에 접근하기 위해서는 import
를 이용한다. 다시 한 번 강조하지만 export
키워드가 붙은 함수, 변수에 대해서만 접근이 가능한다.
import
를 통해 다음과 같이 모듈에 접근한다. 이때, 쉼표,
로 여러개의 함수/변수를 가져올 수 있다.
import { 모듈 함수/변수 } from '모듈 경로';
그러면, 조금 전에 만들었던 모듈에 접근한다면 아래와 같다.
// ./src/index.js
import {add} from '../lib/arithmeticOperation.js';
const num1 = 10;
const num2 = 4;
console.log(add(10, 4));
모듈에 빼기 기능까지 추가해서 작성해보았다.
//모듈 파일
export const add = (num1, num2) => num1 + num2;
export const sub = (num1, num2) => num1 - num2;
// js파일
import {add, sub} from '../lib/arithmeticOperation.js';
const num1 = 10;
const num2 = 4;
console.log(add(10, 4));
console.log(sub(10, 4));
import
에는 as
를 통해 별칭(alias)
을 부여해서 사용할 수 있는 용법도 있다. 별칭을 부여한다는 것은 모듈을 가져올 때 이름 중복을 피하거나, 편하게 사용하기 위해서 모듈의 이름을 변경하는 것이다. as
를 통한 별칭 지정은 다음과 같다.
import {원래이름 as 별칭} from '경로';
방금 전의 모듈 코드에 별칭을 붙여서 사용해본다.
import {add as a, sub as s} from '../lib/arithmeticOperation.js';
const num1 = 10;
const num2 = 4;
console.log(a(10, 4));
console.log(s(10, 4));
as
를 통해 모듈에서 내보낼 때 별칭을 지정할 수도 있다.
// 모듈파일
export const add = (num1, num2) => {
return num1 + num2;
}
export const sub = (num1, num2) => {
return num1 - num2;
}
export {add as a, sub as s};
마지막에 export
와 as
를 이용해서 별칭으로 내보내고 있다. 접근은 일반 모듈 접근하듯이 한다. 다만 import
시 내보낸 별칭을 사용해야 별칭을 이용할 수 있다.
//js 파일
import {a, s} from '../lib/arithmeticOperation.js';
const num1 = 10;
const num2 = 4;
console.log(a(10, 4));
console.log(s(10, 4));
모듈 내에서 가져와야할 것이 많은 경우(혹은 모두 가져와야할 경우) *
를 사용해서 모듈 내의 모든 함수, 변수를 가져온다.
*
를 사용해서 전체 모듈을 가져오면, 모듈은 객체 형태로 가져와지기 때문에 모듈의 함수나 변수를 객체 프로퍼티, 메소드 접근하듯이 사용할 수 있다.
import * as Op from '../lib/arithmeticOperation.js';
const num1 = 10;
const num2 = 4;
console.log(Op.add(10, 4));
console.log(Op.sub(10, 4));
https://vincentgeranium.github.io/study/2019/08/26/module.html
https://codedragon.tistory.com/6139
https://m.blog.naver.com/cybervictor008/220698639553
https://xionwcfm.tistory.com/185