동아리에서 프로젝트장을 맡아 프론트엔드 및 백엔드 스터디를 이끌고 있습니다. 백엔드는 저도 초보이다 보니 공부하면서 스터디원들에게 전달하기 위해 만든 자료입니다.
VSCode, Node 등의 설치는 이미 되어있다고 가정합니다.
공부할 것
- 서버, 데이터베이스에 대한 개념 알아오기
- CORS란?
- SQL 문법 대충이라도 익혀보기
- GET, POST, PUT 등 Rest API와 각 메소드에 대해
우선 Node.js Typescript 보일러플레이트를 갖다 써봅시다. git clone 으로 푹찍해옵니다.
yarn add express 및 yarn add @types/express로 express와 타입 파일을 설치합니다.
src/index.ts 에 다음과 같은 코드를 입력해봅니다.
import express, { Application, Request, Response } from 'express';
const app: Application = express();
app.get('/', async (req: Request, res: Response): Promise<Response> => {
return res.status(200).send({
message: 'Hello World!',
});
});
const PORT = 3000;
try {
app.listen(PORT, (): void => {
console.log(`Connected successfully on port ${PORT}`);
});
} catch (error: any) {
console.error(`Error occured: ${error.message}`);
}
yarn dev 로 서버를 띄워봅니다. 이제 브라우저에서 http://localhost:3000 에 접속하면 {"message":"Hello World!"} 가 뜹니다. 와! 이제 기본적인 CRUD를 구현해볼건데요, 테스트를 위해 포스트맨 가입 후 설치 or 웹상에서 사용할 수 있게 준비해둡니다. 또, DB를 연결해야 하는데 간단하게 sqlite3를 사용하겠습니다.
POST 메소드
POST 메소드는 클라이언트에서 서버에 데이터를 보낼 수 있는 메소드입니다.
import cors from 'cors';
import bodyParser from 'body-parser';
yarn add cors, yarn add body-parser 로 라이브러리를 설치해줍니다. cors에 대해서는 꼭! 검색해서 알아보셔야 합니다. body-parser는 post로 보낸 body를 해석할 수 있게 해주는 라이브러립니다.
- import 할 때 빨간 밑줄 생기며 'cors'에 대한 선언 파일을 찾을 수 없습니다. 오류 발생 시 yarn add @types/cors --dev 로 라이브러리 설치하면 해결됩니다! (참고: https://velog.io/@hyunjoong/타입스크립트-모듈-에-대한-선언-파일을-찾을-수-없습니다)
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
위 코드를 추가하여 app에서 각 미들웨어를 사용할 수 있게 해주세요.
app.post('/', async (req: Request, res: Response): Promise<Response> => {
return res.status(200).send({
message: `Hello World! ${req.body.name}`,
});
});
위 코드를 추가해주고, postman에서 보내면, name이 잘 뜨는 것을 확인할 수 있습니다.
DB 달기
yarn add sqlite3 으로 sqlite3을 설치해줍니다. sqlite는 파일 하나로 이루어진 DB로, 따로 DB를 띄우지 않고 서버에 붙일 수 있습니다. db 폴더를 만들어줍니다.
import sqlite3 from 'sqlite3';
임포트 후
const db = new sqlite3.Database('./db/my.db', sqlite3.OPEN_READWRITE, (err) => {
if (err) {
console.error(err.message);
} else {
console.log('Connected to the mydb database.');
}
});
위 코드로 db를 초기화해줍니다.
const dropQuery = `
DROP TABLE IF EXISTS person
`;
const insertQuery = `
CREATE TABLE IF NOT EXISTS person(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(20)
)
`;
const dummyDataQuery = `
insert into person(name) values ('hi'), ('hello')
`;
person이라는 테이블이 있으면 없애고, 없으면 만들어줍니다. 그 후 더미데이터를 넣습니다.
db.serialize(() => {
db.each(dropQuery);
db.each(insertQuery);
db.each(dummyDataQuery);
});
적용.
app.post('/', async (req: Request, res: Response): Promise<Response> => {
const query = `insert into person(name) values ('${req.body.name}')`;
db.serialize();
db.each(query);
return res.status(200).send({
message: `입력 완료: ${req.body.name}`,
});
});
POST 메소드에 위 코드를 추가하여, POST 요청이 왔을때 body의 name을 person에 넣도록 합니다.
app.get('/', async (req: Request, res: Response) => {
const query = `SELECT * FROM person`;
db.serialize();
new Promise((resolve, reject) =>
db.all(query, (err, rows) => {
if (err) console.log(err);
return resolve(rows);
}),
).then((rows) =>
res.status(200).send({
user: rows,
}),
);
});
GET 메소드를 위와 같이 수정하여 person 테이블을 보여줍니다.
- 전체 코드
import express, { Application, Request, Response } from 'express';
import cors from 'cors';
import bodyParser from 'body-parser';
import sqlite3 from 'sqlite3';
const app: Application = express();
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const db = new sqlite3.Database('./db/my.db', sqlite3.OPEN_READWRITE, (err) => {
if (err) {
console.error(err.message);
} else {
console.log('Connected to the mydb database.');
}
});
const dropQuery = `
DROP TABLE IF EXISTS person
`;
const insertQuery = `
CREATE TABLE IF NOT EXISTS person(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(20)
)
`;
const dummyDataQuery = `
insert into person(name) values ('hi'), ('hello')
`;
db.serialize(() => {
db.each(dropQuery);
db.each(insertQuery);
db.each(dummyDataQuery);
});
app.get('/', async (req: Request, res: Response) => {
const query = `SELECT * FROM person`;
db.serialize();
new Promise((resolve, reject) =>
db.all(query, (err, rows) => {
if (err) console.log(err);
return resolve(rows);
}),
).then((rows) =>
res.status(200).send({
user: rows,
}),
);
});
app.post('/', async (req: Request, res: Response): Promise<Response> => {
const query = `insert into person(name) values ('${req.body.name}')`;
db.serialize();
db.each(query);
return res.status(200).send({
message: `Hello World! ${req.body.name}`,
});
});
const PORT = 3000;
try {
app.listen(PORT, (): void => {
console.log(`Connected successfully on port ${PORT}`);
});
} catch (error: any) {
console.error(`Error occured: ${error.message}`);
}
과제
위 내용을 이용하여, 다음과 같은 프로그램을 만들어 보세요.
- / 에 get 메소드로 접근하면 모든 책과 음식을 보여줍니다.
- /books 에 get 메소드로 접근하면 모든 책의 목록을 보여줍니다.
- /meals 에 get 메소드로 접근하면 모든 음식의 목록을 보여줍니다.
- /new 에 post 요청 body로 {"type": "book", "name": "책제목예시", "price": 3000, "author": "작가이름예시"} 형식의 json을 전달하면 책 목록에 해당 책을 추가하고, {"type": "meal", "name": "음식이름예시", "price": 3000, "restaurant": "식당이름예시"} 형식의 json을 전달하면 음식 목록에 해당 음식을 추가합니다.
'Web > Backend' 카테고리의 다른 글
[Koa] Koa에서 apidoc 사용하기 (1) | 2023.06.05 |
---|---|
[백엔드 스터디] 2. 서버를 띄워보자 (0) | 2022.09.27 |
[Strapi] Strapi 설치부터 배포까지 (1) | 2022.08.23 |
[GCP] 구글 클라우드 플랫폼에 Nginx로 리액트 프로젝트 배포하기 (2) | 2020.11.29 |
[JWT] JSON Web Token (0) | 2020.08.19 |
댓글