Node.js 외부 파일로 HTML 양식 만들어 사용하기: fs 모듈 이용

Node.js fs 모듈

Node.js 파일 시스템 모듈(fs) 을 정리하며 서버 내 만들어준 파일을 불러와 변수에 담아 사용하는 방법을 알 수 있었습니다.

이를 보니 제가 회사에서 mustache 파일로 HTML 양식을 미리 만들어 둔 후 require([‘mustache’]), … 식의 코드로 불러와 사용하고 있습니다.

이 방식을 회사 운영 중인 웹 사이트를 개발한 솔루션이 사용하고 있어 자체 제작 인가 했더니 검색해보니까 RequireJS 라는 라이브러리의 텍스트 플러그인으로 동일한 형태로 사용하는 것 보니까 이를 이용한 것 같네요.

잡설이 길었는데, 그러다 보니 외부 파일로 아예 HTML 을 작성해 이를 별도의 파일로 작성하여 불러오는 방식에 적응 되어 있어 Node.js 에서 이런 방식으로 구현할 수 없을까? 생각이 들었습니다.

궁금할 때는 바로 해봐야겠죠!

HTML 양식 만들기

Node.js Project 내에 간단한 불러올 HTML 양식을 만들어 보겠습니다. 이 양식은 파일 명 updateLog.html 에 저장 하였습니다.

<h1>Update Log</h1>
<p>2024-04-05: fs 모듈을 통한 양식 불러오기 기능이 추가 되었습니다.</p>
HTML

아래는 메인 이 될 웹 페이지 HTML 문서 입니다. 이 양식은 index.html 에 저장 하였습니다.

<!DOCTYPE html>
<html>
<head>
    <title>첫 화면</title>
</head>
<body>
    <h1>Hello, World!</h1>
    <p>이 화면은 첫 화면 입니다.</p>
</body>
</html>
HTML

fs 모듈로 HTML 양식 불러오기

방금 만들어진 파일을 한번 불러오겠습니다. 제가 만든 HTML 파일의 이름, 경로에 맞춰 작성 되었으므로 자신의 파일 위치에 맞춰 인수를 수정하시면 됩니다.

여기서 주의하셔야 할 점은 인수 ‘utf8’ 입니다. 이 인수가 없이 HTML 파일을 읽어오면 Buffer 객체로 출력 됩니다.

정상적으로 가져 왔다면 터미널에 updateLog.html 안의 내용이 출력 됩니다.

const fs = require('fs');

const data = fs.readFile(__dirname + '/updateLog.html', 'utf8', (err,data) => {
  if (err) throw err;
  console.log(data);
});
JavaScript

app.js HTML 리턴 엔드포인트(endpoint) 추가

자, 그러면 이 가져온 코드는 어떻게 index.html 화면에 보낼 수 있을까요?

저는 이 작업을 Express 프레임워크를 이용해 웹 애플리케이션으로 제공하고 있고 index.html 은 다음과 같은 코드에 의해 localhost:3000 주소로 에서 동작하게 만들어져 있습니다.

이 내용은 Express HTML 페이지를 렌더링(보여주는)하는 방법 | Node.js 게시글에 상세하게 정리하고 있어요.

// app.js
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
});

app.listen(port, () => {
    console.log(`Server is running on http://localhost:${port}`);
});
JavaScript

이 코드를 기반으로 방법을 고민하던 도중 저는 불러온 html 파일 내용을 클라이언트에 응답해 주는 코드를 별도로 만들고 index.html 페이지 내에서 불러오면 되겠구나? 생각이 들었습니다.

이 방법을 위해 주목해야 할 것은 app 변수에 사용 중인 get() 메소드 입니다. 이 메소드의 첫 번째 인수로 받는 값은 웹 주소의 경로가 됩니다.

예로 들어 위의 코드는 인수로 ‘/’ 값이 작성되어 있죠. 그래서 http://localhost:3000/ 으로 접속이 될 겁니다. 접속을 하게 되면 위의 작성한 html 페이지가 출력되죠.

Express 코드 실행 결과

응답객체 res 의 json() 메소드

이 코드에서 get 메소드 내의 코드는 sendFile() 메소드 을 통해 html 파일 등 파일의 내용을 요청을 한 클라이언트에게 전송하고 있습니다.

Express의 res 객체엔 기존 포스팅에서 다루었던 send(), sendFile() 메소드 외에도 여러 메소드 가 있는데 이번에 사용한 메소드는 json() 메소드 입니다.

json() 메소드는 클라이언트가 요청 할 경우 JSON 형태의 값을 전송합니다. JSON 은 JavaScript Object Notation 의 줄임 말로 데이터의 표현을 JavaScript 의 객체(Object) 방식으로 약속해 각 시스템 끼리 주고 받자는 의미 입니다.

이를 이용해 작성한 html 파일 내의 내용을 리턴 하기 위해 만든 새로운 엔드포인트 코드는 다음과 같습니다.

app.get('/updateLog', (req, res) => {
    const data = fs.readFile(__dirname + '/updateLog.html', 'utf8', (err,data) => {
        if (err) throw err;
        const jsonObj = {
            updateLog: data
        }
        res.json(jsonObj);
    });    
});
JavaScript

이 코드는 클라이언트가 http://localhost:3000/updateLog 를 브라우저 등에서 요청할 경우 jsonObj 변수의 내용을 반환 합니다.

브라우저로 해당 URL 을 접속하면 이 데이터 내용이 표시 됩니다.

http://localhost:3000/updateLog 접속 결과

index.html 에서 updateLog JSON 값 가져오기

거의 다 왔습니다. 이제 저 위의 값을 index.html 에서 가져올 겁니다. 이 때 이용할 것은 JavaScript 의 fetch() 함수 입니다.

fetch() 함수

fetch() 함수는 웹 브라우저에서 제공하는 API 이며 인자로 URL 을 제공하면 서버의 응답을 변수에 담아 보여줍니다.

Internet Explorer 를 제외한 최신 웹 브라우저 라면 대부분 지원하고 있고 2015년 쯤 등장하여 사용되고 있습니다.

설명을 들으면 감이 오시죠? 저희는 이 함수를 이용해서 아까 만든 URL 에 요청에 JSON 값을 리턴 받아 보겠습니다.

이는 index.html 에서 필요할 때 fetch() 함수로 불러올 겁니다. 작성된 html 코드는 다음과 같습니다.

<!DOCTYPE html>
<html>
<head>
    <title>첫 화면</title>
</head>
<body>
    <h1>Hello, World!</h1>
    <p>이 화면은 첫 화면 입니다.</p>

    <script>
        fetch('/updateLog')
            .then(response => response.json())
            .then(data => console.log(data))
            .catch(error => console.error('Error:', error));
    </script>
</body>
</html>
HTML

그럼 메인 화면에 접속해서 console.log 가 정상적으로 출력 되는지 확인 하겠습니다.

fetch() 함수 리턴 결과

불러온 html 기존 문서에 추가 하기

위처럼 객체(Object) 형태로 데이터가 잘 넘어왔고 updateLog 안엔 html 내용이 텍스트로 들어 있습니다. 그럼 이를 문서 내에 한번 추가해 보겠습니다.

<!DOCTYPE html>
<html>
<head>
    <title>첫 화면</title>
</head>
<body>
    <h1>Hello, World!</h1>
    <p>이 화면은 첫 화면 입니다.</p>

    <script>
        fetch('/updateLog')
            .then(response => response.json())
            .then(data => {
                const html = data.updateLog; //객체 내 updateLog 값 가져오기
                document.body.innerHTML += html; //기존 내용에 텍스트로 된 html 내용 추가 
            })
            .catch(error => console.error('Error:', error));
    </script>
</body>
</html>
HTML

해당 코드로 인해 반환 받은 태그 내용을 body 에 추가 했습니다. 잘 동작합니다.

불러온 내용 html 내용

HTML 외부 파일로 분리하는 것이 좋은가?

사실 이런 식으로 HTML 파일을 분리해서 상용 하는 것 자체에 문제가 있진 않지만, 잘 사용되는 방법은 아니라고 합니다.

이런 식으로 양식을 별도의 템플릿(Template) 으로 두고 사용하려면 이런 방식이 아닌 템플릿 엔진(Template Engine)이라 불리 우는 동적 HTML 생성하기 위한 도구, 라이브러리를 사용합니다.

저도 이렇게 구현해 봤지만 생각보다 효율적으로 보이진 않네요. 다음번엔 템플릿 엔진을 사용한 포스팅을 작성해 보겠습니다.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x
목차
위로 스크롤