본문 바로가기

Node.js

02.자바스크립트 기초 문법과 모듈

1. npm 패키지

노트에서 패키지를 사용할 때는 npm 공식 웹 사이트(https://www.npmjs.com/

npm 공삭 웹 사이트로 이동한 후 terminal을 검색하면 검색 결과 오른쪽에 가로 막대 3개가 있는데, 여기에서 p는 인기도, q는 품질, m은 유지보수를 뜻합니다. 패키지마다 클릭하면 어떻게 설치하는지, 그리고 어떤 식으로 사용하는지 확인할 수 있습니다.

터미널 창에서 npm i 를 사용하여 패키지를 설치할 수 있습니다. 패키지를 설치한 후에는 package.json 파일에 dependencies라는 항목이 생겨서 애플리케이션이 사용하는 패키지와 버전이 표시되어 있습니다.

 

패키지를 더 이상 사용하지 않는다면 삭제할 수도 있습니다. npm에서 패키지를 삭제하는 uninstall 명렬을 터미널 창에 입력합니다.

 

2. 자바스크립트 기초문법

프로그램에서 함수란 특정 작업을 실행하도록 명령을 모아 놓은 것이입니다. 자바스크립트 함수 제작과 사용법 살펴보면

1. 기본 방법

함수를 사용하는 기본 방법은 함수를 선언하고 필요할 때 호출하는 것입니다. 여러 명령으로 구성된 함수를 만드는 것을 함수를 선언한다고 하고, 만들어진 함수를 실행하는 것을 함수를 호출한다고 합니다. 함수를 선언할 때는 function이라는 예약어를 사용하고 그 뒤에 함수 이름을 붙입니다.그리고 필요한 명령은 중괄호{}안에 작성합니다. 함수를 선언할 때 어떤 값을 받아야 한다면 그 값을 주고받는 변수를 함수 이름 옆에 괄호를 붙여서 저장합니다.이를 매개변수 혹은 피라미터라고 합니다. 

function 함수명 {...} / function 함수명(매개변수){...}

 

함수를 호출할 때는 넘겨주는 변수값을 인수 또는 아큐먼트라고 합니다. 선언한 함수명(인수1,인수2)로 함수를 선언할 때의 변수는 매개변수, 함수를 실행할 때의 변수는 인수라고 하고 일반적으로 이 2가지를 묶어서 인자라고 합니다.

 

2. 함수 표현식

한 번만 실행하고 끝나는 함수라면 굳이 이름을 붙이지 않고 필요한 명령만 묶을 수 있습니다. 이름이 없는 함수는 변수에 할당해서 변수 이름을 함수처럼 사용할 수 있습니다. 모듈에서는 변수에 할당한 함수를 마치 벼수처럼 여러 모듈 간에 주고박을 수도 있습니다. 함수를 식처럼 사용하므로 이렇게 작성한 함수를 함수 표현식이라고 합니다. 

함수를 값으로 가지는 변수는 한 번 만들면 중간에 바꾸지 않으므로 const 예약어를 사용합니다.

*에크마스크립트 2015 이전에는 var 키워드를 사용해서 변수를 지정했습니다. 지금은 var가 가지고 있는 몇가지 문제 때문에 변수를 지정할 때 let이나 const를 많이 사용합니다.

 

3. 즉시 실행 함수

함수 표현식으로 작성한 함수를 반드시 변수에 할당해야만 사용할 수 있는 것은 아닙니다. 비동기 처리 방법으로 함수 안에 또 다른 함수를 넣어서 실행할 수 있습니다. 이럴 경우 따로 변수를 거치지 않고 함수를 선언하는 동시에 실행할 수 있습니다. 이런 함수를 즉시 실행 함수라고 합니다.

// 함수 선언과 호출을 동시에 
(function (a,b){
  console.log(`두 수의 합: ${a+b}`);
})(100,200);

 

4. 화살표 함수

에크마스크립트 2015부터는 함수를 선언할 때 화살표(=>)를 사용해서 조금 더 간단하게 만들 수 있습니다. 화살표를 사용하므로 화살표 함수 또는 에로우 평션이라고 합니다.화살표 함수는 function이라는 예약어를 사용하지 않고 함수 이름도 없습니다.

(매개변수) => {...} 

매개변수가 없을 때는 매개변수가 들어가는 소괄호 부분을 비워 둡니다.  

화살표 함수에서 실행할 명령이 한 줄뿐이라면 중괄호{}를 생략할 수 있습니다. 그리고 한 줄 명령에 return문이 포함되어 있다면 return문도 생략할 수 있습니다. 

 

5. 자바스크립트 객체

자바스크립트에서 객체는 여러 자료 형태를 하나로 묶어 놓은 것을 말합니다. 객체는 중괄호({})안에 모든 정보를 담는데 키와 값이 하나의 쌍을 이룹니다. 이런 키:값 형태의 쌍이 여러 개일 경우 쉼표로 구분합니다. 키: 값 형태의 쌍을 프로퍼티라고 합니다. 키는 문자열이어도 큰따옴표를 사용하지 않지만 값이 문자열이라면 큰따옴표를 사용해야 합니다.

 

 

3.자바스크립트 비동기 처리

더보기

프로그램 코드를 작성한 순서대로 처리하는 방식을 동기 처리라고 합니다.동기 처리는 한 번에 손님 1명 주문만 처리합니다. 대기하는 줄이 길면 주문을 처리하는데도 시간이 걸립니다. 순서대로 처리하므로 실행시간이 짧은 코드가 나열되어 있을 때 적합합니다. 반면 비동기 처리 방식은 주문을 받는 과정과 만드는 과정을 동시에 진행하므로 대기하는 줄도 짧고 빠른 시간에 주문을 처리합니다. 프로그램 중간에 시간이 많이 걸리는 작업을 잠시 미뤄 두고 빨리 처리할 수 있는 다음 작업으로 넘어가서 하난의 작업이 완료되지 않아도 다른 작업을 시작할 수 있는 것이 비동기 프로그래밍이라고 합니다.

*비동기를 연습할 때 setTimeout함수를 사용해 괄호 안에 있는 명렬을 특정 시간이 지난 후에 실행합니다.

 

시간이 걸리는 함수와 빨리 처리할 수 있는 함수가 뒤섞여있을 때 함수들을 원하는 처리 순서에 맞게 프로그래밍하는 것을 비동기 처리라고 합니다. 자바스크립트에서는 시간이 걸리는 작업이 있을 경우 기본적으로 비동기로 처리합니다.

 

자바스크립트에서 비동기 처리를 할 때 사용하는 방법은 크게 다음 3가지입니다.

방법 버전 기능
콜백 함수 기존부터 사용 함수 안에또 다른 함수를 매개변수로 넘겨서 실행 순서를 제어합니다. 콜백 함수가 많아지면 기독성이 떨어질 수 있습니다.
프라미스 에크마스크립트 2015부터 도입 프라미스 객체와 콜백 함수를 사용해서 실행 순서를 제어합니다.
ansyc/await 에크마스트립트 2017부터 도입 ansyc와 await 예약어를 사용해서 실행 순서에 제어합니다.
  • 콜백함수

콜백 함수란 다른 함수의 매개변수로 사용하는 함수를 말합니다. 예를 들어 A함수 안에 B함수를 매개변수로 지정하면 A함수를 모두 실행한 후 이어서 B함수를 실행합니다. 

1. 함수 이름을 콜백으로 사용하기

// '주문 접수' 3초 후 '완료' 메시지 표시하기   (결과 비교: 02\results\callback-1.js)
const order = (coffee,callback) =>{
  console.log(`${coffee} 주문접수`);
  setTimeout(()=>{
    callback(coffee)
  },3000);
}

const display = (resule)=>{
  console.log(`${resule} 완료!`);
}
order('아메리카노',display)
  • 프라미스

프라미스는 처리에 성공했을 때와 성공하지 않았을 때의 반환 결과를 미리 약속해 둔 것입니다. 프라미스 객체에서는 처리에 성공했는지 실패했는지 판단하고 그 결과값을 반환합니다. 그 결과값을 받아서 처리하는 부분을 직접 작성해야 하는데 이때 사용하는 함수가 then과 catch입니다. then함수는 성공했을 때, 그리고 catch함수는 실패했을 때 넘겨박은 결과값을 사용해서 실행할 명령을 지정합니다.

// 프로미스를 사용해 피자 주문하기   (결과 비교: 02\results\promise.js)
let likePizzz = false;
const pizza = new Promise((resolve,reject)=>{  // new Prmois를 사용해서 만든 프라미스 객체
  if(likePizzz)
  resolve('피자를 주문합니다.');
  else
  reject('피자를 주문하지 않습니다.')
});

pizza  //프라미스 체이닝
.then(result => console.log(result))
.catch(err=>console.log(err));
  • async/await

에크마스크립트 2017부터 async와 await 예약어 사용 가능합니다. 함수를 선언할 때 함수 앞에 async를 붙여서 선언하면 그 함수 안에서는 await를 붙여서 비동기 처리할 수 있습니다. await 예약어는 자바스크립트에서 비동기 코드를 실행할 때 유용한데, await는 async함수에서만 사용할 수 있습니다. 그래서 await를 사용해서 특정 함수를 비동기 처리하겠다면 그 함수를 감싸는 async function을 만들어야 합니다.

*async는 aynchronous 비동기의 줄임말입니다.

async function 함수(){
...
await 함수 // 오래 걸릴 수 있는 함수에 await을 추가
}
async function init() { // init함수 안에서 비동기 처리를 할 것이므로 init 함수 선언 앞부분에 async를 붙입니다.
                  // 자료를 가져오는데 시간이 얼마나 걸리든지 자료 가져오기가 끝난 후 넘어가도록 설정
  const response = await fetch("https://jsonplaceholder.typicode.com/users");  // fetch 함수는 네트워크를 통해 서버에서 가져오기 
  const users = await response.json();  // 서버에서 가져온 프라미스 객체를 users에 저장 
  console.log(users);  // users 표시
}

init();

 

4. 노드의 모듈

노드에서는 대부분의 기능을 모듈이라는 단위로 나누어서 작성합니다. 모듈은 기능별로 나누어 놓은 함수입니다.

노드에서는 require 함수를 통해 모듈을 사용해왔는데 이것을 CommonJS 모듈 시스템이라고 합니다. 이후에는 에크마스크립트가 발전하면서 모듈을 처리하는 표준이 정해졌는데 노드에서는 이 방식을 에크마스트립트 모듈 시스템 혹은 ES 모듈 시스템이라고 합니다. 최신 문법이나 타입스크립트를 사용한다면 ES 모듈 시스템을 선택할 수 있습니다. 노드의 공식 문서에서 CJS와 ESM이 CommonJS 모듈과  ES 모듈 시스템을 가리킵니다.

 

4.1 모듈 내보내기 - modul.exports

모듈을 외부로 내보내는 것을 흔히 익스포트한다고 합니다.

module.exports = 외부로 내보낼 함수 또는 변수

모듈에서 함수를 정의할 때 맨 앞에 exports를 붙여서 함수를 직접 내보낼 수도 있습니다.

const user = "홍길동";
module.exports = user;

exports.hello = (name) =>{
  console.log('${name}님, 안녕하세요?');
};

module.exports = hello;

 

여러 개 변수를 내보낼 경우에는 {}로 묶어서 객체 형태로 내보냅니다.

// user.js
const user1 = "Kim";
const user2 = "Lee";
const user3 = "Choi";

module.exports = {user1,user2}


// test.js
const users = require("./users-1");
const hello = require("./hello");

hello(users.user1);

 

4.2 모듈 가져오기- require 함수

CommonJS 모듈 시스템에서 모듈을 가져올 때는 require 함수를 사용합니다. require()괄호 안에 모듈 파일의 경로를 지정하면 됩니다. 모듈을 가져와서 사용하는 것을 임포트한다고 합니다. 모듈을 가져올 때에는 모듈 파일의 경로를 상대 경로로 지정한다는 점에 주의하세요. 이때 가져오는 모듈의 확장자인 .js는 생략할 수 있습니다.

require("모듈 파일 경로")
const user = require("./user");
const hello = require("./hello");

hello(user);

 

5. 노드의 코어 모듈

노드에는 백엔드 개발에 필요한 모듈이 이미 내장된 코어 모듈이 존재합니다. 자세한 노드에서 지원하는 코어 모듈은 노드 공식 웹 사이트를 참고하세요. https://nodejs.org/docs/latest/api/assert.html

 

Assert | Node.js v21.6.1 Documentation

Assert# Source Code: lib/assert.js The node:assert module provides a set of assertion functions for verifying invariants. Strict assertion mode# In strict assertion mode, non-strict methods behave like their corresponding strict methods. For example, asser

nodejs.org

const fs = require("node:fs");
기능 모듈명 설명
파일 시스템 fs 파일이나 폴더에 접근할  수 있는 기능을 제공합니다. 예를 들어 파일 일기/쓰기/삭제 이동/이름 변경이나 폴더 작업을 처리
HTTP http HTTP 서버를 만들고 요청을 처리하는 기능을 제공합니다. 
경로 path 파일 경로와 관련된 작업을 하는 기능을 제공합니다. 예를 들어 파일 경로를 지정하거나 상대 경로를 계산하는 작업을 할 수 있습니다.
스트림 streams 데이터 스트림을 처리하는 기능을 제공합니다. 예를 들어 파일 경로를 지정하거나 상대 경로를 계산하는 작업을 할 수 있습니다.
암호화 crypto 암호화와 관련된 기능을 제공합니다. 해시함수, 암호화 알고리즘, 암호화 및 복호화 등을 지원합니다.
운영체제 os 운영체제와 상호 작용하는 기능을 제공합니다. 예를 들어 운영체제의 정보를 알아내거나 시스템 리소스 정보를 확인할 수 있습니다.
유틸리티 util 다양한 유틸리티 함수를 제공합니다. 예를 들어 객체 상속, 비동기 처리를 프라미스로 변환하는 등의 작업을 할 수 있습니다.
이벤트 event 이벤트 기반 프로그래밍을 지원하는 기능을 제공합니다. 이벤트 생성, 등록,처리 등을 할 수 있으며, 커스텀 이벤트를 사용하여 비동기 처리를 할 수 있습니다.

2022년 발표한 노드 18.0.0 이후 버전부터 코어 모듈을 가져올 때는 node:라는 접두사를 붙여서 가져오려는 모듈이 코어 모듈이라는 사실을 명확하게 보여 줄 수 있게 했습니다.

6. 노드의 글로벌 모듈

require 함수 없이 그대로 사용할 수 있는 모듈을 글로벌 모듈이라고 합니다.  글로벌 모듈에 있는 변수나 함수는 코드를 작성할 떄 따로 가져오지 않고 바로 사용합니다. 앞서 사용한 require함수 역시 글로벌 모듈에 포함되어 있습니다. 

글로벌 모듈에 있는 객체를 글로벌 객체라고 합니다. 글로벌 객체는 global이라는 모듈에 포함되어 있는데 코드 어디에서나 사용할 수 있어서 global이라는 모듈 이름을 빼고 간단히 줄여서 사용합니다.

global.console.log(`${값}`)  또는 console.log(`${값}`);

 

예시) 타이머 함수 : setTimeout , seTInterval, clearlnterval

프런트엔드 개발에서 자주 사용하는 자바스크립트 함수인 setTimeout이나 setInterval, clearInterval 같은 함수도 노드에서 글로벌 객체로 사용할 수 있습니다. 

* setTimeout 함수는 지정한 시간이 지난 후에 함수 내용을 실행, setInterval 함수는 지정한 시간마다 함수 안의 내용을 실행, clearInterval 함수는  setInterval 함수 반복 실행하던 것을 멈춤

 

7. ES 모듈 시스템

노드 13.2.0 이후 버전부터는 ES 모듈 시스템을 공식으로 지원합니다. 하지만 노드는 CommonJS 모듈 시스템을 기반으로 해서 만들었으므로 ES모듈 시스템을 사용하려면 ES 모듈 시스템에 맞게 설정해야 합니다.

 

ES 모듈 시스템을 사용하는 2가지 방법

방법1: package.json에 모듈 추가하기

애플리케이션을 개발할 때 애플리케이션 전체에서 ES 모듈 시스템을 사용한다면 그에 필요한 항목을 package.json 파일에 추가하면 됩니다. 

"type" : "module" 

단 package.json에서 ES모듈을 사용하겠다고 설정한 후에 CommonJS 모듈 시스템을 사용하면 오류가 발생합니다. 

 

방법2: 파일 확장자를 .mjs로 지정하기

CommonJS 모듈 시스템과 ES 모듈 시스템을 모두 사용해서 애플리케이션을 개발한다면 package.json 파일을 수정해서는 안 됩니다. 그 대신 ES 모듈 시스템을 사용하는 파일의 확장자를 .js가 아닌 .mjs로  지정하면 됩니다. 그리고 애플리케이션을 실행할 때도 .mjs 확장자를 붙여서 실행합니다. 

 

ES 모듈 시스템에서 모듈 내보내기 : export, export default

ES 모듈 시스템에서 모듈을 내보낼 때는 export 예약어를 사용합니다. 이 때 변수나 함수 앞에 export를 붙일 수도 있고 모듈 끝에 export를 사용해서 내보낼 수도 있습니다.

export 대상
export default 대상
export {대상1, 대상2 ..}

방법1: 하나씩 내보내기(export 붙이기)

모듈에 있는 함수나 변수, 객체 가운데 외부에서 사용할 수 있게 할 대상 앞에 export를 붙여 줍니다.

export const goodbye = (name) => { // export 변수타입 대상
  console.log(`${name}님, 안녕히 가세요.`);
};

 

방법2: 기본으로 내보내기(export default)

모듈에서 내보낼 대상이 하나뿐이라면 앞에 export를 붙여도 되지만 모듈 코드 마지막에서 export default를 사용할 수도 있습니다.

const goodbye = (name) => {
  console.log(`${name}님, 안녕히 가세요.`);
};

export default goodbye;

 

방법3: 여러 개 내보내기

모듈에서 여러 개를 내보낼 때는 객체로 묶어야 합니다. 이때 default를 붙이지 않습니다.

const hi = (name) => {
  console.log(`${name}님, 안녕하세요?`);
};

const goodbye = (name) => {
  console.log(`${name}님, 안녕히 가세요.`);
};

export { hi, goodbye }; // 한꺼번에 묶어서 객체 형태로 내보냄

 

ES 모듈 시스템에서 모듈 가져오기

방법1) import ~ from

ES 모듈 시스템에서 모듈 가져올 떄는 import와 from을 사용합니다. 이때 import 다음에 어떤 이름으로 받을 지 지정하는데대부분 원래 모듈에서 지정한 이름과 똑같이 사용하면 됩니다. 그리고 from 뒤에는 가져올 모듈 파일의 이름을 지정합니다.

import 변수명/함수명 from 모듈_파일
import { hi, goodbye } from "./greeting.mjs"; //가져올 값이 객체 하나라서 {}을 생략

hi("홍길동");
goodbye("홍길동");

노드에서는 mjs 파일을 통해 ES 모듈 시스템을 사영하므로 파일 확장자까지 적어야 합니다.

 

방법2)import ~ as

import문에서 as 예약어를 함께 사용하면 가져오는 함수나 변수의 이름을 바꿔서 받을 수 있습니다. 

import { hi as hello, goodbye as bye } from "./greeting.mjs";
// hi 가져온 값, hello 바꿀 값
// goodbye 가져온 값, bye 바꿀 값

hello("홍길동");
bye("홍길동");

 

모듈에서 가져와야 할 값이 너무 많다면 * 기호를 사용해 모듈 안에 있는 모든 함수를 불러올 수도 있습니다. 

import * as say from "./greeting.mjs"; // *으로 가져올 이름들을 대체하여 모두 say로 통일함

say.hi("홍길동");
say.goodbye("홍길동");

 

 

만일 모듈에서 여러 함수나 변수를 묶어서 내보낼 떄 default를 붙였다면 이것은 객체 1개를 내보낸 것으로 간주해서 *as 없이 객체 이름을 가져올 수 있습니다.

// 내보내기
const hi = (name) => {
  console.log(`${name}님, 안녕하세요?`);
};

const goodbye = (name) => {
  console.log(`${name}님, 안녕히 가세요.`);
};

export default { hi, goodbye };


// 가져오기
// import * as say from "./greeting.mjs";원래 이거지만 * as를 생략함
import say from "./greeting-2.mjs";

say.hi("홍길동");
say.goodbye("홍길동");

 

위 내용은 DO IT Node.JS 입문 책을 참고하여 작성되었습니다.