생각보다 사용방법이 어렵다 느껴 간단하게 정리해보고자 합니다.

 

Multer는 파일 업로드를 처리하는 미들웨어 입니다.

특히 multipart/form-data를 처리하는데 사용하고, 파일을 디스크 또는 메모리에 저장할 수 있습니다.

 

기본개념

multer를 사용하면 클라이언트라 form-data로 업로드한 파일을 서버에서 처리하고 저장할 수 있습니다.

 

storage: 파일 저장 방식(디스크 저장 or 메모리 저장)

destination : 파일이 저장될 폴더 지정

filename : 저장될 파일명 지정 (이름 충돌 방지)

limits : 파일 크기 제한 설정 가능

fileFilter : 특정 파일만 허용 가능 ( ex : 이미지 파일만 허용)

 

const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, cb) {
      cb(null, "uploads/");
    },
    filename(req, file, cb) {
      const ext = path.extname(file.originalname); // 이미지.png => 이미지 (날짜).png    이름중복방지
      cb(null, path.basename(file.originalname, ext) + Date.now() + ext);
		//기존 파일명 + 현재 시간(중복 방지) + 확장자 형태로 저장
    },
  }),
});

 

  1. 파일 저장위치 : uploads/ 폴더에 저장
  2. 파일 이름 처리 : 
    • path.extname(file.originalname)    -> 파일 확장자 추출
    • path.basename(file.originalname, ext)  -> 확장자를 제외한 파일 이름 추출
    • Data.now() 를 추가하여 파일 이름이 중복되지 않도록 합니다
      (여러 사람이 이용하다보면 파일 이름 중복의 가능성이 있습니다)
    • (ex : image.png  -> image62375637545.png) 의 형식으로 저장됩니다.

 


 

Multer의 활용

 

1. 파일 업로드 (single())

<form action="/upload" method="POST" enctype="multipart/form-data">
  <input type="file" name="image" />
  <button type="submit">업로드</button>
</form>

 

app.post("/upload", upload.single("image"), (req, res) => {
  res.json({ file: req.file }); // 업로드된 파일 정보 응답
});

클라이언트가 image라는 이름으로 1개의 파일을 업로드하면 저장됨. (req.file 에 업로드된 파일 정보가 저장됩니다.)

* 여기서 "image"는 form애 있는 input의 name 을 의미합니다.

 

 

2. 다수의 파일 업로드( array() )

<form action="/upload" method="POST" enctype="multipart/form-data">
  <input type="file" name="images" multiple />
  <button type="submit">업로드</button>
</form>

form은 위와 동일 input의 name이 image => images로 변경

app.post("/upload-multiple", upload.array("images", 5), (req, res) => {
  res.json({ files: req.files });
});

images 라는 필드 이름으로 최대 5개의 파일을 업로드 가능

 

 

3. 다수의 필드로 파일 업로드 ( fields() )

<form action="/upload" method="POST" enctype="multipart/form-data">
  <input type="file" name="profile" />
  <input type="file" name="cover" />
  <button type="submit">업로드</button>
</form>
app.post(
  "/upload-fields",
  upload.fields([{ name: "profile", maxCount: 1 }, { name: "cover", maxCount: 5 }]),
  (req, res) => {
    res.json({ profile: req.files.profile, gallery: req.files.cover });
  }
);

profile 최대 업로드 : 1, cover 최대 업로드: 5

 

 

 

4. 파일 필터링 ( 이미지만 허용하는 예시)

<form action="/upload" method="POST" enctype="multipart/form-data">
    <input type="file" name="image" accept="image/*" required />
    <button type="submit">업로드</button>
  </form>
const upload = multer({
  storage: multer.diskStorage({
    destination(req, file, cb) {
      cb(null, "uploads/");
    },
    filename(req, file, cb) {
      const ext = path.extname(file.originalname);
      cb(null, path.basename(file.originalname, ext) + Date.now() + ext);
    },
  }),
  fileFilter(req, file, cb) {
    if (!file.mimetype.startsWith("image/")) {
      return cb(new Error("이미지 파일만 업로드 가능합니다."), false);
    }
    cb(null, true);
  },
});

 

 

accept = "image/*" :  이미지 파일만 선택 가능하도록 제한

required : 파일을 선택하지 않으면 제출 불가능


 

Multer의 파일 처리과정

 

  1. 클라이언트가 form-data로 요청을 보냅니다(POST /upload)
  2. Multer가 요청을 가로채고 파일을 uploads/ 에 저장합니다 (uploads/ 는 예시)
  3. 파일 정보가 req.file 또는 req.files에 저장됩니다.
  4. 라우터에서 req.file을 이용해 응답하거나, db에 저장합니다.

'Node js' 카테고리의 다른 글

passport.js 정리하기  (0) 2025.02.14
mongoDB 에 대하여  (1) 2025.01.25
3. express 미들웨어 정리하기  (3) 2025.01.24
2. 노드의 특성  (0) 2025.01.07
1. Node.js 란?  (0) 2025.01.07

1. passport.js란?

  • passport.js는 Node.js에서 인증을 처리하기 위한 미들웨어로, 다양한 인증 전략을 제공합니다.
    인증을 처리하는 데 필요한 로직을 간단하게 구현할 수 있게 도와줍니다.

2. passport의 흐름

  1. passport.use로 전략 등록하기
    • 인증 전략의 개념 
      • 인증 전략은 사용자가 시스템에 접근하기 위한 인증방법을 정의하는 것 입니다.
        예를들어, 로컬 로그인, 카카오 로그인, 구글 로그인 등이 전략으로 제공됩니다.
    • passport.use 사용법
      • passport.use() 메서드는 인증 전략을 등록하는 함수입니다.
        등록된 전략은 이후 passport.authenticate()로 호출해 사용합니다.
    • 예시
      passport.use(
        new LocalStrategy(
          {
            usernameField: 'email', // 로그인 시 사용할 필드
            passwordField: 'password',
          },
          async (email, password, done) => {
            const user = await User.findOne({ where: { email } });
      	  //유져가 있고, password 와 user.password가 같다면
            if (user && bcrypt.compareSync(password, user.password)) {
              return done(null, user);
            } else {
              return done(null, false, { message: 'Invalid credentials' });
            }
          }
        )
      );

      인자값에 대해 정리를 해보자면,
      1. passport.use(strategy(option, callback));
       - strategy : 사용하고자 하는 인증 전략 (ex : LocalStrategy)
       - option : 전략에 필요한 옵션 설정 (ex : usernameField, passwordFiend, passReqToCallback)
       - callback : 인증을 처리하는 함수, 이 함수에서 done을 호출하여 인증결과를 반환합니다.

      2. callback(username, password, done);  , done(error, user|false, options?)
       - error : 인증 중에 발생한 에러 (에러가 발생하지않으면 null 또는 undefined
       - user : 인증 성공시 인증된 사용자 객체 (없으면 false)
       - options : 인증 실패 시 추가적인 정보 (ex {message : "Invalid credentials"})
  2. passport.authenticate로 인증 요청하기
    • 인증 요청의 과정
      • 사용자가 로그인 폼 형식에 맞춰 제출하면 passport.authenticate가 호출되고, 해당 전략에 맞는 인증 과정이 시작됩니다.
    • passport.authenticate 와 전략 선택
      • passport.authenticate("local")에서 "local"은 등록된 전략의 이름입니다.
      • local 전략이 사용되며 그에 맞는 인증 로직이 실행됩니다.
      • local 의 경우 passport-local 의 LocalStrategy를  kakao의 경우 passport-kakao 입니다.
        passport.authenticate("local") 은  passport.use( new LocalStrategy()) 을 실행
        passport.authenticate("kakao") 은  passport.use( new KakaoStrategy()) 을 실행

      • 저는 여기서 의문이 생겼습니다. authenticate에서 "local"은 어떻게 passport.use( new LocalStrategy())를 찾고 실행하는가 였습니다.
        passport.use("kakao", new KakaoStrategy(...)) , passport.use("local", new LocalStrategy (...)) 처럼
        "kakao"  "local 을 명시적으로 붙이지 않아도, 내부적으로 passport가 전략의 생성자를 보고 자동으로 매칭해주기 떄문이라고 합니다.
  3. serializeUser 로 세션에 사용자 정보 저장하기
    • 세션 관리의 필요성
      • 로그인한 사용자의 정보를 세션에 저장하여, 사용자가 로그인을 유지하고 인증된 상태를 지속적으로 사용할 수 있도록 합니다.
    • serializeUser의 역할과 사용법
      • serializeUser 는 로그인 한 사용자 정보를 세션에 저장할 떄 사용합니다. 
      • 보통 사용자 id만 저장하며, 이 정보는 deserializeUser 에서 사용합니다.
      • passport.serializeUser((user, done) => {
          done(null, user.id); // 사용자 정보를 세션에 저장
        });
        passport.use 에서의 callback이 가지고 있는 done과 흡사합니다.
        passport.use는 인증 시도 및 실패 처리가 이뤄지는 반면  serializeUser 에서는 인증이 성공한 후에 세션에 저장하는 과정이므로 실패 관련 정보가 없습니다.
        그렇기 때문에  user | false , option 이 없습니다.
  4. deserializeUser 를 이용해서 세션에서 사용자 정보 조회하기
    • 세션을 통한 인증 유지
      • 세션에 저장된 사용자 정보를 기반으로 인증된 상태를 유지합니다. 세션이 만료되거나 사용자가 로그아웃할때  까지 세션 정보를 참조합니다.
    • deserializeUser의 역할과 사용법
      • deserializeUser는 serializeUser를 통해 저장된 사용자 ID를 조회하여 실제 사용자 정보를 데이터베이스에서 가져옵니다. 로그인 후 매 요청시마다 호출되어 사용자 정보를 불러옵니다.
      • passport.deserializeUser((id, done) => {
            User.findOne({ where: { id } })
              .then((user) => done(null, user))
              .catch((err) => done(err));
          });


3. 결론

  • passport.js를 사용하면 전략을 등록하고 인증을 처리한 후, 세션을 이용해 인증된 사용자를 관리할 수 있습니다.
    • 세션을 통해 인증을 유지하며 serializeUser , deserializeUser를 사용하여 사용자정보를 효율적으로 관리합니다.
  • 전략 등록부터 인증까지의 전체 흐름
    • 전략 등록(passport.use)  -> 인증 요청(passport.authenticate) -> 세션 저장(serializeUser) -> 세션 조회 (deserializeUser) -> 인증유지

'Node js' 카테고리의 다른 글

파일 업로드 처리 (Multer)  (0) 2025.02.17
mongoDB 에 대하여  (1) 2025.01.25
3. express 미들웨어 정리하기  (3) 2025.01.24
2. 노드의 특성  (0) 2025.01.07
1. Node.js 란?  (0) 2025.01.07

1. mongoDB

mongoDB는 NoSQL 데이터베이스이고, 그  구조와 사용법이 JSON 형식과 유사하게 설계되어있습니다.

 

2.mongoDB와 JavaScript의 관계

 

1. JSON 과 BSON : mongoDB는 데이터를 JSON과 비슷한 BSON 형식으로 저장합니다.

자바스크립트 개발자에게는 친숙하게 느낄 수 있습니다.

 

2. JavaScript 기반 쿼리 : mongoDb의 셸에서 쿼리는 JavaScript 구문을 기반으로 작성합니다.

JavaScript 를 사용하는 것처럼 데이터를 조회하고, 조작할 수 있습니다.

 

3. Node.js와의 호환성 : mongoDB는 Node.js와 잘 어울리는 라이브러리(mongoose, mogodb)나 패키지를 제공하여 JavaScript로 쉽게 다룰 수 있습니다.

 

3. mongoDB의 NoSQL 에 대해

 

NoSQL의 특징

  • 관계형 데이터베이스(RDBMS)처럼 고정된 테이블 구조가 없습니다.
  • 데이터를 도큐먼트(document)로 저장하며, 각 도큐먼트는 키-값 쌍으로 구성됩니다.
  • 스키마가 유연하여 서로 다른 구조의 데이터를 한 걸렉션에 저장할 수 있습니다.
  • 수평확장(sharding)에 유리하며 대규모 데이터를 처리하기 적합합니다.

 

MySQL 과 NoSQL(몽고디비) 비교

MySQL NoSQL(몽고디비)
규칙에 맞는 데이터 입력
JOIN 지원
안정성, 일관성
용어(테이블, 로우, 칼럼)
자유로운 데이터 입력
JOIN 미지원 (aggregate로 비슷하게 가능)
확장성, 가용성
용어(컬렉션, 도큐먼트, 필드)

 

비정형 데이터에는 mongoDB가 사용하기 좋다

'Node js' 카테고리의 다른 글

파일 업로드 처리 (Multer)  (0) 2025.02.17
passport.js 정리하기  (0) 2025.02.14
3. express 미들웨어 정리하기  (3) 2025.01.24
2. 노드의 특성  (0) 2025.01.07
1. Node.js 란?  (0) 2025.01.07

express의 미들웨어는 요청과 응답 사이에 위치한 함수로, 주로 요청을 처리하거나. 응답을 수정하는 작업을 합니다.

각 미들웨어는 요청을 처리하고, next()를 호출하여 다음 미들웨어로 넘길지, 응답을 보낼지 결정할 수 있습니다.

 

  • 미들웨어는 app.use()로 설정합니다.
  • 요청이 들어오면 순차적으로 실행되며, 각각의 미들웨어가 요청을 수정하거나 처리합니다.

1. morgan("dev")

app.use(morgan("dev"));

기능

- morgan은 HTTP 요청에 대한 로깅을 처리하는 미들웨어입니다.

dev는 로깅 형식중 하나로, 개발환경에서 요청 URL, HTTP상태 코드, 응답시간을 콘솔에 출력합니다.

 

사용하는 이유

 - 요청과 상태를 쉽게 추적하기위해 사용되며, 요청이 서버에 들어올 때마다 콘솔에 로그가 찍혀 확인할 수 있습니다.

 morgan은 단순히 요청을 로그로 보여주며 next()를 호출하지 않아도 다음 미들웨어로 넘어갑니다.

 

 

2. express.static()

기능

 - 정적 파일 제공,

 - 이 미들웨어는 정적파일(HTML, CSS, 이미지, JavaScript 파일)을 제공하는 미들웨어입니다.

 - 서버에서 제공할 파일들이 특정 폴더에 있을 때, 해당 파일들을 URL 경로에 맞게 자동으로 제공해줍니다.

app.use(express.static(path.join(__dirname, "public")));

( __dirname : 현재 파일의 디렉토리를 의미)

path.join을 통해 디렉토리 안의 public 폴더를 지정하며, 폴더안의 파일을 클라이언트(브라우저)에게 제공할 수 있게 합니다.

 

3. express.json()

app.use(express.json());

 

기능

 - json 데이터를 파싱하는 미들웨어입니다.

클라이언트에서 JSON 형식으로 데이터를 전송하면, JavaScript 객체로 변환하여 req.body에 저장합니다.

 

요청 본문에 JSON 데이터가 있으면 파싱하고, next()를 호출하여 다음 미들웨어로 넘어갑니다.

(직접호출 하지 않아도 자동으로. 호출됨)

 

4. express.urlencoded({extended: boolean})

app.use(express.urlencoded({ extended: false }));

 

기능

 - URL 인코딩 된 폼 데이터를 파싱하는 미들웨어입니다.

false 옵션은 querystring 라이브러리를 사용하여 데이터를 처리합니다.  중첩된 객체나 복잡한 구조는 처리하지 않으며, 일반적인 폼 데이터는 파싱합니다.

(직접호출 하지 않아도 자동으로. 호출됨)

 

HTML 폼을 통해 전송된 데이터를 처리하기 위해 사용하며 사용자가 제출한 폼 데이터를 req.body에서 확인할 수 있습니다.

 


 

express 에서는 미들웨어가 위에서 아래로 순차적으로 실행됩니다. 각 미들웨어가 요청을 처리하거나, 요청을 수정하거나, 응답을 보내며, 그 후  next()가 호출되면 다음 미들웨어로 넘어갑니다. 
단, 정적 파일을 제공하거나 응답을 완료한 미들웨어는 더 이상 다음 미들웨어로 넘어가지 않습니다.

그렇기에 미들웨어의 순서는 매우 중요합니다.

 

'Node js' 카테고리의 다른 글

파일 업로드 처리 (Multer)  (0) 2025.02.17
passport.js 정리하기  (0) 2025.02.14
mongoDB 에 대하여  (1) 2025.01.25
2. 노드의 특성  (0) 2025.01.07
1. Node.js 란?  (0) 2025.01.07

1. 이벤트기반

Node.js는이벤트를 기반으로 동작합니다.

이벤트가 발생했을 때 반응하도록 처리합니다.


2. 흐름

1. 콜백 함수 생성 : 이벤트가 발생했을 때 실행될 콜백 함수를 정의합니다.

2. 이벤트리스너 등록 : 특정 이벤트가 발생시 콜백함수가 실행되도록 이벤트 리스너를 등록합니다.

3. 이벤트 발생 : 이벤트가 발생하면 등록된 이벤트 리스너가 반응하며 지정된 콜백 함수를 실행합니다.

 

 


3. 블로킹과 논블로킹 I/O

Node.js는 기본적으로 비동기적이고 논 블로킹 방식으로 동작하며, 동기적이고 블로킹 방식으로도 동작할 수 있습니다.

  • 비동기(Asynchronous) : 다른 작업의 완료를 기다리지 않고 즉시 작업을 시작합니다.
  • 논블로킹(Non-blocking) : 작업을 실행할 때, 그 작업이 끝날때 까지 대기하지않고 계속해서 실행됩니다.
  • 동기(Synchronous) : 작업이 순차적으로 실행되며, 하나의 작업이 완료되어야 다음 작업을 시작합니다.
  • 블로킹(Blocking) : 작업을 실행할 때, 그 작업이 끝날 떄까지 다른 작업을 멈추거나 대기합니다.

Node.js의 비동기적, 논블로킹에 대해

Node.js는 기본적으로 비동기적이고 논블로킹 방식으로 설계되었습니다. 이것은 I/O 작업을 수행할 때 다른 작업들이 대기하지 않고 계속 실행될 수 있도록 합니다.

 

 

 

'Node js' 카테고리의 다른 글

파일 업로드 처리 (Multer)  (0) 2025.02.17
passport.js 정리하기  (0) 2025.02.14
mongoDB 에 대하여  (1) 2025.01.25
3. express 미들웨어 정리하기  (3) 2025.01.24
1. Node.js 란?  (0) 2025.01.07

1. Node.js란 크롬 V8 JavaScript 엔진으로 빌드된 JavaScript 런타임입니다. (공식 홈페이지)

서버 애플리케이션을 개발할 수 있게 해주는 플랫폼으로, 자바스크립트를 사용하여 서버를 구축할 수 있게 해줍니다.

 

2. Node.js는 내장된 HTTP 서버 라이브러리를 포함하고 있어, Apache와 같은 별도의 웹 서버 소프트웨어 없이도 웹 서버를 구축할 수 있습니다.  따라서 Node.js는 서버 측 애플리케이션을 개발하는 데 사용되는 런타임 환경이며, 서버로서의 역할을 수행합니다.

질문) 노드는 서버가 아닌가?
 - Node.js는 서버 자체가 아니라, 서버를 구축할 수 있는 런타임 환경입니다.  Node.js는 JavaScript사용하여 서버를 개발할 수 있는 플랫폼을 제공합니다. 서버라고 불리는 이유는 Node.js를 이용해 운영되는 서버 애플리케이션입니다.

 

정리하자면
1. Node.js === 자바스크립트 런타임

2. 자바스크립트를 서버에서 실행할 수 있게 해주는 런타임 환경이며 서버 애플리캐이션을 개발할 수 있는 플랫폼을 제공

 

'Node js' 카테고리의 다른 글

파일 업로드 처리 (Multer)  (0) 2025.02.17
passport.js 정리하기  (0) 2025.02.14
mongoDB 에 대하여  (1) 2025.01.25
3. express 미들웨어 정리하기  (3) 2025.01.24
2. 노드의 특성  (0) 2025.01.07

+ Recent posts