📱테스트 환경
"express": "^4.18.2"
"typescript": "^5.3.3"
Mysql 을 연결하기 위해서 일단 해당 모듈을 설치한다.
npm install mysql2
그리고 DB 연결을 위한 설정을 진행한다.
import mysql2 from "mysql2/promise";
const mysql2Connection = mysql2.createConnection({
host: "",
user: "",
password: "",
database: "",
});
export default mysql2Connection;
설정이 완료되면 다음과 같이 호출하여 사용할 수 있다.
const mysqlConnect = await mysql2Connection;
const query = await mysqlConnect.query('...')
근데 문제는 이렇게 사용하면 API 가 호출될때마다 연결을 시도한다는 점이다.
이렇게 되면 자원손해가 크기 때문에 연결을 하고 나서 이를 재사용할 수 있도록 하는게 목표이다.
그럼 설정하는 부분부터 수정하면
// db/db.ts
let connectionPromise: Promise<mysql2.Connection> = null;
const mysqlConfig ={
host: "",
port: ,
user: "",
password: "",
database: "",
};
export const connect = async () => {
if (connectionPromise) return connectionPromise;
connectionPromise = mysql2.createConnection(mysqlConfig);
return connectionPromise;
};
export const getConnect = () => {
if (!connectionPromise) throw new Error('DB connection has not been established.');
return connectionPromise;
};
재사용을 위해 connect 와 getConnet 를 만들어준다.
그리고 index.ts 에 가서 connect() 를 먼저 호출해주는게 포인트다.
// index.ts
connect()
.then(() => {
console.log("DB connected");
})
.catch((err) => {
console.error("DB connection failed", err);
});
그런 다음 routes 를 만들때 DB 연결할때는
// src/routes/routes.ts
const db = await getConnect();
const [result] = await db.query('...');
getConnect() 를 호출하여 사용하면 된다.간단한 GET Router 를 살펴보면
router.get("/:id", async (req: Request, res: Response, next: NextFunction) => {
try {
const db = await getConnect();
const [rows] = await db.query(
`
SELECT
a.article_id,
u.user_id,
u.username,
u.profile_image,
c.ctg_name as ctg_name,
a.topic,
a.content,
a.image,
a.created_at,
a.updated_at
FROM
article a
LEFT OUTER JOIN users u ON a.user_id = u.user_id
LEFT OUTER JOIN category c ON a.ctg_id = c.ctg_id
WHERE
a.article_id = ?
`,
[res.req.params.id]
);
res.send(rows);
} catch (e) {
throw e;
}
});
데이터를 얻을 때는 대괄호로 변수를 묶어주고 query 를 사용한다.
WHERE 에서 사용하는 변수는 ? 로 설정하고, 쿼리 밖 대괄호에 변수를 넣어준다.
이유는 SQL 인잭션 공격을 방지함을 위해서 이다.
router.post(
"/comment/save",
async (req: Request, res: Response, next: NextFunction) => {
try {
const db = await getConnect();
await db.execute(
`
INSERT INTO articleviews
(
article_id,
user_id,
parent_articleviews_id,
content,
created_at,
updated_at
)
VALUES
(?, ?, ?, ?, DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'), NULL)
`,
[
req.body.article_id,
req.body.user_id,
req.body.parent_articleviews_id,
req.body.content,
]
);
res.sendStatus(200);
} catch (e) {
res.sendStatus(500);
}
}
);
Insert 이후 해당 Id 값을 얻고 싶다면 변수를 대괄호로 감싸고 .insertId 를 찾으면 된다.
ㅇㅖ시로는 다음과 같다.
const [result] = await db.execute(
`
INSERT INTO article
(
user_id,
ctg_id,
topic,
content,
image,
created_at,
updated_at
)
VALUES
(?, ?, ?, ?, ?, DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'), NULL)
`,
[userId, ctgId, topic, content, image]
);
const insertId = (result as ResultSetHeader).insertId;
res.status(200).send({ id: insertId });
두 개의 차이점은 하나는 query 를 사용하였고 하나는 execute 를 사용하였다.
기능 상의 큰 차이는 없지만 보안이나 성능적인 차원에서 execute 사용을 권장한다.
- 보안: execute는 SQL 인젝션 공격에 대한 보호를 제공
query는 개발자가 입력 검증과 적절한 쿼리 구성을 신경 써야 한다. - 성능: execute는 반복적으로 같은 쿼리를 다른 매개변수로 실행할 때 더 효율적이다.
미리 준비된 쿼리는 파싱 비용이 한 번만 발생
24.04.29 추가
Mysql 을 사용하면서 연결이 끊키는 경우가 발생해서 관련 내용은 여기에 ..
[Express] mysql2 Can't add new command when connection is in closed state
📱테스트 환경"express": "^4.18.2""typescript": "^5.3.3"Mysql 이 8시간동안 아무런 작업이없으면 연결이 자동으로 끊킨다고 한다.그래도 Mysql 을 사용한지 꽤 오래됐는데 .. 지금까지 몰랐다 ...!!유저가 많
8735.tistory.com
'Javascript' 카테고리의 다른 글
[Nuxt] if else view 조작하기 (0) | 2024.05.09 |
---|---|
[Nuxt] 페이지 이동 (0) | 2024.04.24 |
[Express] Mysql Html Tag 걸러내기 (0) | 2024.04.16 |
[Express] AWS S3 Image 삭제하기 (0) | 2024.04.12 |
[Express] AWS S3 Image 업로드하기 (2) | 2024.04.12 |