본문 바로가기
Backend/Node.js

[Express] 정리 (1)

by 잘먹는 개발자 에단 2025. 4. 10.

먼저 처음에 다음 과 같은 모듈들이 필요하다.

const express = require('express')
const sql = require('mssql/msnodesqlv8');

- Express : 빠르게 웹 서버와 API 엔드포인트를 만들기 위해서

- mssql/msnodesqlv8 : SQL Server와 Node.js 간의 연결을 가능하게 해주는 라이브러리, Window 인증 ( Trusted Connection )을 지원한다. 

 

const config = {
  server: "ETHANGRAM",
  database: "HRDB2",
  options: {
    trustServerCertificate: true,
    trustedConnection: true, // Windows 인증 활성화
  },
};

* 윈도우 인증 trustedConnection

- Sql Server에 접속할 때 Window 운영 체제에 이미 로그인한 사용자의 자격증명을 사용하는 방식

- 사용자는 별도의 사용자 이름이나 암호를 입력하지 않아도, 현재 윈도우 사용자 계정의 자격증명으로 Sql Server에 접근할 수 있어서 편하고, 이를 갖다가 통합적인 보안이라고 한다.

* 데이터베이스 관리자가 Sql Server 인증 계쩡과 별도로 Active Directory를 사용해 사용자 권한을 관리할 수 있어서 중앙집중적으로 보안을 유지할 수 있다.

* Window 자체의 보안 메커니즘을 활용하기 때문에, 암호화와 인증과정이 보다 안전하게 이루어진다.

 

* trustServerCertificate 옵션

- 보통 암호화된 연결 SSL/TLS를 설정할 때 사용된다.

- 이 옵션을 true로 설정하면 클라이언트가 Sql Server로부터 받은 서버 인증서를 신뢰할 것을 강제한다.

- 하지만, 인증서를 따로 검증하지 않기 때문에, 개발환경에서는 편리하지만 운영환경에서는 보안 위험 ( 예를 들면 중간자 공격 등 )을 증가시킬 수 있다.

 

const port = 3001;

const poolPromise = sql
  .connect(config)
  .then((pool) => {
    console.log("SQL SERVER에 연결됨");
    return pool;
  })
  .catch((err) => {
    console.error("SQL SERVER 연결 실패", err);
    process.exit(1);
  });

* sql.connect(config) 

- sql server에 연결을 시도하고, 성공하면 연결 풀 pool 을 반환한다. 

    ㄴ 연결풀 : 한번 생성된 연결 풀은 여러 요청이 들어올 때 재사용되어 성능향상에 도움이 된다.

 

app.get("/flag", async (req, res) => {
  try {
    const pool = await poolPromise;
    const result = await pool.request().query(`
      SELECT TOP (1000) [id], [status], [description]
      FROM [Test].[dbo].[FLAG]
    `);
    res.json(result.recordset);
  } catch (error) {
    console.error("쿼리 실행 중 오류:", error);
    res.status(500).send("서버 내부 오류가 발생했습니다.");
  }
});

* app.get() 메서드

- 특정 경로에 대해서 GET 요청을 처리하는 라우트를 등록

- 첫번째 인자인 /flag는 요청 url 경로이다.

- 두번째 인자인 콜백함수는 요청이 들어왓을 때 실행되는 함수이며 두개의 인자를 받는다. 

    ㄴ req - request : 클라이언트 요청에 대한 정보를 담고 있다. 

    ㄴ res - response : 서버가 클라이언트에게 응답을 보내는데 사용된다.

 

* res.json() 메서드

- 결과를 json 형식으로 응답 본문에 담아서 전송한다.

 

* res.send() 메서드

- 문자열이나 버퍼, 객체 등을 그대로 응답할 때 사용된다.

 

* res.status() 

- 응답상태 코드를 설정할 때 사용되머, 메서드 체이닝으로 다른 응답 메서드와 결합할 수 있다. 

// POST : INSERT
app.post("/insert", async (req, res) => {
  try {
    // request body에서 데이터 추출출
    const status = req.body.status;
    const description = req.body.description;

    // 연결 풀 획득득
    const pool = await poolPromise;

    // SQL 쿼리 실행 시에, 입력값을 바인딩하여 SQL 인젝션 방지
    const result = await pool
      .request()
      .input("status", sql.NVarChar, status)
      .input("description", sql.NVarChar, description).query(`
        INSERT INTO [Test].[dbo].[FLAG] ( [status], [description])
        VALUES ( @status, @description) 
      `);

    // 성공적으로 삽입된 경우, 클라이언트에게 응답
    if (result.rowsAffected[0] > 0) {
      res.status(201).send({
        message: "데이터 삽입 성공",
        data: {
          status: status,
          description: description,
        },
      });
    } else {
      res.status(400).send("데이터 삽입 실패");
    }
  } catch (error) {
    console.error("쿼리 실행 중 오류:", error);
    res.status(500).send("서버 내부 오류가 발생했습니다.");
  }
});

* JSON 파싱 미들웨어. 

express가 들어오는 요청의 body를 자동으로 파싱할 수는 없다. Express.js에서 클라이언트로부터 JSON 형식의 요청 본문 body를 받으려면 해당 데이터를 자동으로 파싱하여 req.body 프로퍼티에 담아주기 위해서 반드시 미들웨어인 app.use(express.json())을 추가해야한다. 이 미들웨어는 들어오는 요청의 Content-Type이 application/json일 때 JSON 데이터를 파싱하여 Javascript 객체로 변환해주며, 이를 통해서 라우트 핸들러 내에서 편리하게 데이터를 사용할 수 있다. 

 

* GET and POST

- 일반적으로 POST 요청은 데이터가 요청 본문에 포함되어, URL에 노출되지 않고, GET 요청보다 민감한 데이터를 전송할 때 안전하다. 데이터 전송량도 GET 방식은 url 길이에 제한이 있지만, POST 방식은 대용량 데이터를 전송할 수 있어 파일 업로드나 복잡한 데이터 전송 시 유용하다.

 

* 요청 시 MIME 타입도 왠만하면 헤더에 명시해주는 것이 좋다. 웹에서 전송되는 문서의 종류를 명시하는 방법이다. 주로 text/plain이나 application/json등이 있다.

 

 

const compression = require("compression");
const express = require("express");
const app = express();

// 응답 압축 미들웨어 추가
app.use(compression());

app.get("/", (req, res) => {
  res.send("압축된 응답 데이터입니다.");
});

app.listen(3000, () => {
  console.log("서버 실행 중");
});

* 압축된 응답

- Express에서는 클라이언트로 보내는 응답 데이터를 압축할 수 있다.

- compression 패키지를 사용해야한다. 그러면 Express 어플리케이션이 클라이언트에게 보내는 데이터를 gzip 또는 deflate와 같이 압축할 수 있다. 

- 다만 압축또한 cpu 연산을 추가로 필요로 하기 때문에 부하나 상황을 적절히 잘 판단한다. 모든 요청에 대해서 무조건적으로 압축을 적용하지 않는다. 

- 압축을 해서 응답을 하게 되면, 브라우저에서는 이를 자동으로 압축해제한다. 따로 추가적인 처리를 할 필요는 없다. 다만, http 요청시에 Accept-Encoding 헤더를 통해 어떤 압축 방식을 지원하는지 알리므로, 서버는 그에 맞춰서 응답을 압축하게 된다. 

 

 

 

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

* app.listen() 메서드 

- 지정한 포트에서 HTTP 서버를 실행하며, 클라이언트의 요청을 수신할 준비를 한다.

- 두 번째 인자로 전달한 콜백 함수는 서버가 시작되면, 실행되어 확인 메시지를 콘솔에 출력한다.

- Node.js의 기본모듈 http.createServer()를 사용해서 서버를 생성할 수도 있지만, Express를 사용하면 라우팅과 미들웨어 관리가 훨씬 간편해짐. 

 

 

'Backend > Node.js' 카테고리의 다른 글

Passport 인증 미들웨어  (0) 2025.04.22