nodeJS와 Express를 이용하여 서버를 구축해볼 것이다.
먼저 nodeJS와 Express가 무엇인지 알아보자.
nodeJS
JavaScript로 브라우저 환경이 아닌 서버 환경에서 실행할 수 있도록 한 런타임 환경
모듈화(내장 모듈 제공) - http, hs, path, cryto 등
예시) http 모듈 서버 생성
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello from Node.js!');
});
server.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});
Express
Node.js의 웹 서버 구축을 더 쉽게 해주는 Node.js 웹 애플리케이션 프레임워크
Node.js 의 내장 http 모듈을 간결하고 직관적으로 사용할 수 있게 한다.
- 경량 프레임워크: 웹 서버를 빠르게 구축할 수 있도록 제공.
- 미들웨어 지원: 요청 및 응답 처리 흐름을 조절.
- 라우팅 시스템: app.get(), app.post()와 같은 메소드 제공.
- 템플릿 엔진 통합 가능: Pug, EJS, Handlebars 등 지원.
- 확장성: 다양한 서드파티 미들웨어(body-parser, cors, morgan) 지원.
코드 예시
// node 모듈 안에 있는 express를 불러오겠다!, node_modules에 있는 express 모듈 import
const express = require("express");
// app => express 모듈을 활용할 수 있는 객체
// app 객체에 서버와 관련된 설정들을 적용할 수 있음
const app = express();
const port = 3000; // 실행될 포트 번호
// localhost(사용자)가 브라우저 http://localhost:3000/ 경로로 요청시 동작할 핸들러 함수
app.get("/", (req, res) => {
// 요청하면?
res.send("Hello World!"); // 동작!
});
// 특정 포트에서 실행되도록 설정(서버가 실행될 node.js 프로세스가 몇 번 포트에서 사용자의 요청을 대기하고 있을 것인지)
// 실행될 Node.js 프로세스가 몇번 포트에서 사용자의 요청을 대기하고 있을 것인지?
app.listen(port, () =>
console.log(
`http://127.0.0.1:${port}/ 서버 프로세스가 3000번 포트에서 실행 중입니다.`
)
);
특정 웹 페이지를 띄우고 싶을 때 어떻게 할까?
다음은 public 폴더 내에서 정적 파일을 서버에서 제공해주는 파일을 작성한 코드다.
public 폴더를 통해 정적 리소스를 제공하도록 하였고 루트 경로 시, index.html을 받아오도록 코드를 작성하였다.
const express = require("express");
const app = express();
const port = 3000; // 실행될 포트 번호
// 정적 리소스 호스팅, Express의 미들웨어 기능으로 활용
app.use(express.static("public")); // public이라는 이름의 폴더를 정적 리소스가 제공되는 경로로 적용
// lh:3-/로 접속 시 응답할 핸들러(엔드포인트)
app.get("/", (_, response) => {
response.sendFile("index.html"); // public/index.html 파일을 응답
});
app.listen(port, () =>
console.log(
`http://127.0.0.1:${port}/ 서버 프로세스가 3000번 포트에서 실행 중입니다.`
)
);
특징 | Node.js | Express.js |
종류 | 런타임 환경 | 웹 프레임워크 |
목적 | JS 실행 환경 제공 | 웹 애플리케이션 개발 편의성 제공 |
사용법 | 저수준 API 제공 (http) | 라우팅, 미들웨어 지원 |
기본 라우팅 지원 | X (직접 작성) | O (app.get()) 등 제공 |
미들웨어 지원 | 제한적 | 풍부한 미들웨어 지원 (body-parser) |
복잡도 | 상대적으로 복잡 | 더 간결하고 직관적 |
활용해보자!
그렇다면 클론 코딩했던 파파고 미니 프로젝트에서 NCP에서 제공하는 파파고 API를 활용하여 사용자가 언어를 입력하면 다른 언어로 자동으로 바뀌도록 해주는 기능을 구현해보겠다.
기본적인 데이터 흐름 구조는 다음과 같다.
클라이언트에게 데이터를 전달해줄 Node Server가 NCP에서 제공하는 파파고 API 두 개를 요청하여 받아와 클라이언트에서 사용할 수 있는 엔드포인트를 제공해주는 로직이다.
[언어감지]
https://api.ncloud-docs.com/docs/ai-naver-papagolanguagedetection-dect
[언어 번역]
https://api.ncloud-docs.com/docs/ai-naver-papagonmt-translation
Node Server 코드
import HTTP from "superagent"; // HTTP 요청을 간편하게 보내기 위한 라이브러리
import express, { json } from "express"; // express.json()을 간편하게 작성하기 위한 미들웨어로 JSON 데이터를 파싱할 수 있게 함.
const app = express();
const port = 3000;
const CLIENT_ID = "NCP 클라이언트 ID 키";
const CLIENT_SECRET = "NCP에서 받은 시크릿 키";
app.use(express.static("public"));
app.use("/api", express.static("public/api")); // /api 경로에 대해서도 public/api에서 정적 파일 제공
app.use(json()); // 미들웨어로 JSON 요청 본문을 자동으로 파싱
// lh:3-/로 접속 시 응답할 핸들러(엔드포인트)
app.get("/", (_, response) => {
response.sendFile("./index.html"); // 정적 HTML 파일을 클라이언트에 반환
});
// lh:3-/detect/로 요청 시 응답할 핸들러 - POST:/detect
app.post("/detect", (request, response) => {
console.log("POST:/detect called");
console.log(request.body);
const { query } = request.body; // 객체 디스트럭처링
// 언어 감지 요청 처리 로직
const DETECT_LANGUAGE_URL =
"https://naveropenapi.apigw.ntruss.com/langs/v1/dect";
const requestBody = {
query: query,
};
HTTP.post(DETECT_LANGUAGE_URL)
.send(requestBody)
.set("x-ncp-apigw-api-key-id", CLIENT_ID)
.set("x-ncp-apigw-api-key", CLIENT_SECRET)
.end((err, result) => {
if (result.status === 200) {
// 번역 결과 데이터
const resultData = result.body;
// 응답 객체를 통해 클라이언트로 응답
response.send(resultData);
} else {
console.error(err);
}
});
});
// lh:3-/translate로 요청 시 응답할 핸들러 - POST:/translate
app.post("/translate", (request, response) => {
console.log("POST:/translate called");
const TRANSLATE_LANGUAGE_URL =
"https://naveropenapi.apigw.ntruss.com/nmt/v1/translation";
console.log("Received Body:", request.body);
const requestBody = {
source: request.body.source,
target: request.body.target,
text: request.body.text,
};
HTTP.post(TRANSLATE_LANGUAGE_URL)
.send(requestBody)
.set("x-ncp-apigw-api-key-id", CLIENT_ID)
.set("x-ncp-apigw-api-key", CLIENT_SECRET)
.end((err, result) => {
if (result.status === 200) {
const resultData = result.body;
response.send(resultData);
} else {
console.error(err);
}
});
return;
});
app.listen(port, () =>
console.log(
`http://127.0.0.1:${port}/ 서버 프로세스가 3000번 포트에서 실행 중입니다.`
)
);
클라이언트 api.js 코드
// 언어 감지
export const detectLanguage = async (text) => {
let sourceLanguage; // 감지된 언어의 결과값을 담을 임시변수
const url = "http://127.0.0.1:3000/detect";
const body = { query: text };
// fetch API
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
};
await fetch(url, options)
.then((response) => response.json())
.then((data) => {
sourceLanguage = data.langCode;
});
return sourceLanguage;
};
// 번역
export const translateLanguage = async (source, target, text) => {
let targetData;
const url = "http://127.0.0.1:3000/translate";
const body = {
source: source,
target: target,
text: text,
};
// fetch API
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
};
await fetch(url, options)
.then((response) => response.json())
.then((data) => {
targetData = data.message.result;
});
return targetData;
};
클라이언트 app.js 코드
import { detectLanguage, translateLanguage } from "./api/api.js";
const [sourceSelect, targetSelect] = document.getElementsByTagName("select");
const [sourceTextarea, targetTextarea] =
document.getElementsByTagName("textarea");
let debounceTimeout;
let inputValue;
let sourceLang;
let targetLang = targetSelect.value;
sourceTextarea.addEventListener("input", (event) => {
if (debounceTimeout) clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(async () => {
inputValue = event.target.value;
const result = await detectLanguage(inputValue);
sourceSelect.value = result;
sourceLang = result;
targetTranslateFn();
}, 1000);
});
targetSelect.addEventListener("change", (event) => {
targetLang = event.target.value;
console.log(targetLang);
targetTranslateFn();
});
const targetTranslateFn = async () => {
const result = await translateLanguage(sourceLang, targetLang, inputValue);
console.log(result);
targetSelect.value = result.tarLangType;
targetTextarea.innerText = result.translatedText;
};
⭐️완성본⭐️
성공적으로 입력한 언어를 감지하고 타겟 언어에 맞게 잘 번역해주는 것을 볼 수 있다.
'JavaScript' 카테고리의 다른 글
[JavaScript] Ajax & XMLHttpRequest을 이용하여 서버 요청하기 (0) | 2025.01.12 |
---|---|
[JavaScript] Debounce와 Throttle에 대해 알아보자 (0) | 2025.01.08 |
[JavaScript/HTML] script 태그의 defer와 async 속성 알아보기 (1) | 2025.01.07 |
[JavaScript] 함수 정의(함수 선언문, 함수 표현식, Function 생성자, 화살표 함수) (0) | 2024.06.30 |
[JavaScript] var, let, const 비교 (+ 호이스팅 이해하기) (0) | 2024.06.28 |