Multer: 파일 업로드
💻 multer
- 파일 업로드를 위해 사용되는 Node.js의 미들웨어
💡 미들웨어란?
- 양 쪽을 연결하여 데이터를 주고 받을 수 있도록 중간에서 매개 역할을 하는 소프트웨어.
- 양쪽을 연결
- 중간에서의 매개 역할
// app.js
// multer 불러오기
const multer = require("multer");
// multer 설정
const upload = multer({
dest: "uploads/", // 어디에 저장 될지
});
const uploadDetail = multer({
storage: multer.diskStorage({
destination: function (req, file, done) {
done(null, "uploads/"); // 어디에 저장될지 경로 설정!
// uploads 라는 폴더가 미리 만들어져 있어야 함
},
filename: function (req, file, done) {
// done(null, 우리가 설정 할 파일 이름)
// const extension = path.extname(파일이름.확장자) -> 확장자만 return을 해주는 함수
const extension = path.extname(file.originalname);
// path.basename(파일이름.확장자, 확장자) -> 파일 이름만 리턴
done(
null,
path.basename(file.originalname, extension) + Date.now() + extension
);
console.log(path.basename(file.originalname, extension));
console.log(path.extname(file.originalname));
},
}),
limits: { fileSize: 5 * 1024 * 1024 }, // 5MB
});
💡 dest와 storage의 차이
- dest: 간단한 파일 저장이 필요하며 기본 설정이 충분 할 경우.
- 파일 이름이나 저장 경로를 설정 할 필요가 없을 때.
- 파일이름: 랜덤으로 자동 생성
- 고정된 디렉토리 (dest: ‘path/’)
- 파일 이름이나 저장 경로를 설정 할 필요가 없을 때.
- storage: 파일 이름 또는 저장 경로를 동적으로 변경해야 할 때.
- 동적으로 설정 가능 (diskStorage.destination) & (diskStorage.filename)
- 파일을 메모리나 다른 방식으로(세부적으로) 저장하려 할 때.
// index.ejs
<form action="/upload" method="post" enctype="multipart/form-data"> </form>
// form 태그의 enctype 속성으로 "multipart/form-data" 반드시 설정 해야 한다!
💡 세부 설정
- storage: 저장할 공간에 대한 정보
- diskStorage: 파일을 저장하기 위한 모든 제어기능 제공 (파일 저장관련 설정)
- destination: 업로드 할 파일을 저장할 폴더를 지정
- filename: 파일이름 (요청객체, 업로드된 파일 객체, 콜백함수 순서)
- extname(): 확장자를 추출
- basename(): 파일이름을 추출 (파일의 원래 이름, 확장자) -> 확장자를 제외해서 파일이름만 추출
💻 multer: 하나의 input에 파일 여러개 업로드
// index.ejs
<h2>하나의 input에 파일 여러개 업로드</h2>
<form action="/uploads/array" method="post" enctype="multipart/form-data">
<input type="file" name="multifiles" multiple />
<br />
<input type="text" name="title" placeholder="사진 제목" />
<br />
<button>업로드</button>
</form>
// app.js
// 하나의 input에 여러개 파일
app.post("/uploads/array", uploadDetail.array("multifiles"), (req, res) => {
// console.log(req.file); // undefined
console.log(req.files); // 파일 여러개 일때
/** 배열 안에 객체 형태로 들어온다.
* [ << 배열
{
fieldname: 'multifiles',
originalname: 'hachi.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'uploads/',
filename: 'hachi1732518372784.jpg',
path: 'uploads\\hachi1732518372784.jpg',
size: 27487
},
{
fieldname: 'multifiles',
originalname: 'hachiwarae.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'uploads/',
filename: 'hachiwarae1732518372788.png',
path: 'uploads\\hachiwarae1732518372788.png',
size: 199533
}
]
*/
console.log(req.body);
res.send("업로드 완료");
});
- array(): 동일한 필드 이름으로 여러 파일을 업로드할 때 사용
- req.files에 배열로 저장
💻 multer: 여러개의 input에 파일 업로드
// index.ejs
<h2>여러 개 input에 파일 업로드</h2>
<form action="/uploads/fields" method="post" enctype="multipart/form-data">
<input type="file" name="file1" /> <br />
<input type="text" name="title1" placeholder="사진 제목1" />
<br /><br />
<input type="file" name="file2" /> <br />
<input type="text" name="title2" placeholder="사진 제목2" />
<br /><br />
<input type="file" name="file3" /> <br />
<input type="text" name="title3" placeholder="사진 제목3" />
<br /><br />
<button>업로드</button>
</form>
// app.js
// 여러개의 input에 파일 업로드
// .fields() 사용
// fields의 매개 변수는 배열[{name:'name값1'},...]
app.post(
"/uploads/fields",
uploadDetail.fields([
{ name: "file1" },
{ name: "file2" },
{ name: "file3" },
]),
(req, res) => {
// upload.fields() 로 받아주는 req.files 객체 형태로 들어옴
console.log(req.files);
/**
* {filename1: [{업로드 파일 정보}], filename2:[{업로드 파일 정보}], filename3:[{업로드 파일 정보}]} // 객체 형태로 들어온다.
*/
console.log(req.body);
res.send("업로드 완료");
}
);
- fields(): 여러 다른 필드 이름으로 여러 파일들을 업로드할 때 사용
- req.files에 객체로 저장 (필드별로 구분)
💻 axios 동적 폼 파일 업로드
// index.ejs script
function fileOnlyUpload() {
const file = document.getElementById("dynamicFile");
console.log(file.files);
console.dir(file.files[0]);
const formData = new FormData();
// 자바 스크립트에서 기본적을 제공하는 클래스
// 파일을 페이지 전환없이 비동기로 제출하고 싶을 때 사용
formData.append("dynamicFile", file.files[0]);
axios({
method: "post",
url: "dynamicUpload",
data: formData,
headers: {
"Content-Type": "multipart/form-data",
},
}).then((res) => {
console.log(res.data.path);
const img = document.querySelector("img");
img.src = `/${res.data.path}`;
});
}
// 2. 글과 파일을 함께 업로드
function fileAndTextUpload() {
const formData = new FormData();
// input[type='file'], 파일 정보를 서버로 보내기 위해 선택
const file = document.getElementById("dynamicFile");
// input[type='text'], 이미지에 대한 제목, 즉, 글자 정보를 서버로 보내기 위해 선택
const title = document.getElementById("dynamicText");
// img태그, 사진의 src, alt 속성을 바꾸기 위해 선택
const img = document.querySelector("img");
console.log(file.files);
formData.append("dynamicFile", file.files[0]);
formData.append("dynamicFile", title.value);
/*
formData = {
dynamicFile: 파일정보(fileList[0])
dynamicTitle: "사진 제목 string"
}
*/
axios({
method: "post",
url: "/dynamicUpload",
data: formData,
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((res) => {
console.log(res.data);
console.log(res.data.fileInfo.dynamicTitle);
img.src = "/" + res.data.file.path;
img.alt = res.data.fileInfo.dynamicTitle + "사진";
img.classList.add("profile");
document.querySelector(".tit").innerText =
res.data.fileInfo.dynamicTitle;
})
.catch((err) => console.log("EROOR", err));
}
// app.js
// 동적 폼 파일 업로드
app.post("/dynamicUpload", uploadDetail.single("dynamicFile"), (req, res) => {
// 하나의 객체에 합쳐서 보내는 방법
// res.send(...req.file, ...req.body);
res.send({ file: req.file, fileInfo: req.body });
});
app.listen(PORT, () => {
console.log(`http://localhost:${PORT}`);
});
Database
- 데이터를 저장하는 구조/자료의 모음
💻 DBMS (DataBase Management System)
- 데이터베이스에 접근하고 이를 관리하기 위해 존재한다.
- 관계형 데이터베이스(Relational DBMS)도 있다.
💻 DB구조
- 열 (Column, Attribute, 속성)
- 행 (Record, Tuple, 튜플)
- 테이블 (Table, Relation)
💡키 (Key)
- DB에서 튜플을 찾거나 순서대로 정렬할 때 구분하고, 정렬의 기준이 되는 속성
- 기본키 (Primary Key) ⭐
- 테이블을 대표하는 속성
- 메인 키로 한 테이블에서 특정 튜플(행)을 유일하게 구별할 수 있는 속성
- Null 값 불가
- 중복 값 불가
- 외래키 (Foreign Key) ⭐
- 어떤 테이블의 기본키를 참조하는 속성
- 참조되는 기본키 값이 변경되면 참조하는 외래키 값도 변경된다.
- Null 값과 중복 값 등 허용
- 관계 데이터베이스에서 키는 특정 튜플을 식별할 때 사용하는 속성이거나 혹은 속성의 집합이다.
- 테이블간 관계를 맺는데도 사용된다.
💻 SQL (Structured Query Language)
- 관계형 데이터베이스에 정보를 저장하고 처리하기 위한 프로그래밍 언어
- 실행 순서가 없는 비절차적언어이다!
- 크게 세개로 나눌 수 있다: DDL, DML, DCL
💡 DDL 데이터 정의어 (Data Definition Language)
- 데이터베이스의 구조를 정의하는 언어
- 주요 명령어:
- CREATE: 새로운 테이블 생성
- ALTER: 기존 테이블 구조 변경
- DROP: 기존 테이블 삭제
- TRUNCATE: 테이블 초기화
- RENAME: 테이블 이름 변경
⭐ DROP 과 TRUNCATE의 차이
- DROP은 테이블 삭제하기
- TRUNCATE는 테이블 초기화 하기. 테이블의 모든 행(row) 일괄 삭제!
💡 DML 데이터 조작어 (Data Manipulation Language)
- 데이터베이스 내의 데이터를 조작하는 언어
- 주요 명령어:
- SELECT: 데이터 조회
- INSERT: 새로운 데이터 삽입
- UPDATE: 기존 데이터 수정
- DELETE: 데이터 삭제
- DISTINCT: 중복된 행 제거
- LIMIT: 결과로 반환되는 행 수를 제한하는데 사용, OFFSET과 함께 사용해 시작 지점을 지정 할 수 있다.
- GROUP BY: 데이터를 그룹화 하는 역할
- JOIN: 두 개 이상의 테이블을 연결하여 데이터를 검색
⭐ SELECT문은 데이터를 검색하는 기본 문장이다!
⭐ SELECT문의 순서: SELECT 속성이름, FROM 테이블이름 WHERE 검색조건 ORDER BY 속성이름
⭐ ORDER BY
- SELECT문의 마지막에 위치한다.
- 오름차순(ASC), 내림차순(DESC)으로 정렬할 수 있다. (ASC가 기본 값!)
💡 DCL 데이터 제어어 (Data Control Language)
- 데이터베이스에 대한 접근 권한을 제어하는 언어
- 주요 명령어:
- GRANT: 사용자에게 권한 부여
- REVOKE: 사용자로부터 권한 회수
더보기
SQL이 비절차적 언어라 순서 상관 없이 내가 실행시키고 싶은 줄에 가서 ctrl+enter 만 누르면 되는게 굉장히 흥미로웠다😮그나마 학부생때 기억이 나서 할만했던 SQL..!
'SeSAC x CodingOn 웹 취업 부트캠프' 카테고리의 다른 글
[새싹/코딩온] 풀스택 웹 개발자 취업 부트캠프 6주차 (2): 환경변수, Sequelize, Database 응용 (0) | 2025.01.04 |
---|---|
[새싹/코딩온] 풀스택 웹 개발자 취업 부트캠프 6주차 (1): MVC 패턴, MySQL 연결 (0) | 2025.01.04 |
[새싹/코딩온] 풀스택 웹 개발자 취업 부트캠프 5주차 (1): 동적 폼 전송 (0) | 2024.12.12 |
[새싹/코딩온] 풀스택 웹 개발자 취업 부트캠프 4주차 (2): EJS, Form (0) | 2024.12.02 |
[새싹/코딩온] 풀스택 웹 개발자 취업 부트캠프 4주차 (1): 비동기처리 (0) | 2024.11.24 |