반응형

Node.js에서 다른 디렉토리에 있는 모듈을 불러올 때는 상대 경로 설정과 절대 경로를 설정하는 두 가지 방식이 있다.

 

1. 폴더 구조


폴더와 파일 구조가 다음과 같을 때, auth.js와 index.js에서 user.js에 정의된 User를 불러오는 방법에 대해 알아보자.

  • model/user.js : DB 스키마, User 모델 정의
  • middleware/auth.js : 로그인 인증 미들웨어
  • middleware/admin.js : 관리자 권한 체크 미들웨어
  • index.js : 서버 실행 및 라우팅 진입점

 

2. user.js에서 User 모델 export하기


const mongoose = require("mongoose");

const userSchema = new mongoose.Schema({
  email: String,
  password: String,
  role: { type: Number, default: 0 } // 0: 일반, 1: 관리자
});

const User = mongoose.model("User", userSchema);

// 다른 파일에서 require 할 수 있도록 export
module.exports = User;
  • module.exports = User; 로 내보내면 require() 로 그대로 불러올 수 있다.

 

3. 상대경로(require)로 불러오기


(1) auth.js 파일에서 User 불러오기

const User = require("../model/user");
  • ..는 현재 middleware 폴더에서 상위 디렉토리(project/)로 이동하는 것을 의미한다.
  • 그 다음 model/user.js로 접근한다.

 

(2) index.js 파일에서 User 불러오기

const User = require("./model/user");
  • index.js 기준 같은 경로(./)의 model 폴더를 찾는다.
🔖
./file → 현재 디렉토리 기준
../file → 상위 디렉토리 기준

 

4. 절대경로로 불러오기


상대경로는 편리하지만, 깊은 디렉토리 구조에서는 ../../../model/user와 같이 의미파악에 어려움이 있을 수 있다. 이런 경우는 절대경로를 써서 가독성을 높인다.

(1) Node 기본 절대경로

const User = require("/Users/yourname/project/model/user");
  • 루트 디렉토리부터 절대경로로 지정한다.
  • PC환경마다 루트가 다르기 때문에 프로젝트에서는 잘 쓰이지 않는다.

(2) path 모듈 활용

const path = require("path");
const User = require(path.resolve(__dirname, "../model/user"));
  • __dirname → 현재 파일이 위치한 디렉토리 절대경로이다.
  • path.resolve() 로 항상 절대경로를 얻을 수 있다.

반응형
반응형

express를 사용하려면 Node.js가 설치되어 있어야 한다. npm 5.0+ 버전에서는 npm 설치를 하면 package.json 파일의 dependencies에 모듈을 자동으로 추가한다. 이전 버전에서는 npm install (module) --save 옵션을 명시적으로 지정해야 dependencies에 모듈이 자동으로 추가된다.

node -v // 노드 설치 확인

mkdir react-blog // 폴더 생성

npm init // package.json 파일 생성

npm install express
npm install nodemon --save-dev

package.json 파일은 Node.js 프로젝트에 필요한 것을 담고 있으며, 패키지 설치, 빌드, 실행 등에서 중요한 역할을 한다.

Express.js는 웹 프레임워크이다. 특징을 살펴보자.

  • 웹이나 모바일 앱을 만들 때 필요한 기본 기능을 안정적으로 제공한다.
  • HTTP 메서드를 다루는 다양한 유틸리티 메서드가 있어서 API를 쉽고 빠르게 만들 수 있다.
  • 미들웨어를 조합해서 인증, 로깅, 요청 데이터 파싱 등 기능을 손쉽게 추가할 수 있다.
  • Node.js 위에서 작동해서 네이티브 기능을 가리지 않고 그대로 사용할 수 있다. (오버헤드가 적음)
  • 미들웨어
    • Express의 핵심은 최소한의 기능만 갖추고, 미들웨어로 확장하는 방식이다.
    • 미들웨어는 요청과 응답 사이에 필요한 작업을 하는 함수인데, 자유롭게 조합이 가능하다.

🔍 express 기본 코드

const express = require('express');
const app = express();
const port = 5000;

// GET method route
app.get('/', (req, res) => {
    res.send('GET request to the homepage')
});

// POST method route
app.post('/', (req, res) => {
    res.send('POST request to the homepage')
});

app.listen(port, () => {
    console.log(`Server is running on ${port}`) // `(backtick): ES6 표준 문법, 변수 작성 시 사용
});
반응형
반응형

🤔 require()에 대해 알아보자

require()는 Node.js에서 외부 모듈(라이브러리), 로컬 파일, JSON 데이터 등을 불러올 때 사용하는 함수이다. Node.js는 기본적으로 CommonJS 모듈 시스템을 따르며, require()는 해당 방식의 대표적인 모듈 호출 방법이다.

 

🔍 코드 분석

index.js의 코드를 살펴보자.

const express = require('express'); // Express 모듈 사용
const app = express(); // app이라는 새로운 Express 앱 만듦

const mongoose = require('mongoose'); // Mongoose ODM 모듈 불러오기
const bodyParser = require('body-parser'); // HTTP 요청 본문(body) 파싱하는 미들웨어 불러오기
const cookieParser = require('cookie-parser'); // 쿠키를 읽고 파싱하는 미들웨어 불러오기

이 코드에서 사용하는 모든 모듈은 node_modules 폴더에 설치되어 있어야 하며, require()는 해당 경로부터 모듈을 탐색한다.

require()는 Node.js가 내부적으로 node_modules 폴더부터 탐색한다.
예: node_modules/express/index.js 등

📁 Node.js가 모듈을 찾는 순서

예를 들어 require('express')를 실행하면 Node.js는 다음 순서로 파일을 찾는다.

  1. node_modules/express/index.js
  2. node_modules/express/package.json → main 항목 확인
  3. node_modules/express/index.json or .node (특수 바이너리)
  4. 못 찾으면 에러 발생 (MODULE_NOT_FOUND)

 

🤔 import 방식에 대해 알아보자

import는 ES6에서 도입된 ESM 시스템의 문법이다. Node.js는 원래 CommonJS 기반이지만, 현재는 ESM도 공식적으로 지원하고 있다.

🔍 코드 분석

ESM 방식은 정적으로 모듈을 불러오며, 모듈 구조를 컴파일 시점에 분석할 수 있다는 장점이 있다. 브라우저와 호환성이 좋아, TypeScript, React, Next.js 등에서 주로 사용한다.

import express from 'express';

Node.js에서 ESM을 사용하려면 다음 중 하나의 설정이 필요하다.

  1. package.json"type": "module" 설정
  2. 파일 확장자를 .mjs로 변경

 

🧠 What I Learned

Node.js에서 처음으로 require()를 사용하면서 단순히 모듈을 불러오는 방식이라고만 생각하며 import와는 어떤 차이점이 있는지 궁금했다.
이번 정리를 통해 Node.js가 기본적으로 CommonJS를 기반으로 작동한다는 점, 그리고 ES6 이후 등장한 import 방식은 정적 로딩을 기반으로 하며 별도의 설정이 필요하다는 점을 알았다.

반응형
반응형

리액트 프로젝트를 클론한 후 로컬에서 실행하려고 npm start 명령어를 입력하면서 문득 npm startnpm run start 명령어가 같은 의미인지 궁금해졌다.

자바스크립트 프로젝트에서 개발을 하다 보면, 로컬 서버 실행, 테스트, 빌드 등 반복 작업을 위해 터미널에서 명령어를 자주 입력하게 된다. 이런 작업들을 스크립트로 등록해 두면 훨씬 편리하다.

이번 글에서는 npm startnpm run start의 차이를 살펴보고, 자주 사용하는 반복 작업을 어떻게 스크립트로 등록하고 실행하는지도 함께 정리해 보자.

🤔 npm start vs npm run start

결론부터 말하면 npm startnpm run start의 축약형이다. npm start는 package.json 파일의 scripts 항목 중 "start"에 정의된 명령어를 실행한다. npm run start도 동일한 방식으로 동작한다.

⚠️ "start"는 특별한 예약어라 npm run을 생략할 수 있지만, "build", "test", "dev" 등 다른 스크립트는 반드시 npm run <스크립트명> 형태로 실행해야 한다.

🛠️ 스크립트를 등록하는 이유

리액트 프로젝트뿐 아니라 대부분의 프런트엔드/백엔드 자바스크립트 프로젝트는 다양한 CLI 명령어를 사용한다.

  • 테스트: jest, vitest, mocha
  • 빌드: webpack, vite, parcel
  • 린트: eslint
  • 포맷팅: prettier

이 명령어들을 매번 정확하게 기억하는 것은 어렵기 때문에, 반복적으로 수행하는 동작에 대해 package.json에 스크립트로 등록해 두면 간단한 명령어로 편리하게 사용할 수 있다.

🗂️ 스크립트 등록 방법

Node.js 프로젝트의 package.json에 scripts 항목이 있는데, 해당 부분에서 직접 편집하거나 명령어를 입력하여 등록하는 방법이 있다.

  1. package.json을 열고 직접 편집
  2. npm pkg set scripts.{스크립트 이름}={명령어} 명령어 입력
$ npm pkg set scripts.hi "echo 'HI!'"

file : package.json

{
    // 생략
    "scripts": {
        "hi": "echo 'Hi!'"  
        "start": "react-scripts start"
    },
    // 생략
}

🧠 스크립트 실행 방법

스크립트 등록을 마치면 npm run <스크립트 이름> 명령어를 입력하여 실행할 수 있다.

$ npm run hi

> our-project@1.0.0 hi
> echo 'Hi!'

Hi!

npm start도 이 방식으로 동작하는 것이며, 단지 "start"만 예외적으로 run 생략이 가능하다.

🧩 보너스: 자주 쓰는 스크립트 예시

package.json 파일에 다음과 같이 등록해 두면 터미널에서 짧은 명령으로 실행할 수 있어 편리하다.

"scripts": {
  "start": "react-scripts start",
  "build": "react-scripts build",
  "test": "react-scripts test",
  "lint": "eslint .",
  "format": "prettier --write ."
}
$ npm start       # 개발 서버 실행
$ npm run build   # 빌드
$ npm run test    # 테스트
$ npm run lint    # 린트
$ npm run format  # 코드 포맷팅
반응형
반응형

자료형

자료형과 원시 자료형

자료형이란 값의 성질에 따라 분류한 것이다.

자바스크립트는 자료형을 크게 원시 또는 객체 자료형으로 나누고, 작게는 8개의 세부 자료형으로 나눈다.

원시 자료형의 종류
원시 자료형을 원시 타입 또는 기본 타입이라고 한다. 원시 자료형은 한 번에 단 하나의 값만 가질 수 있는 타입이다.

 

  1. 숫자형
    • 숫자형은 수의 종류를 구분하지 않는다.
    • 소수, 음수, 실수와 같은 수를 모두 포함하는 자료형이다.
    • 숫자형에는 정수, 실수 말고도 일반적이지 않은 값들이 있다.
      • Infinity, -Infinity : 최솟값이나 최댓값을 구할 때 주로 사용한다. Infinity는 0으로 어떤 수를 나눈 결과이기도 하다.
      • NaN : Not a Number이라는 뜻으로 불가능한 숫자형의 결과를 표현할 때 사용하는 값이다. 숫자와 문자열을 곱하면 정상적인 연산의 결과물이 나올 수 없으므로 NaN이라는 값을 얻는다.
      • let inf = Infinity;
      • let minf = -Infinity;
      • let nan = NaN;
/* 사칙 연산 */
console.log(1 + 2); // 3
console.log(1 * 2); // 2
console.log(1 - 2); // -1
console.log(1 / 2); // 0.5

/* 모듈러 연산 */
console.log(1 % 2); // 1
console.log(1 / 0); // Infinity

 

  1. 문자형
    • 문자열을 포함하는 자료형이다.
    • 어떤 값이 문자형이라는 것을 알리기 위해 큰따옴표("") 또는 작은따옴표('')로 감싸야한다.
    • 백틱(``)을 이용해도 문자형을 만들 수 있다.
let name = '이정환';
let location = "역곡";
let introduce = `${name}은 ${location}에 살고 있습니다`;

console.log(introduce); // 이정환은 역곡에 살고 있습니다

 

  1. 불리언, null, undefined
    • 불리언 형은 작업을 성공적으로 종료했는지, 어떤 값이 있는지 등을 확인할 때 유용하게 사용한다.
    • null은 "아무것도 없다"라는 뜻으로 변수에 아무 값도 할당할 필요가 없을 때 사용한다. 대다수 프로그래밍 언어에서 null은 하나의 값으로 단순하게 취급하지만, 자바스크립트에서는 독립적인 자료형으로 분류한다.
    • undefined는 '미정의 값'이라는 뜻이다. C나 자바 언어에서는 변수를 생성하고 아무런 값도 할당하지 않으면 null을 갖지만, 자바스크립트에서는 null 대신 undefined를 가지게 된다.
et emptyVar = null;

console.log(emptyVar); // null

let realEmptyVar;

console.log(realEmptyVar); // undefined

 

 

형 변환

어떤 값의 자료형을 다른 자료형으로 변환하는 것을 '형 변환'이라고 한다.

다른 자료형끼리 서로 연산한다는 가정해 보자. 숫자와 문자를 서로 더하는 연산이라면, 프로그래밍에서는 먼저 숫자를 문자로 변환하고 나서 문자와 문자를 이어 붙이는 연산을 수행한다. 숫자를 문자로 변환하는 것처럼 서로 같은 자료형으로 만드는 작업이 선행되어야 연산이 정상적으로 이루어지기 때문이다.

  1. 묵시적 형 변환
    자바스크립트 엔진이 스스로 알아서 변환하는 작업이다. 2번째 예시에서 숫자와 문자의 덧셈에서 자바스크립트가 암묵적으로 숫자를 문자로 형 변환해 계산했기 때문에 문자형 간의 덧셈 연산은 두 문자를 이어 붙인 결과가 되었다.
let number = 10;
let string = 20;
const result = number + string;

console.log(result); // 30
let number = 10;
let string = "20";
const result = number + string;

console.log(result); // 1020

 

  1. 명시적 형 변환
    묵시적 형 변환과 반대로 내장 함수 등을 이용해 프로그래머가 의도적으로 어떤 자료형을 다른 자료형으로 변경하는 작업이다.
  • 숫자형으로 변환
let strA = "10";
let strB = "10개";

let numA = Number(strA);
let numB = Number(strB);

console.log(numA); // 10
console.log(numB); // NaN

함수 Number는 자바스크립트가 기본적으로 제공하는 내장 함수로, 제공된 문자열을 숫자로 변환해 반환한다. 변수 strB처럼 숫자가 아닌 문자를 포함한 문자열은 정상적으로 변환되지 않기 때문에 NaN을 반환한다.

숫자뿐만 아니라 문자도 함께 포함된 문자열을 숫자로 변환하고 싶다면, 함수 parseInt를 사용한다.

Parameter Description
value Required.
The value to be parsed.
radix Optional. Default is 10.
A number (2 to 36) specifying the number system.

* radix parameter specifies the number system to use: 2 = binary, 8 = octal, 10 = decimal, 16 = hexadecimal

let strA = "10";
let strB = "10개";

let numA = parseInt(strA, 10);
let numB = parseInt(strB, 10);

console.log(numA); // 10
console.log(numB); // 10

함수 parseInt는 Number처럼 괄호 안에 있는 문자열을 숫자로 변환하는 자바스크립트의 내장 함수이다. Number와 달리 괄호 안에 두 개의 값을 콤마로 구분해 전달하는데, 첫 번째 값은 변환하려는 문자열이고, 두 번째 값은 진수이다.

Caution 함수 parseInt가 동작할 때는 문자열의 첫 문자부터 숫자로 변환하므로, 문자열이 숫자가 아닌 문자로 시작한다면 NaN을 반환한다.

let str = "파이팅 2023";
let num = parseInt(str, 10);

console.log(num); // NaN

 

  • 문자열로 변환
let num = 2022;
let str = String(num);

console.log(str); // 2022

변수 num에 저장된 숫자 2022를 함수 String을 이용해 문자열로 변환한다. String 역시 자바스크립트 내장 함수로 인수로 제공된 값을 문자열로 변환해 반환한다.

let varA;
let varB = null;
let varC = true;

let strA = String(varA);
let strB = String(varB);
let strC = String(varC);

console.log(strA); // undefined
console.log(strB); // null
console.log(strC); // true

undefined 값은 문자열 undefined, null 값은 문자열 null, true 값은 문자열 true로 변환된다.

 

  • 불리언으로 변환
let varA = "하이";
let varB = 0;
let varC = ""; // ""는 값이 없기 때문에 Falsy 값으로 간주되어 false를 반환

let boolA = Boolean(varA);
let boolB = Boolean(varB);
let boolC = Boolean(varC);

console.log(boolA); // true
console.log(boolB); // false
console.log(boolC); //

console.log("boolC:", boolC); // boolC: false

console.log(boolC);를 실행하니 콘솔에 아무것도 없는 것처럼 느껴져서 console.log("boolC:", boolC);를 한 줄 추가해서 다시 결과를 확인하니 false로 나오는 것을 확인했다.

 

📌 기억할 것

`a++`처럼 증감 연산자를 변수 `a` 뒤에 두면, 증감 연산의 결과는 연산자가 있는 다음 행부터 반영된다. 
피연산자인 변수 뒤에 증감 연산자를 두는 것을 '후위 연산'이라고 하며, 이 연산의 결과는 다음 행부터 적용된다는 특징이 있다.
만일 증감 연산을 작성한 행에서 반영하고 싶다면 증감 연산자를 변수 앞에 두면 된다.

반응형
반응형

웹 에디터로 자바스크립트 편집하기

자바스크립트는 어떻게 실행될까?

자바스크립트는 '자바스크립트 엔진'이라는 프로그램이 해석해 실행한다. 자바스크립트 엔진 기본적으로 웹 브라우저에 탑재되어 있다. Node.js와 같은 별도의 실행 환경을 설치하지 않는 한, 자바스크립트를 실행하려면 반드시 웹 브라우저가 있어야 한다.

크롬처럼 자바스크립트 엔진을 사용하면서도 여러 줄에 걸쳐 코드를 입력하고 편집할 수 있는 웹 에디터인 '코드샌드박스'를 활용하여 실습을 진행해 보자.

코드샌드박스 사용 방법

크롬처럼 자바스크립트 엔진을 사용하면서도 여러 줄에 걸쳐 코드를 입력하고 편집할 수 있는 웹 에디터이다. 코드샌드박스는 샌드박스 단위로 웹 언어를 입력하고 편집할 수 있는 웹 에디터이다.

크롬 브라우저에서 다음 주소를 입력한다.
https://codesandbox.io

사이트에 접속하면 Try for free 혹은 Start for free 버튼을 클릭한다.

자바스크립트를 선택한다.

Open template를 클릭한다.

자바스크립트를 실습할 수 있는 샌드박스 페이지이다.
샌드박스 페이지는 크게 3개의 창으로 구성되어 있다. 가장 왼쪽에는 파일 탐색, 검색 등 제어기능을 모아 놓은 공간이다. 가운데 창은 코드를 작성하는 에디터 공간이다. 오른쪽 창은 결과물을 브라우저나 콘솔에서 확인하는 공간이다.

실습 환경이 갖춰졌으니 변수와 상수에 대해 알아보자.

변수와 상수

변수

변수란 프로그램을 실행하는 과정에서 변경될 수 있는 값을 저장하는 저장소이다. 어떤 값을 이름으로 가리킬 때 사용하는 기능이기도 하다.

키워드 let : let age = 25;
코드를 입력하면 25라는 값은 이제부터 age라는 이름으로 부를 수 있다. 키워드 let을 붙여 없던 변수를 만들면 "변수를 선언한다"라고 하며, age = 25처럼 값을 변수에 지정하면 '할당한다'라고 표현한다.
변수를 선언함과 동시에 값을 할당할 수도 있는데, 이것은 "변수를 초기화한다"라고 한다. 자바스크립트에서 변수의 초기화는 선택 사항이다.

키워드 var : var age = 25;
var를 이용한 변수 선언은 let과 달리 이름을 중복해 선언해도 실행할 수 있다. 가급적 변수 선언 키워드로는 let을 사용한다.

상수

상수 역시 변수처럼 이름을 가진 공간이다. 그러나 변수와 달리 프로그램 실행 과정에서 값을 변경할 수 없다.

키워드 const : const age = 25;
선언과 동시에 할당하는 초기화 과정이 필요치 않은 변수와 달리, 상수는 선언과 동시에 값을 할당하는 과정이 꼭 필요하다.

명명 규칙

  1. 기호 사용 규칙
    • 변수의 이름에는 한글을 포함하여 문자, 숫자 그리고 특수 기호의 일부(_, $)를 사용할 수 있다.
    • 특수 기호 _: 두 단어 이상으로 이루어진 합성어일 때 가독성을 높이기 위해 사용.
    • 특수 기호 $: jQuery를 사용할 때처럼 이 변수가 별도의 라이브러리 객체라는 것을 가리킬 때 사용.
  2. 숫자 사용 규칙
    • 변수 이름으로 숫자를 사용할 수 있지만, 숫자로 시작해서는 안 된다.
    • let 2022year = "good"; (X)
    • let _2022year = "good"; (O)
  3. 예약어 규칙
    • let, const 키워드처럼 예약어란 자바스크립트에서 이미 사용하기로 약속한 단어이다. 따라서 예약어는 변수명으로 사용할 수 없다.
    • https://www.w3schools.com/js/js_reserved.asp
  4. 대•소문자 구별
    • 위 3가지 규칙과 달리 대•소문자를 구별하는 명명 규칙은 직접적인 오류가 발생하지는 않는다.
    • 하지만 이 규칙을 인지하지 못한 상황에서 아래와 같이 변수의 이름을 짓게 되면, 의도치 않은 오류가 발생할 수 있다.
let code = 1;
let Code = 2;

console.log(code); // 1
console.log(Code); // 2
반응형

+ Recent posts