Day 9 : 에러나면 손모가지 날라가붕께

2023. 5. 30. 16:19International Sign Lang 프로젝트/백엔드

728x90
 

Day 8 : 가상 DOM 생성, 웹 스크래핑, 및 JSON 데이터 MySQL 저장 (후 많다 많아)

Day 7 : 왜 굳이 웹 서버 프레임워크를 사용해야 하나? 2023.05.24 - [Project ISL/프론트엔드] - Day 6 : 첫걸음은 '레이아웃 설계'로부터 Day 6 : 첫걸음은 '레이아웃 설계'로부터 2023.05.18 - [Project ISL/프론트

xpmxf4.tistory.com

이전 글을 읽어와 주시면 감사하겠습니다 :)


오늘은 API 를 바로 작성해 볼 것입니다!

하지만 언제나 제가 글에서 얘기하듯, 무턱대고 코드 짜는 건

장기적인 관점에서... 는 사실 단기적인 관점에서도 지'양'할 일이죠.

 

그리고 아직 Node+Express 에 갓입문한 병아리이기 때문에

API를 작성하기 이전에 라우터에 관련한 세팅이라던지

REST API 작성을 고려한 설계에 대한 고민이 필요합니다.

 

1. app.js 란? 세팅하기

먼저 Express의 기본 구조는 다음과 같습니다.

app.js
이 파일은 주로 애플리케이션의 중심, 실행 주체 역할을 합니다.
Express 앱 설정, 미들웨어 설정, 라우팅 설정 등 대부분의 주요 설정이 이 파일에서 이루어집니다.
bin
이 폴더는 일반적으로 애플리케이션을 시작하는 스크립트를 포함하고 있습니다.
예를 들어, www 파일은 애플리케이션의 서버를 시작하는 데 사용됩니다.
package.json
이 파일은 NPM(Node Package Manager)에서 사용하는 것으로,
프로젝트의 메타데이터와 프로젝트에서 사용하는 의존성(dependencies)을 정의합니다.
public
이 디렉토리는 정적 파일들(HTML, CSS, JavaScript, images 등)을 저장하는 곳입니다.
이 파일들은 직접적으로 클라이언트에 서빙됩니다.
routes 
이 폴더는 라우팅 로직을 포함합니다. 여기에는 특정 URL 패턴에 응답하는 라우트 핸들러가 정의됩니다.
views
이 폴더는 템플릿 엔진을 사용하여 렌더링 될 뷰 파일들을 포함합니다.
예를 들어, EJS나 Pug와 같은 템플릿 엔진을 사용하여 HTML을 동적으로 생성할 수 있습니다.
이 폴더에는 HTML 레이아웃과 템플릿들이 저장됩니다.

과거 웹 애플리케이션의 방식이던 SSR의 방식을 채용한다면

위에 있는 모든 파일과 폴더들은 필수요소입니다.

 

하지만 이번 프로젝트에서 서버는 프론트엔드 쪽과 REST API를 통한

JSON 형식의 데이터만 주고받는 식의 통신만 할 예정입니다.

즉, 템플릿 엔진에 관련한 폴더인 public, views 가 필요가 없습니다.

 

그렇다면 다음처럼 남게 됩니다.

app.js
bin
package.json
routes

그렇다면 우리의 설정이 끝났을 까요?

아니죠, 서버의 설정을 담당하는 app.js 에서의 설정을 고쳐야 합니다!

 

원래 app.js의 코드는 다음과 같습니다

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function (req, res, next) { next(createError(404));});
// error handler
app.use(function (err, req, res, next) {
     // set locals, only providing error in development res.locals.message = err.message; res.locals.error =                   req.app.get('env') === 'development' ? err : {};
     // render the error page res.status(err.status || 500);
     res.render('error');});

module.exports = app;

길다 그죠...?

여기서 템플릿 엔진에 관한 설정을 지우면 다음처럼 됩니다!

var express = require("express")
var path = require("path")
var cookieParser = require("cookie-parser")
var logger = require("morgan")

var indexRouter = require("./routes/index")
var usersRouter = require("./routes/users")

var app = express()

app.use(logger("dev"))
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
app.use(cookieParser())

// routers
app.use("/", indexRouter)
app.use("/users", usersRouter)

템플릿 엔진에 관한 코드는 전부 없애도 무방합니다!

 

2. 이제야 첫 API 작성

과거에 작업했던 저의 법규 날리기 페이지입니다!

저렇게 법규를 날리면 프론트엔드 쪽에서는

사용자의 IP에서 from_country와 클릭한 나라(path태그)의 to_country를 body에 담아

POST 형식으로 백엔드에 날리게 하도록 설계했습니다!

// app.js
var countriesRouter = require("./routes/countries")
app.use("/countries", countriesRouter)

// countries.js
const express = require("express")
const router = express.Router()

router.post("/", function (req, res) {
    const from_country = req.body.from_country
    const to_country = req.body.to_country

    // 올바른 데이터를 받았는지 확인하는 로직
    // DB 에 저장하는 작업

    res.json({
        message: "Data Received",
        from_country: from_country,
        to_country: to_country,
    })
})

생각보다 간단합니다만 `/countries` API는 프론트에서

from_country와 to_country를 받아서 DB까지 넣는 것이 역할입니다!

그전에 먼저 들어온 데이터에 대한 유효성 체크를 해야겠죠!

데이터 유효성 검증

// 올바른 데이터를 받았는지 확인하는 로직
    if (from_country.length !== 2 || to_country.length !== 2) {
        return res.status(400).json({
            error: "Invalid country code",
        })
    }

모든 국가코드는 2글자이기 때문에

들어온 값이 2글자가 아니라면 400번 에러를 response로 돌려주기로 설정했습니다!

 

이제는 DB 에다가 값 넣기!

이제 거의 다 왔습니다!!

 

제 DBMS는 mysql 이기 때문에 mysql 모듈을 다운받고

해당 모듈을 통해 DB에 대한 connection을 진행하겠습니다!

 

const mysql = require("mysql2")
const fs = require("fs")

const [host, user, password, database] = fs.readFileSync("database_config.txt", "utf8").split("\n")

const db = mysql.createConnection({
    host,
    user,
    password,
    database,
})

router.post("", function (req, res) {
    const from_country = req.body.from_country
    const to_country = req.body.to_country

    if (from_country.length !== 2 || to_country.length !== 2) {
        return res.status(400).json({
            error: "Invalid country code",
        })
    }

    const query = "INSERT INTO isl (from_country, to_country) VALUES (?, ?)"
    db.query(query, [from_country, to_country], function (err, result) {
        if (err) {
            console.log(err)
            return res.status(500).json({
                error: "Database error",
            })
        }

        res.json({
            message: "Data Received",
            from_country: from_country,
            to_country: to_country,
        })
    })
})

mysql connection을 만들 때 사실

파라미터 안에다가 하드코딩으로 user와 password 값을 가져와도 되지만

그렇게 할 경우, github에 올렸을 때 저의 아이디와 패스워드는 공공재 급으로 변하겠죠...?

그래서 이런 보안이 중요한 경우 외부 파일로 저장하고, 이를. gitignore 에다가 저 정합니다!

 

특이한 게 있다면, 제가 mysql 모듈을 가져와야 한다고 해놓고선

mysql2 모듈을 가져왔습니다!

구라치다 걸리믄 알제?

원래는 mysql 모듈로 코드를 작성했었는 데

전혀 예상하지 못한 에러를 만나게 되어 mysql2 모듈로 수정을 하게 되었습니다!

이에 대한 글은 다음에서 확인해주세요!

 

 

Day 10 : MySQL2 오류, "Client does not support authentication protocol requested by server" 해결 방법

Day 9 : 에러나면 손모가지 날라가붕께 더보기 Day 8 : 가상 DOM 생성, 웹 스크래핑, 및 JSON 데이터 MySQL 저장 (후 많다 많아) Day 7 : 왜 굳이 웹 서버 프레임워크를 사용해야 하나? 2023.05.24 - [Project ISL/프

xpmxf4.tistory.com

 

성공적!

TIL

새로운 프레임워크를 사용하다 보니 단순한 API를 작성하는 것도 오래 걸리더라고요... 배움의 길은 멀다

그래도 설계를 다 하면서 하니 계속 진도를 나아가는 데 있어서 나의 판단에 대한 의구심이 없어지는 것을 

느낄 수 있었기에 예전보다 성장했다는 것을 배울 수 있었습니다!

 

GITHUB

https://github.com/xpmxf4/ISL_BackEnd

 

GitHub - xpmxf4/ISL_BackEnd

Contribute to xpmxf4/ISL_BackEnd development by creating an account on GitHub.

github.com

보셨다면 스타 하나 부탁드리겠슴돠!!!!

그리고 언제나 피드백은 환영입니다 :)

728x90