SQL 쿼리 작성, 웹 서버 구축, DB 연동, Postman테스트

nooori·2024년 7월 5일

SQL문을 작성하고 웹 서버를 구축한 다음 데이터베이스를 연동해서 어떻게 데이터를 불러올 수 있는지에 대한 과정을 간략히 기록하려고 한다.

SQL 쿼리 작성하기

  • 전체 상품 리스트 추출하는 SQL 쿼리
  • 결과
  • 상품 상세 페이지 정보 추출하는 SQL 쿼리

  • 결과

  • 상품 대표 이미지 모두 추출하는 SQL 쿼리

  • 결과

DBeaver로 SQL 쿼리문이 정상적으로 잘 실행이 되는 것을 확인할 수 있었다. 이제 웹 서버를 구축한 다음에 이 데이터베이스와 연동해보자!

웹 서버 구축하고 데이터베이스와 연동하기

웹 서버는 Node.js + Express를 사용해서 구축할 것이다.
Node.js는 이미 쓰고 있어서 설치가 되어있었고 Express를 설치했다.

  1. express 설치
npm install express --save
  1. 로그인 기능 구현할 예정이라서 express-session도 설치
npm install express-session --save
  1. MariaDB를 연동할 때 MYSQL을 사용할 예정이라서 MYSQL도 설치
npm install mysql --save

필요한 툴들은 모두 설치를 마쳤으니 웹 서버 구축하는 코드를 작성하면 된다.

  • app.js
const express = require('express');
const app = express();
const session = require('express-session');
const fs = require('fs'); 

// 웹 서버 띄우기
// app이 express를 받아왔기 때문에 바로 웹 서버의 기능을 이용할 수 있다
const server = app.listen(3000, () => {  
  // 포트 3000번으로 열거고 성공적으로 열리면 그 다음에 행할 것들을 함수 안에 넣어주면 된다.
  console.log('Server Started! port 3000.');
});

// 만들어둔 MariaDB에 접속된 정보
const db = {
  database: "dev",
  connectionLimit: 10,
  host: 'localhost',  // MariaDB가 설치되어 있는 host
  user: "root",
  password: "mariadb"
};

// mysql의 기능 중 createPool에 만들어둔 db를 넣어주면 db와 연동할 수 있다.
const dbPool = require('mysql').createPool(db);

let sql = require('./sql.js');  // sql.js 사용할 수 있도록 불러오기

// 만약 클라이언트에서 서버로 데이터를 넣거나 받는 요청이 있을 경우 sql.js에 작성해둔 query를 어떻게 받아와서 데이터를 가져오는지 구현
// :alias => 만약 사용자가 우리 서버를 호출할때 /api/login, /api/logout이 아니라 /api/~ 경로로 들어올 경우 모두 다 여기를 거치게 된다. 로그인, 로그아웃 기능은 제품 데이터 정보가 필요하지 않으므로 제외. 
app.post('/api/:alias', async (request, res) => {
  try {
    res.send(await req.db(request.params.alias))
  } catch (error) {
    res.status(500).send({
      error
    })
  }
});

const req = {
  async db(alias, param = [], where = '') {
    return new Promise((resolve, reject) => dbPool.query(sql[alias].query + where, param, (error, rows) => {
      if (error) {
        if (error.code != 'ER_DUP_ENTRY')
          console.log(error);
        resolve({
          error
        });
      } else resolve(rows);
    }));
  }
};
  • sql.js
    DBeaver에서 정상적으로 잘 동작하던 SQL 쿼리를 가져왔다.
module.exports = {
  productList: {
    query: `SELECT t1.*, t2.path, t3.category1, t3.category2, t3.category3
            FROM dev.t_product t1
            JOIN dev.t_image t2 ON t1.id = t2.productid 
            JOIN dev.t_category t3 ON t1.categoryid = t3.id 
            WHERE t2.type = 1 `
  },
  productDetail: {
    query: `SELECT t1.*, t2.path, t3.category1, t3.category2, t3.category3
            FROM dev.t_product t1
            JOIN dev.t_image t2 ON t1.id = t2.productid 
            JOIN dev.t_category t3 ON t1.categoryid = t3.id 
            WHERE t1.id = ? and t2.type =3`
  },
  productMainImages: {
    query: `SELECT *
            FROM dev.t_image
            WHERE productid = ? and type = 2`
  },
}

실제로 동작되는지 Postman으로 테스트하기

Postman 클라이언트 프로그램이 아직 완성되지 않은 상태에서 서버의 특정 URL로 데이터를 GET, POST, PUT, DELETE 등의 요청을 할 수 있게 해주는 도구이다. 이전에 Mock 데이터나 Mock server를 만들 때 사용해본 경험이 있어서 사용법이 크게 어렵진 않았다.

먼저 POST 요청을 하나 만들었다. http://localhost:3000/api/productList 로 요청을 보내면 app.js에서 정의해둔 app.post('/api/:alias'~가 실행되고, req 함수의 sql[alias]에는 productList가 들어간다. 그리고 .query가 동작하면서 sql.js에서 productList에 해당하는 SQL query가 실행된다. 성공적으로 끝나면 이제 그 결과값을 반환 받을 수 있다.
요청을 send 하니

데이터베이스 정보들이 정상적으로 잘 가져와졌다.

로그인이 필요한 페이지들은?

대부분의 로그인 기능이 있는 사이트에는 로그인한 사용자만 볼 수 있는 페이지들이 있고 로그인하지 않은 사용자는 접근할 수 없는 페이지들이 존재한다. 예를 들어 제품을 보는 것은 로그인이 필요하지 않지만, 장바구니에 상품을 저장하거나 판매자가 새로운 상품을 등록할 때는 반드시 로그인이 필요하다. 그렇기 때문에 로그인한 경우와 로그인하지 않은 경우를 모두 고려해서 코드를 작성해야한다.

후에 카카오톡으로 로그인하기 기능을 구현해볼 계획이지만 현재는 간단하게 임의로 로그인 기능을 작성해보았다.

app.use(session({  // 앱에서 session 사용할 예정
  secret: 'secret code',  // session에 대한 key, 
  resave: false,  // request 요청이 왔을 때 session에 수정이 생기지 않더라도 session을 다시 저장하는 옵션인데 필요가 없으니 false로 지정
  saveUninitialized: false,  // session에 저장할 내용이 없더라도 항상 session을 저장할 것인지에 대한 옵션, 마찬가지로 false
  cookie: {  // 쿠키 사용할 예정이라서 쿠키 설정
    secure: false,   // false라고 해둬야 login 하면서 쓸 수 있는 session key를 사용할 수가 있다
    maxAge: 1000 * 60 * 60  //쿠키가 유지되는 시간(1시간)
  }
}));

// 로그인이 되었다는 가정하에 email 키에 강제로 이메일을 넣었다
app.post('/api/login', async (request, res) => {
  request.session['email'] = 'nori@gmail.com';
  res.send('ok'); 
});

app.post('/api/logout', async (request, res) => {
  request.session.destroy();  // session 말끔히 지우기
  res.send('ok');
});

app.post('/api/:alias', async (request, res) => {
  if(!request.session.email) {  // sessioni에 이메일이 없으면(로그인한 상태가 아니라면)
    return res.status(401).send({error:'로그인이 필요합니다.'});
    // return해서 거부하기.
  }
  try {
    res.send(await req.db(request.params.alias))
  } catch (error) {
    res.status(500).send({
      error
    })
  }
});

원하는 대로 잘 작동하는지 테스트를 해볼텐데 로그인을 하면 제품의 리스트를 보여주고 로그인을 하지 않은 상태라면 제품의 리스트를 볼 수 없다고 가정하자.

  1. 먼저 로그인을 한다. 'ok' 메세지가 떴으니 로그인이 성공적으로 된 것을 알 수 있다.

  2. productList 요청을 해보면 데이터들이 무사히 받아와지는 것을 볼 수 있다.

  3. 그럼 로그아웃을 해본 다음 다시 productList 요청을 해보면 어떨까?
    로그아웃을 한 다음 동일한 요청을 보내면

이번에는 로그인이 정보가 필요하다는 메세지가 뜨면서 제품의 정보를 볼 수가 없다.

  1. 확실하게 하기 위해 다시 로그인을 하고 같은 요청을 보내보자!

    다시 한번 실행해봐도 로그인을 하면 보여지고 로그아웃을 하면 볼 수 없다.

마무리

SQL 쿼리를 확인하고 웹 서버를 구축한 다음 데이터베이스 연동한 후 Postman을 사용해서 데이터를 잘 받아오는지 확인해보았다🤗
웹 서버 구축하고 데이터베이스를 연동하는 과정이 어렵긴 했지만, 그래도 원하는 대로 기능이 잘 동작하는걸 확인하니 다른 프로젝트에서도 빨리 응용해보고 싶어졌다.

이전 유튜브 프로젝트를 하면서 Mock Data가 필요해서 Postman을 처음 사용해보았는데, 그때도 그렇고 지금도 그렇고 미리 서버를 테스트를 해볼 수 있어서 정말 편리하고 서버 개발을 할 때 유요한 도구인 것 같다고 다시 한번 느꼈다.

이번 포스트를 작성한 이유는 다시 한번 복습을 하는 의미도 있었지만 흐름을 이해하고 기록을 하고 싶었기 때문이다. 프로젝트를 하다보면 중간에 에러를 만나거나 기능 구현을 시도하는 과정에서 흐름이 끊겨서 분명 전에 작성했던 코드인데도 프로젝트 전반적인 동작 과정이 희미해질 때가 있다. 다시 한번 코드를 파헤쳐보는 좋은 기회이기도 하지만 한번쯤은 이렇게 기록을 해보면서 전체 그림을 그려보는 것도 도움이 될 것이라고 생각했다.

0개의 댓글