모듈화 (modularisation)
모듈(module)이라는 건 말 그대로 전체를 설계할 때 조립, 해체, 수정을 쉽게 할 수 있도록 전체의 구성요소들을 최소 단위의 블럭들로 규격화 한 것을 말한다. 쉽게 얘기하면 레고 블럭 같은 거라고 생각하면 된다.
코딩도 마찬가지다.
소위 말하는 '좋은 코드'란 처음 코드를 작성한 사람 뿐만 아니라 다른 어느 누가 코드를 보거나 이어서 코드를 짜더라도 코드를 쉽게 파악하고 쉽게 수정할 수 있는 코드이다.
그러기 위해서는 코드의 모듈화, 캡슐화가 반드시 필요하다.
큼직한 기능별로 파일을 나누고, 같은 파일 안에서도 되도록이면 세부적인 기능별로 함수화해서 코드의 유지 및 보수 난이도는 낮추고, 코드의 재사용율은 높여서 같은 코드를 여러번 반복해서 작성하는 일이 없도록 해야 한다.
웹개발을 처음 배우기 시작한 당시에는 html 파일 한 개 안에서 script와 style을 모두 처리했다가,
이후에 html, js, css 파일을 분리하는 발전과정을 겪었다.
그리고 이제 한 번 더 발전하려는 것이 js 파일을 모듈화 하는 것이다.
최근에 개인과제로 만들었던 영화 검색 사이트를 예로 들면,
script.js 파일 하나에서 모든 javascript 코드를 전부 담당했던 것을
이렇게 나눠주면 된다.
왜냐하면 사이트에서 필요한 기능이 크게 2가지이기 때문이다.
따라서 1번 기능을 담당할 movie.js 와
2번 기능을 담당할 search.js 로 나누고,
main.js 가 이 둘을 하나로 묶어주는 메인보드 역할을 한다.

그림 출처: James R 튜터님 https://www.youtube.com/@jamesr3187
<script type="module">1. 모듈 별로 독립적인 scope 생성
2. 스크립트 지연 실행 기본 내장 ≡<script defer>
3. Strict Mode 기본 내장
그런데, 여기서 js 파일을 3개로 나눴다고,
html 파일의 <head> 안에서 그냥
<script src="./main.js"></script>
<script src="./movie.js"></script>
<script src="./search.js"></script>
이렇게 하면 안 된다.
물론 "절대 안 된다!" 는 아니지만, 이렇게 되면 모듈화의 의미가 없어진다.
왜냐하면, 파일만 3개로 나눴을 뿐이지 각각의 js 파일이 모두 같은, 하나의 scope 안에 존재하기 때문이다.
따라서 각각의 파일이 서로 독립적으로 scope를 가지려면, 즉 제대로된 모듈화를 하려면
<script> 안에 type="module" 이라는 attribute를 넣어서 이 script 파일이 module 이라고 명시해줘야 한다.
<script type="module" src="./main.js"></script>
<script type="module" src="./movie.js"></script>
<script type="module" src="./search.js"></script>
이렇게 되면 각각의 js 파일이 각자의 scope 를 가지기 때문에
서로 독립적으로 코드를 진행해 나갈 수 있고,
이를 쉽게 확인하는 방법은, 3개의 파일에서 같은 변수명을 선언해보는 것이다.
let movies;
type="module" 을 넣어주기 전에는 한 scope 안에 있었기 때문에 첫번째 js 파일에서 이미 defined 된 변수명이므로 두번째 js 파일의 let movies; 에서 오류가 발생한다.
하지만, type="module" 을 넣어주게 되면, 똑같이 해도 오류가 발생하지 않는 것을 확인할 수 있고, 이로써 비로소 모듈화가 된 것이다.
이 type="module" 에는 다른 기능도 있다.
이전 글에서 <script defer> 에 대해 설명했었는데
그것과 같은 기능이다.
strict mode 에 대해서는 간략한 예시만 보여주고, 자세한 건 나중에 관련 글을 써보도록 하겠다.
// 변수 선언없이 즉시 사용 방지
a = 10;
console.log(a); // Uncaught ReferenceError: a is not defined
// 예약어를 변수명으로 사용 방지
let arguments; // Invalid use of 'arguments' in strict mode.