이전 글에 이어서 이번 시간에는 xterm.js, node-pty를 활용하여 웹 터미널을 만들어 보도록 하겠습니다. 웹 터미널을 구현하기 위해 크게 프론트엔드, 백엔드, 서버 이렇게 3개의 파트가 준비되어야합니다. 프론트엔드는 React, 백엔드는 NodeJS를 활용하고 언어는 TypeScript로 작성하였습니다. 먼저, 프론트엔드 파트부터 천천히 살펴보겠습니다.

웹 터미널 구현을 위해 첫 번째로 할 일은 React 프레임워크를 가지고 xterm.js 모듈로 웹 터미널의 껍데기를 만들겁니다. 웹 터미널 라이브러리화도 고려할 것이므로 초기에 이것저것 설정해야할 것이 있습니다. 기본적인 prettier, eslint, tsconfig 설정을 더불어 라이브러리 개발 환경을 위해 rollup 모듈을 사용합니다. rollup 모듈에 대해서 알고 싶다면 이 글을 추천드립니다. React 개발 환경에서 lib 디렉터리를 만들어 이 곳에서는 웹 터미널 라이브러리를 코드를 작성하도록 합니다. 그리고 npm link로 웹 터미널 라이브러리 링크를 만들어 쉽게 라이브러리 개발을 할 수 있도록 설정합니다.

├── frontend # 최상단 디렉터리
│   ├── lib # 웹 터미널 라이브러리 코드
│   │   ├── dist
│   │   ├── package.json
│   │   ├── rollup.config.js
│   │   ├── src
│   │   ├── tsconfig.json
│   ├── node_modules # lib 디렉터리 npm link로 연결
│   ├── package.json
│   ├── public
│   ├── src # 웹 터미널 모듈을 가져다 쓸 React 코드
│   └── tsconfig.json
cd frontend/lib
npm link

cd ..
npm link webterminal

React 코드를 수정하면 hot reload가 되어 브라우저에 바로 반영이 되고, 웹 터미널 라이브러리 코드를 수정하면 라이브러리가 자동 빌드가 되도록 package.json에 다음과 같이 스크립트를 작성하고 실행하면 더욱 빠르게 개발을 진행 할 수 있습니다.

...
"scripts": {
    "dev": "yarn dev:lib & yarn start",
    "dev:lib": "cd lib && yarn watch",
    "start": "react-scripts start"
},
...

개발 환경 설정을 하였으니 간단하게 코드를 작성해봅시다. lib 디렉터리로 이동하여 xterm.js 모듈로 웹 터미널 껍데기를 만듭시다.

// lib/src/WebTerminal/WebTerminal.tsx

import React, { useEffect } from 'react';
import { Terminal } from 'xterm';

import 'xterm/css/xterm.css';

const WebTerminal = () => {
    useEffect(() => {
        const terminal = new Terminal();

        terminal.open(document.getElementById('terminal') as HTMLElement);
        terminal.write('Hello from \\x1B[1;3;31mxterm.js\\x1B[0m $ ');
    }, []);

    return <div id="terminal" />;
};

export default WebTerminal;

React 쪽 코드는 다음과 같이 작성하고 yarn start으로 실행하면 브라우저에 웹 터미널을 볼 수 있습니다.

// src/App.tsx

import React from 'react';
import WebTerminal from 'WebTerminal';

import '../lib/node_modules/xterm/css/xterm.css';

const App = () => {
    return (
        <div className="App">
            <WebTerminal />
        </div>
    );
};

export default App;

축하드립니다. 웹 터미널을 만들었습니다. 👏👏👏

나의 소중한 웹 터미널

나의 소중한 웹 터미널