Node.js 설치: 브라우저 없이 서버에서 버튼 작동 체크

공정위 광고 문구 Ver 3.1
공정위 광고 문구 Ver 3.2(모바일 전용)
테스트 환경RHEL 계열AlmaLinux 9.8root 계정2026-10-19 확인

서버에서 자바스크립트를 실행하려면 먼저 Node.js 설치가 필요합니다. Nginx와 Apache 구성의 워드프레스 서버에 Node.js 24.21.0을 설치하고, jsdom 30.1.3으로 브라우저 없이 웹 페이지의 버튼 스크립트를 검사했습니다.

기본 저장소의 nodejs는 16.20.2이며, 스크립트 검사에 사용할 jsdom 30.1.3은 Node.js 22.22.2 이상을 요구합니다. 그래서 dnf 모듈 스트림 24로 설치를 진행했습니다.

1️⃣ 서버에 Node.js와 jsdom 설치 목적

서버에서 버튼 스크립트를 검사하려면 Node.js와 jsdom 두 가지가 필요합니다.

🔲 Node.js

자바스크립트는 보통 브라우저 안에서 실행되지만, Node.js를 설치하면 서버에서도 자바스크립트를 읽고 실행할 수 있습니다.

Node.js를 설치하는 것은 브라우저 안에만 있던 자바스크립트 실행기를 서버에도 하나 두는 것입니다. 그래서 Node.js는 웹 서버를 만들거나, 여러 파일을 한꺼번에 처리하는 명령을 만들거나, jsdom 같은 패키지를 불러와 페이지를 검사할 때 사용합니다. Ghost도 Node.js 위에서 실행되는 CMS입니다.

🔲 jsdom

jsdom은 Node.js에서 사용하는 패키지로, HTML을 읽어 브라우저처럼 버튼을 누를 수 있는 문서로 만듭니다. 브라우저가 페이지를 열 때 만드는 문서 구조(DOM)를 화면 없이 서버 안에 그대로 만드는 방식이라, 스크립트는 실제 브라우저에 있는 것처럼 버튼을 찾고 글자를 바꿉니다. 창을 띄우지 않으므로 서버에서 명령 한 줄로 실행할 수 있습니다.

이는 곧 사람이 브라우저를 열어 하나씩 눌러 보던 확인을 서버가 명령으로 대신한다는 것입니다. 그래서 jsdom은 버튼 동작을 고칠 때마다 자동으로 시험하거나, 페이지에서 제목·링크 같은 내용만 뽑아내거나, 글 HTML을 한꺼번에 손볼 때도 사용합니다.

PHP나 curl로 페이지를 받으면 처음 내려온 HTML만 확인할 수 있습니다. 버튼을 누른 뒤 바뀌는 글자는 스크립트가 실행되어야 나타납니다.

브라우저는 페이지 받기, 페이지 읽기, 버튼 눌러 보기, 화면에 보여 주기의 네 단계를 거칩니다. jsdom은 화면에 보여 주는 단계만 빼고 나머지 세 단계를 서버에서 진행하므로, 버튼의 위치와 크기는 브라우저에서 확인합니다.

🧩 브라우저와 jsdom이 하는 일
설명 다이어그램
🖥️ 실행하는 쪽
페이지 받기서버가 보낸 HTML을 받음
페이지 읽기어디에 무엇이 있는지 파악
버튼 눌러 보기스크립트가 글자를 바꿈
화면에 보여 주기위치·크기·글꼴을 그림
글자 바뀜 ✓오류 ✓위치·크기 ✓위치·크기 ✗ (브라우저에서 확인)
브라우저는 네 단계를 모두 진행합니다.
jsdom은 앞의 세 단계만 서버에서 진행합니다.

2️⃣ 설치 전 확인: 기본 저장소와 모듈 스트림

[dnf install nodejs]를 실행하기 전에 설치될 판부터 확인합니다. AlmaLinux 9.8 기본 저장소의 nodejs는 16.20.2입니다.

dnf list --available nodejs
사용 가능한 꾸러미
nodejs.x86_64                    1:16.20.2-8.el9_4                     appstream

모듈 저장소에는 18, 20, 22, 24 네 스트림이 있으며, 확인일 기준 22 스트림은 22.23.2, 24 스트림은 24.21.0입니다.

dnf module list nodejs
nodejs 18     common [d], development, minimal, s2i Javascript runtime
nodejs 20     common [d], development, minimal, s2i Javascript runtime
nodejs 22     common [d], development, minimal, s2i Javascript runtime
nodejs 24     common [d], development, minimal, s2i Javascript runtime

npm 레지스트리 기준 jsdom 30.1.3이 요구하는 판은 22 계열 22.22.2 이상, 24 계열 24.15.0 이상, 또는 26 이상입니다. 22와 24 스트림 모두 이 조건을 충족합니다.

3️⃣ Node.js 설치: dnf module

이번에는 24 스트림을 설치했으며, 실행 전에 [--assumeno] 옵션으로 설치될 꾸러미 목록부터 확인했습니다.

dnf module install nodejs:24 --assumeno

목록에는 nodejs와 npm, nodejs-libs, nodejs-docs, nodejs-full-i18n 다섯 꾸러미만 있었습니다. 웹 서버와 PHP, 커널 꾸러미는 포함되지 않았습니다. 확인한 뒤 [-y] 옵션으로 설치를 진행합니다.

dnf module install -y nodejs:24
종속성이 해결되었습니다.
==============================================================================================
 꾸러미             구조    버전                                              저장소      크기
==============================================================================================
그룹/모듈 꾸러미 설치:
 nodejs             x86_64  1:24.21.0-1.module_el9.8.0+321+1555b6a2           appstream   70 k
 npm                noarch  1:11.19.0-1.24.21.0.1.module_el9.8.0+321+1555b6a2 appstream  2.1 M
종속 꾸러미 설치 중:
 nodejs-libs        x86_64  1:24.21.0-1.module_el9.8.0+321+1555b6a2           appstream   24 M
취약한 종속 꾸러미 설치 중:
 nodejs-docs        noarch  1:24.21.0-1.module_el9.8.0+321+1555b6a2           appstream  5.3 M
 nodejs-full-i18n   x86_64  1:24.21.0-1.module_el9.8.0+321+1555b6a2           appstream  8.9 M
모듈 프로파일 설치:
 nodejs/common                                                                                
모듈 스트림 활성화:
 nodejs                     24                                                                

연결 요약
==============================================================================================
설치  5 꾸러미

전체 내려받기 크기: 40 M
설치된 크기 : 185 M

[취약한 종속 꾸러미]는 함께 설치하면 좋은 꾸러미를 뜻하는 weak dependencies를 dnf 한국어 화면이 옮긴 말입니다. 내려받기 크기는 40M, 설치 크기는 185M입니다.

node -v
v24.21.0
npm -v
11.19.0
cat /etc/dnf/modules.d/nodejs.module
[nodejs]
name=nodejs
stream=24
profiles=common
state=enabled

node는 24.21.0, npm은 11.19.0으로 설치되었습니다. 설치 뒤 바뀐 설정 파일은 [/etc/dnf/modules.d/nodejs.module] 하나이며, 24 스트림과 common 프로필이 활성 상태로 기록됩니다.

4️⃣ jsdom 설치와 버튼 스크립트 검사

jsdom은 npm으로 작업 폴더에 설치하며, 작업 폴더는 웹 루트 밖에 만듭니다.

mkdir ~/jsdom-test && cd ~/jsdom-test
npm init -y

[npm init -y]는 기본값으로 package.json을 만들며, 이어서 같은 폴더에 jsdom을 설치합니다.

npm install jsdom
added 36 packages, and audited 37 packages in 2s

8 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
npm ls jsdom
jsdom-test@1.0.0 /root/jsdom-test
└── jsdom@30.1.3

jsdom 30.1.3을 포함해 패키지 36개가 설치되었으며, 알려진 취약점은 0건입니다. 작업 폴더의 node_modules 크기는 26M입니다.

node -e 'const { JSDOM } = require(`jsdom`); console.log(new JSDOM(`<h1>안녕</h1>`).window.document.querySelector(`h1`).textContent)'
안녕

h1 태그 하나로 된 HTML을 jsdom이 문서로 읽어, 그 안의 글자 [안녕]을 출력하면 작동 확인이 끝납니다.

버튼 스크립트 검사는 누른 뒤 글자가 제대로 바뀌는지를 서버에서 확인하는 일입니다. 예시로 [복사] 버튼을 누르면 글자가 [복사됨]으로 바뀌는 HTML 파일을 작업 폴더에 만들었습니다.

cat btn.html
<button id="copy">복사</button>
<script>
document.getElementById('copy').addEventListener('click', function () {
  this.textContent = '복사됨';
});
</script>

검사 스크립트는 HTML 파일을 jsdom으로 읽어 스크립트를 실행하고, 버튼을 누르기 전과 누른 뒤의 글자를 출력합니다. 스크립트 오류는 [오류:]로 시작하는 줄로 출력합니다.

cat check.js
const fs = require('fs');
const { JSDOM, VirtualConsole } = require('jsdom');

const vc = new VirtualConsole();
vc.on('jsdomError', (e) => console.log('오류:', e.message));

const dom = new JSDOM(fs.readFileSync(process.argv[2], 'utf8'), {
  runScripts: 'dangerously',
  virtualConsole: vc,
});
const btn = dom.window.document.querySelector('#copy');
console.log('누르기 전:', btn.textContent);
btn.click();
console.log('누른 뒤:', btn.textContent);
node check.js btn.html
누르기 전: 복사
누른 뒤: 복사됨

누른 뒤 글자가 [복사됨]으로 바뀌어, 버튼 스크립트가 작동하는 것을 확인할 수 있습니다.

스크립트에 오타가 하나 있으면 결과가 달라집니다. getElementById의 대문자 I를 소문자 l로 바꾼 파일로 같은 검사를 실행했습니다.

sed 's/getElementById/getElementByld/' btn.html > btn-broken.html
node check.js btn-broken.html
오류: Uncaught [TypeError: document.getElementByld is not a function]
누르기 전: 복사
누른 뒤: 복사

첫 줄에 오류가 출력되고 스크립트가 멈춰, 버튼을 눌러도 글자가 [복사]로 남습니다.

버튼에 CSS로 너비 120px, 높이 40px을 지정한 뒤 크기를 출력했습니다.

cat size.js
const { JSDOM } = require('jsdom');
const dom = new JSDOM('<button id="copy" style="width:120px;height:40px">복사</button>');
const btn = dom.window.document.querySelector('#copy');
console.log('높이:', btn.offsetHeight, '/ 너비:', btn.getBoundingClientRect().width);
node size.js
높이: 0 / 너비: 0

jsdom에는 화면에 그리는 단계가 없어 높이와 너비가 0으로 출력됩니다.

🔢 FAQ & 추천 콘텐츠

npm 레지스트리에 적힌 jsdom 30.1.3의 요구 판은 Node.js 22.22.2 이상, 24.15.0 이상 또는 26 이상이라, 18과 20 스트림은 이 조건에 포함되지 않습니다.

PATH에 없는 node는 [which node]에 나오지 않습니다. 확인한 서버도 [which node] 결과는 없었지만, pip 패키지 nodejs-bin으로 설치된 Node.js 18.4.0이 사용자 폴더 안에 있었습니다.

[d]는 기본값(default) 표시이며, common 프로필 뒤에 붙어 있으면 프로필을 지정하지 않고 설치할 때 common 프로필이 설치됩니다.

🧭 패키지 관리 추천 콘텐츠 글 9 · 참조 2
🗂️ 패키지 관리
📄 yum 명령어 📄 yum-config-manager 명령어 📄 RPM · YUM 차이 📄 apt · apt-get 명령어 📄 snapd 설치
📄 Node.js 설치 📄 CentOS 7 Nginx · PHP 설치 📄 phpMyAdmin 설치 📄 PHP-FPM 설치 및 설정
📡 DNF Module Command 📡 Node.js Previous Releases
yum check-update(yum-패키지 관리 명령어).png
Linux · 패키지
yum 명령어 | 사용법 | 옵션 | yum-utils | 패키지 관리와 저장소 관리🔝
레드햇 계열의 리눅스 배포판에서 사용하는 YUM 명령어는 패키지 관리(설치, 업데이트, 제거)를 하는데 사용하는 명령어입니다.
글 보기 →현재 콘텐츠
YUM 저장소_CentOS-Base.repo(CentOS 7)
Linux · 패키지
yum-config-manager 명령어 | YUM 저장소 설정
yum 명령어는 기본 사용 시 기본 저장소(보통 안정화 버전)에서 패키지를 설치합니다.
글 보기 →현재 콘텐츠
yum update
Linux · 패키지
리눅스: RPM, YUM 차이
RPM(Red Hat Package Manager)과 YUM(Yellowdog Updater, Modified)은 리눅스의 패키지를 설치하는 인스톨 프로그램입니다.
글 보기 →현재 콘텐츠
우분투(Ubuntu) 로고
Linux · 패키지
[Ubuntu] apt 명령어 | apt-get 명령어 사용법과 차이점
Red Hat 계열 리눅스에서는 패키지 관리를 위해 dnf 명령어를 사용하며, Debian 계열에서는 apt 명령어를 사용합니다.
글 보기 →현재 콘텐츠
리눅스Linux(회색 배경의 나무 큐브)
Linux · 패키지
Linux snapd | Rocky Linux에서 snapd 설치
스냅크래프트(Snapcraft) 또는 스냅(Snap)은 캐노니컬(Canonical)이 시작한 Ubuntu 스마트폰 운영 체제를 위한 소프트웨어 배포 및 패키지 도구로서 개발되었으며, 패키지 관리 시스템이다. 스냅(snap)이라고 불리는 패키지와 snapd를 사용하는 도구는 업스트림 소프트웨어 패키징을 간편화하여 다양한 리눅스 배포판에서 사용할 수 있도록 도와준다.
글 보기 →현재 콘텐츠

ℹ️ 제휴 안내
본 사이트의 콘텐츠에는 제휴 링크가 포함되어 있습니다. 방문자가 이 링크를 통해 상품 또는 서비스를 구매하면 본 사이트는 판매처로부터 수수료를 지급받습니다. 이 과정에서 구매자가 지불하는 금액(이벤트 할인 시 금액이 내려갑니다↓)은 오르지 않습니다. 게시된 가격·할인·재고 정보는 작성 시점 기준이며 실제와 다를 수 있으므로, 구매 전 판매처에서 최종 확인하시기 바랍니다. 상품 선정과 평가는 자체 기준에 따라 작성되며, 수수료 지급 여부가 소개 순서나 평가 내용에 영향을 주지 않습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

Prove your humanity: 4   +   10   =