Javascript

[Express] Mysql 연결하기

eulBlue 2024. 4. 16. 11:17

📱테스트 환경

"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