| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
- 카카오뷰 부업
- 카카오뷰 성장
- HTML
- 위드굿즈 굿즈샵
- git 협업하기
- 도서 원씽
- 카카오뷰N잡
- 카뷰 수익 인증
- CSS
- Axios 라이브러리
- 실시간 통신
- 카카오뷰 탭이동
- 책 원씽
- express.js 환경 셋팅
- 카카오뷰 초보
- 엑셀 프린트하기
- Git 팀 작업
- 웹기초
- 카카오뷰 온라인 수익화
- 자기관리
- 30일 글쓰기
- 이석증
- 성공에 대한 거짓말
- 카카오뷰 수익
- 위드굿즈
- 성공비법
- ppt 도형 색
- ppt 다이어그램
- 엑셀 기초 함수
- 원씽
- Today
- Total
김데이의 개발공부
[ TIL ] Day 52 - Multer 적용 방식 / 유효성 검사 validation 본문
[ TIL ] Day 52 - Multer 적용 방식 / 유효성 검사 validation
theday365 2025. 12. 8. 19:13🗓️ 수업 일자 : 2025.12.8
✨ 오늘의 수업 평가 : [ GOOD ] 머리가 터질 뻔했지만 배웠다 💥🤯📚
타입스크립트로 변환하면서 그 동안 묶혀두고 모른척(?) 했던 코드들을 보며
이제는 정말 수정을 해야 할 때가 된거 같아서 오늘 날 잡고 수정을 감행했다!
아직 validation 파일은 다 수정하지 못했지만,
그래도 일단 도전 해 본거에 의의를 두며..
👩💻 [개인 프로젝트] 오늘 작업 내용 💻
- 이미지 업로드 Multer 업그레이드
📝 오늘 배운 내용
- 파일 업로드 미들웨어 Multer
- 유효성 검증 validation 파일 정리
1. 파일 업로드 미들웨어 Multer
미들웨어 Multer
브라우저가 파일을 보낼 때 multipart/form-data 형식으로 보냄
→ Express에서 처리 가능한 형식으로 파일 분석 후 req.file 또는 req.files 로 변환하여 사용 가능하게 제공
(Express 자체로는 브라우저가 보낸 파일 형식을 읽을 수 없음, 변환 과정이 꼭 필요함)
Multer의 주요 역할
- 파일의 저장 위치 설정 : 로컬 / 메모리 / 외부 스토리지(S3 등) 등 어느 위치에 어떻게 저장 할 지 설정 가능
- 파일 이름 & 경로에 대한 커스텀 가능 : 파일명이 충돌나지 않도록 변환을 하거나, 확장자 설정 작업등이 가능
- 파일 종류 필터링 : 서버에 저장하고자 하는 파일 종류를 직접 선택 가능
- 파일 갯수 설정 : 파일을 단일로 받을지, 여러 파일로 받을지 설정 가능
multer sample file
middleware/upload.js
import multer from 'multer';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';
// 파일 작업 상수 선언
const ALLOWED_MIME_TYPES: string[] = ['image/png', 'image/jpeg', 'image/jpg'];
// 5MB 파일 크기 제한
const FILE_SIZE_LIMIT: number = 5 * 1024 * 1024;
// 저장소 설정
const PUBLIC_PATH = './files';
// Multer 저장소 설정
const storage = multer.diskStorage({
destination(req, file, cb) {
cb(null, PUBLIC_PATH);
},
filename(req, file, cb) {
const ext = path.extname(file.originalname);
const filename = `${uuidv4()}${ext}`;
cb(null, filename);
}
});
function imageFilter(req, file, cb) {
if (!file.mimetype.startsWith('image/')) {
return cb(new Error('이미지 파일만 업로드 가능합니다.'));
}
cb(null, true);
}
const upload = multer({
storage,
limits: { fileSize: FILE_SIZE_LIMIT },
fileFilter: imageFileFilter,
})
// 프론트에서 업로드 필드명
export const uploadUserImage = upload.single('image');
Multer를 활용한 실전 예시 - User 등록 시 사용 한 이미지 파일을 multer로 처리하기
1) API 내부 포함 형식 : 유저 등록 요청 내에서 파일을 불러와 처리하는 방식, Multer를 파일 정리용 미들웨어로 사용

routers/userRouter.js
import { Router } from 'express';
import { createUser } from '../controllers/userController.js';
import { uploadUserImage } from '../middleware/upload.js';
const router = Router();
// ⭐ 유저 생성 시 이미지 업로드 동시 처리 ⭐
// POST /api/users
router.post('/', uploadUserImage, createUser);
controllers/userController.js
import prisma from '../prismaClient.js';
// ⭐ 유저 생성 + 이미지 업로드 통합 버전 ⭐
export async function createUser(req, res, next) {
try {
const { name, phoneNumber } = req.body;
if (!name || !phoneNumber) {
return res.status(400).json({ message: "name과 phoneNumber는 필수값입니다." });
}
// 미들웨어 "uploadUserImage"의 multer가 성공하면 req.file 에 이미지 정보가 들어있음
let imagePath = null;
if (req.file) {
imagePath = '/uploads/' + req.file.filename;
}
const newUser = await prisma.user.create({
data: {
name,
phoneNumber: Number(phoneNumber),
image: imagePath,
},
});
return res.status(201).json(newUser);
} catch (err) {
next(err);
}
}
2) 별도 모듈 형식 : 유저 등록 요청 내에서는 이미지 처리를 일절 하지 않고, 순수하게 등록만 진행
→ 파일 변환 / 파일 관리 하는 모듈을 각각 만들어 유저 등록 요청은 "등록만" 할 수 있게 역할 분리, 완전 분업화

// routes/combinedRouter.js
import { Router } from 'express';
import { uploadUserImage } from '../middleware/upload.js'; // 기존 multer 설정 재사용
// multer와 유저 등록 요청 사이의 새로운 연결 모듈을 생성
import { createUserWithImage } from '../controllers/combinedController.js';
const router = Router();
// ⭐ 해당 포스트 요청으로 "이미지 업로드 후 유저 생성 작업으로 이미지 전달, 업로드 진행"
router.post('/create-user-with-image', uploadUserImage, createUserWithImage);
export default router;
controllers/combinedController.js
// ⭐ 업로드 한 이미지를 변환하여, 유저 생성 요청에 연결
import { createUser } from './userController.js';
export async function createUserWithImage(req, res, next) {
try {
// 1. multer 통과 후 req.file 존재함
if (!req.file) {
return res.status(400).json({ message: '이미지가 필요합니다.' });
}
// 2. 업로드된 파일 경로를 body.image 에 끼워넣기!
req.body.image = '/uploads/' + req.file.filename;
// ⭐ 3. 기존 createUser 요청 구문을 재사용
return createUser(req, res, next);
} catch (err) {
next(err);
}
}
2. 유효성 검증 validation
유효성 검증 validation
- Express/TS/Node 기반 서버에서 요청(req)의 값들이 유효한지 판단하는 로직을 모아둔 파일 또는 폴더를 칭하는 말로,
validation 또는 validators, schemaValidator, dtoValidator 등으로 부름 - 비지니스 로직의 경우 "요청"과 관련된 실제 작업만 진행해야 하므로,
요청에 필요한 여러 값을 확인하는 작업을 validation으로 분리해서 관리 해야함
validation 파일의 주요 역할
- req.body 값 검증 : 실제 요청에 사용 될 req.body의 각 값을 확인함.
예시) 글쓰기에서는 title, content의 타입과 허용 범위(길이)를 체크,
회원가입에서는 필수값이 모두 작성 되었는지 등을 확인 - req.query 값 검증 : 검색 / 필터 / 페이지네이션등 요청의 설정에 사용 될 각 값들을 확인
예시) limit / offset 과 같은 값은 숫자로 사용 했는지, keyword 길이 제한 등 확인 - req.param 값 검증 : 삭제 / 수정 / 상세조회 등에서 사용되는 id 값이 제대로 작성 되었는지 확인
- 이 외 요청 작업에 사용되는 기타 설정에 대해서도 모두 확인 진행
유효성 검증 라이브러리 종류
1) Joi (조이) 가장 대중적인 라이브러리
- Express, Nest 등 Node 기반에서 제일 인기 많음
- 객체 스키마 정의가 직관적
- 정규식·조건부 검증·커스텀 규칙 다 지원
- 실무에서 압도적으로 많이 보임
예) const schema = Joi.object({ name: Joi.string().min(2).required() })
2) Yup (얍)
- 프론트/백 모두에서 인기
- React Hook Form과 궁합 좋음
- 구조가 Joi와 비슷하지만 좀 더 프론트 친화적
3) Zod (조드) TypeScript 신흥 강자
- TS 개발자들이 요즘 제일 많이 씀
- “타입 + 검증” 동시에 처리 (리턴 타입 자동 생성!!)
- Next.js, Express, tRPC에서 대세
4) Superstruct
- 빠르고 가볍고 심플
- 함수형 스타일 좋아하는 사람들이 사용
- Joi보다 문법이 훨씬 간단한 편
5) Express-validator
- Express 전용 미들웨어
- 비교적 오래된 스타일
- req.body, req.params 바로 검증 가능
- TS에서는 불편함 때문에 예전보다 사용량 줄어드는 중
6) class-validator (+ class-transformer)
- 데코레이터 기반 "@IsString()", "@IsInt()" 같은 방식
- DTO 구조 만들 때 깔끔함
- Express에서도 쓸 수 있으나 셋업이 다소 번거롭긴 함
- Nest.js에서는 사실상 표준
📃 내일은 뭘 배울까 🤔
- 코드레벨 아키텍쳐 : layered architecture 방식
'코드잇 Node.js(BE) 부트 캠프 > TIL (Today I Learn) 📑' 카테고리의 다른 글
| [ TIL ] Day 54 - SQL 데이터 분석 : 집계, 그룹핑 & 조인, 서브 쿼리, AS & VIEW (0) | 2025.12.10 |
|---|---|
| [ TIL ] Day 53 - SQL 데이터 분석 기초 문법 : 데이터 조회 / 데이터 정렬 (0) | 2025.12.09 |
| [ TIL ] Day 50, 51 - 실습 : 타입스크립트 셋팅 & 파일 적용 (0) | 2025.12.05 |
| [ TIL ] Day 48 & 49 - 디자인 패턴 / 코드 레벨 아키텍쳐 (0) | 2025.12.03 |
| [ TIL ] Day 48 - RESTful API 설계 원칙 / 구현 요소 / 문서화 (0) | 2025.12.02 |