# npm을 이용하여 전역 환경에 Yarn을 설치합니다!
npm install -g yarn
yarn -v 로 확인
yarn init : 새로운 프로젝트나 패키지 시작 (package.json)
yarn add 패키지명 -> yarn add express
Express.js 프레임워크 -> 말그대로 웹서버 개발을 편리하게 만드는 틀/ 도구 - 가장 큰 특징은 미들웨어를 지원해준다는 점 (Auth, logging,에러처리핸들러 등 ➕ 클라이언트의 req를 받을 때, body에 있는 데이터를 분석할 수 있게 해줌 JSON형태로 body를 입력받을 수 있게 됨 )
vs코드 폴더 오픈
app.js 파일 만들기
터미널 열어서 yarn init -y 로 package.json 생성 (알아서 프로젝트명이나 버전을 기본값으로 정해달라는 명령어)
package.json 파일에서 "type": "module" 추가 (이렇게 해야 ES6 모듈 사용가능)
{
"name": "spa-shop",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"type": "module"
}
yarn add express (Express.js 설치)
여기까지 하면 폴더구조가 아래와 같음 - package.json에 들어가서 express 관련된 내용이 있으면 정상 설치 완료
➕ yarn.lock 이란? 어떤 패키지들이 어떤 버전으로 설치되었는지를 기록해놓은 파일 ( 왜 필요? 나중에 이 파일이 있으면 협업할 때 같은 환경으로 개발할 수 있게 도와줌)
➕ node_modules 란? yarn을 통해 설치된 패키지들에 대한 파일이 모여있는 폴더 ⭐️이 폴더는 공유하거나 배포할 때 포함되어서는 ❌!! 안됨!!
미들웨어 ?
전역 미들웨어로 등록하는 방법 -> app.use()
➕ app.use('/api', router); 코드 설명 - app.use 는 미들웨어를 사용하게 해주는 코드! 뒤의 경로로 접근하는 경우에만 json 미들웨어를 거친 뒤, router로 연결되도록 하는 것!
// app.js
// Express에서 req.body에 접근하여 body 데이터를 사용할 수 있도록 설정합니다.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
이렇게 하면 Body Parser는 클라이언트의 요청 req 본문 데이터인 body를 쉽게 파싱할 수 있게 해주는 미들웨어임
app.use((req, res, next) => {
// 필요한 코드
});
여기서 next(); 다음 스택으로 정의된 미들웨어 호출
하지만 미들웨어를 거치는 중간에 next() 가 실행되지 않으면 다음 미들웨어는 실행되지 않고, 클라이언트의 요청은 거기서 종료됩니다.
➕ 현재 미들웨어에서 응답을 보내는 경우, 즉 res.send()이나 res.json()등의 메서드를 호출하는 경우에는 next() 를 호출하면 안됩니다. 이렇게 하지 않으면 이미 요청이 종료된 상태에서 다른 미들웨어가 응답을 보내려고 하여 중복된 요청이 전달되는 문제가 발생하게됩니다.
에러처리는 왜 해야할까?
원하지 않았던 비즈니스 로직이 수행되지 않게! 예상치 못한 문제를 미리 방지해 서버가 안정적으로 되도록
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
에러처리 미들웨어에서 err, req, res, next 와 같이 에러, 요청, 응답, 다음 미들웨어를 호출하는 함수
err: 이전 미들웨어에서 발생한 에러를 전달받은 객체
req, res : HTTP 요청과 응답을 관리하는 객체
next: 다음 미들웨어를 실행하는 함수
// app.js
import ErrorHandlerMiddleware from './middlewares/error-handler.middleware.js';
...
//app.js
// /api 주소로 접근하였을 때, router와 TodosRouter로 클라이언트의 요청이 전달됩니다.
app.use('/api', [router, TodosRouter]);
// 에러 핸들링 미들웨어를 등록합니다.
app.use(ErrorHandlerMiddleware);
⭐️에러처리 미들웨어는 하단에 등록! 왜냐하면, 미들웨어는 등록된 순서대로 실행되기 때문!! 순서가 TodoRouter에서 비즈니스 로직을 수행한 후 발생한 에러를 다음 미들웨어로 전달되기 때문에
➕ app.js 파일의 역할
📢 입문주차에는 noSQL 인 mongoDB를 사용했으나, 이번에는 RDBMS인 mySQL을 사용
여기서 mongoDB는 moongoose를 사용해서 (ODM - Object Document Mapping) 으로 Javascript 객체와 데이터베이스 관계를 매핑mapping(연결) 해주는 도구를 사용했으나,
mySQL에서는 Prisma를 사용하여 ORM (Object Relational Mapping)으로 Javascript 객체와 데이터베이스의 관계 relation을 연결해주는 차이가 있음
# yarn 프로젝트를 초기화합니다.
yarn init -y
# express, prisma, @prisma/client 라이브러리를 설치합니다.
yarn add express prisma @prisma/client
# nodemon 라이브러리를 DevDependency로 설치합니다.
yarn add -D nodemon
# 설치한 prisma를 초기화 하여, prisma를 사용할 수 있는 구조를 생성합니다.
npx prisma init
prisma: 우리가 터미널에서 Prisma를 실행할 수 있도록 도구를 설치하는 명령어
@prisma/client: 우리가 node.js 에서 Prisma를 사용할 수 있게 해줌
nodemon: 개발코드가 변경되었을 때, 자동으로 서버를 재시작해주는 패키지
➕ package.json에 아래와 같은 내용 추가
// package.json
...
"scripts": {
"dev": "nodemon app.js"
},
이렇게 하면 yarn run dev 라고 하면 nodemon 실행
npx prisma init : 아래와 같은 directory structure
내 프로젝트 폴더 이름
├── prisma
│ └── schema.prisma
├── .env
├── .gitignore
├── package.json
└── yarn.lock
datasource 설정하기 : Prisma가 데이터베이스를 연결할 수 있도록 설정, 관리하는데 필요한 정보를 설정
// schema.prisma
datasource db {
// MySQL 데이터베이스 엔진을 사용합니다. /즉, 관계형 데이터베이스 엔진이 무엇인지 알려줌
provider = "mysql"
// 데이터베이스 연결 정보를 .env 파일의 DATABASE_URL 로부터 읽어옵니다.
url = env("DATABASE_URL")
}
Prisma model 설정하기
궁금했던 거
데이터 유형 뒤에 ?가 붙게 된다면, NULL을 허용하는 컬럼이 됩니다.
@@map("Products")
는 Products
테이블을 MySQL에서도 Products
란 이름으로 사용하겠다는 뜻입니다. @@
테이블 명을 정의하기 위해 사용됨
→ @@map()
을 작성하지 않으면, 테이블명의 대문자는 전부 소문자로 치환된답니다. 🥲 실제 데이터 베이스에 있는 테이블명을 대문자로 사용하기 위해서 이렇게 사용함
# schema.prisma 파일에 설정된 모델을 바탕으로 MySQL에 정보를 업로드합니다.(여러분들의 실제 데이터 베이스에 반영이 된다. )
npx prisma db push
npx prisma db push 는 내부적으로 prisma generate가 실행됩니다.
npx prisma generate
PrismaClient 는 Prisma를 사용하여 실제 데이터베이스와의 연결을 관리하는 객체입니다.
new PrismaClient()를 이용해 JavaScript에서 Prisma를 사용할 수 있도록 인스턴스를 생성하게됩니다.
// 이건 Prisma Client 인스턴스를 생성한다는 내용
const prisma = new PrismaClient();
그러나 각 라우터마다 연결하는 건 비효율적
최대한 데이터베이스의 연결을 줄이는 것이 효율적
이런 문제를 해결하기 위해 저희는 /utils/prisma/index.js 파일을 구현하여, 하나의 파일에서 데이터베이스 커넥션을 관리하여 최초로 1번만 MySQL과 커넥션을 생성하도록 코드를 구현하면 된답니다!
utils/prisma/index.js Prisma 리팩토링
// utils/prisma/index.js
import { PrismaClient } from '@prisma/client';
export const prisma = new PrismaClient({
// Prisma를 이용해 데이터베이스를 접근할 때, SQL을 출력해줍니다.
log: ['query', 'info', 'warn', 'error'],
// 에러 메시지를 평문이 아닌, 개발자가 읽기 쉬운 형태로 출력해줍니다.
errorFormat: 'pretty',
}); // PrismaClient 인스턴스를 생성합니다.
routes/posts.router.js Prisma 리팩토링
⭐️⚠️ 꼭! 상단의const prisma = new PrismaClient() 구문은 삭제해주세요!
// routes/posts.router.js
import { prisma } from '../utils/prisma/index.js';