본문 바로가기
Programming/Pyodide Wasm

Pyodide 사용해보기 (1) - Node .js 테스트 서버 구축

by dinB 2021. 7. 14.

최근 진행하는 프로젝트 때문에 클라이언트가 웹 상에서 다른 언어(파이썬)를 사용해야하는 일이 생겼다.

 

이를 위해서 고민하던 중, 마침 Pyodide라는 웹 어셈블리(WASM)가 눈에 들어왔고, 일단 WASM의 목적과 이에 대한 자세한 내용은 이하의 링크를 정독하자. (사실 컨셉을 이해하는데에 매우 도움이 된다.)

 

 

웹어셈블리의 컨셉 - 웹어셈블리 | MDN

본 글에서는 웹어셈블리의 작동원리 뒤에 숨어있는 컨셉을 설명함과 동시에 웹어셈블리의 목표, 웹어셈블리가 해결할 수 있는 문제, 그리고 웹브라우저 렌더링 엔진 안에서 웹어셈블리가 작

developer.mozilla.org

 

1. Pyodide WASM

Pyodide는 본래에는 웹 브라우저로 유명한 Firefox의 Mozila에서 시작한 웹 어셈블리 프로젝트로, 2021년 기준으로는 독립적인 프로젝트로 개편되어 개발 중이며, 현재까지 0.17까지 나온 것으로 알려져있다. 그리고 0.17 버전은 Python 3.8을 사용할 수 있다. (0.16은 Python 3.7로 알고 있음.)

 

무엇보다 Javascript 상에서 Python을 사용할 수 있다는 것이 특징이며,

사실 엄청난 장점은 파이썬의 데이터 사이언스 라이브러리인 Numpy, Pandas, Matplotlib을 넘어 Scipy, 그리고 머신러닝 라이브러리인 Scikit-learn까지 사용할 수 있다는 것이다! (와... 짝짝.. 정도)

 

뿐만 아니라 "어 이것도..?" 라는 말이 나오는 라이브러리도 지원해주니, 궁금하다면 링크를 참조하자!

 

pyodide/pyodide

Python with the scientific stack, compiled to WebAssembly. - pyodide/pyodide

github.com

 

그리고 특히 시각화 라이브러리인 Matplotlib을 활용한 그래프도 웹 상에 그릴 수 있겠지... (그렇다면 파이썬 개발자의 입장으로서 Plotly.js와 같은 자바스크립트 라이브러리를 사용하지 않고도 그래프를 그릴 수 있기에 오히려 이득일 수도 있다.)

 

2. 목적

본 포스팅과 이후에 작성할 포스트는 순전히 메모용으로 작성하기 위한 본 블로그의 목적답게, 상세한 설명보다는 내가 프로젝트를 진행하며 겪는 여러 문제들, 개선할 점들, 새로 알게 된 점들을 메모하기 위해 작성되었다.

 

그래서 두서가 없을 수도 있다.

 

3. 개발

별 거 없다. 단순한 Node.js 서버를 만들어서 Pyodide WASM으로 동작하는 콘솔을 만들고, 이마저도 그나마 매우 미개한 디자인으로 만드는 것이 다일 뿐....

 

4. 시작 - 테스트 페이지를 위한 간단한 Node.js 서버 만들기

이제 아주 간단한 것들부터 시작해보자. 아주 간단한 웹 조차 서버로 관리하는 게 가장 기본적인 것들을 잊지 않기 위한 최선의 방법일 것이다!

 

가장 먼저 Node.js를 위한 서버를 만들어보자.

 

본 포스팅에서는 2021년 기준 Node.js 14.17.0 을 사용하였다. 없다면 다운 받자!

 

 

Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

그리고 본 포스팅에서는 Visual Studio Code를 사용할 것이다. 이 툴은 자바스크립트나 웹 기반의 소스를 작성할 때 엄청나게 효율적이며, 일단 가볍다. 이것보다 더 좋은 웹 개발 IDE는 없을 것 같...다...

 

이것도 없다면 다운하자~!

 

Visual Studio Code - Code Editing. Redefined

Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com

이하는 VSCODE를 설치하고 초기화면이다!

Fig. 1. Visual Studio Code 초기 화면

필자는 Workspace로 pyodide-test 라는 폴더를 만들고, 이 경로로 VSCODE에서 접근하였다.

 

그리고 VSCODE에서 Terminal을 연 후, 다음 그림과 같이 NPM을 초기화해준다.

 

Fig. 2. NPM 초기화

사실 이 정도면 모두 알 듯하다. 우리는 Node.js를 활용할 것이고, 그 중 express를 활용할 것이므로 가장 먼저 NPM 패키지를 초기화 해준다.

 

많은 커맨드가 나온 이후, 쭈우욱 진행하면

 

Fig. 3. NPM 초기화 이후 생성 파일

package.json이 생성된다. 뭐 이건 다른 분들 포스팅에서 좀 더 자세하고 친절하게 알려주시니 여기서는 간단히만 알아보자.

 

Fig. 4. package.json

NPM을 초기화하면 다음과 같은 JSON 파일이 생성된다. 다른거 다 신경 쓸 필요는 없고, Key 중에서 "main"을 확인해보니 index.js 라고 표시되어 있다. 이는 서버 파일이 index.js가 될 것임을 의미한다.

 

만일 server.js로 변경하면 server.js 파일에 서버를 만들어주면 된다.

 

지금은 아무런 Node 모듈도 존재하지 않는다. 우리는 express를 활용할 것이므로 다운받아주자.

 

Fig. 5. Install express

간단히 express를 다운받는다. 이때 --save 명령을 사용함으로써 package.json에 명시될 수 있도록 한다.

 

Fig. 6. Install Nodemon

그 다음으로는 Nodemon을 다운받아준다. 이 모듈은 매우 유용한데, 기존 Node 서버에서 어떠한 로직을 수정하면 필연적으로 서버를 닫은 후, 다시 실행시켜주었어야 했다.

 

그러나 Nodemon을 통해 서버를 실행시키면, 서버 단에서의 수정 사항이 발생하면 자동으로 이를 캐치하여 재실행시켜준다. (마치 리액트의 서버 버전 같은 정도...)

 

자, 그럼 제대로 설치되었는지 확인하기 위해 package.json 파일을 다시 확인해보자.

 

Fig. 7. package.json

<그림 7>과 같이, package.json에 방금 설치한 express와 nodemon이 설치됨을 확인할 수 있다.

 

그럼 이제 본격적으로 서버 파일을 작성해보자.

 

가장 먼저, 우리가 작업할 디렉토리에 다음 그림과 같이 index.js 파일을 생성해준다.

 

Fig. 8. 서버 파일 생성

이제 이 파일에 매우 간단한 express 서버를 작성해 줄 것이다.

const express = require('express'); // Express 불러오기
const app = express(); // Express 생성
const port = 3000; // Port 초기화

// Express 서버 생성
app.listen(port, () => {
    console.log(`Server is running at ${port}`);
})

이게 끝이다. 그럼 다음 터미널 명령어를 통해 서버를 실행시켜보자.

 

Fig. 9. Node 서버 실행

Node.js를 활용하여 서버를 실행시키려면 node 명령어를 통해 서버 파일인 index.js 파일을 실행시키면 된다.

실제로 구동하면 방금 작성한 console.log에서 출력되는 내용을 통해 로직이 정상적으로 작동함을 확인할 수 있다.

 

작성한 서버에 대한 포트를 3000번으로 지정했으니, 서버 실행 후 이하의 주소로 접근해서 확인해보자.

URL : http://localhost:3000

 

Fig. 10. 서버 실행 결과

일단은 접속은 된다. 그런데 접근할 수 없다고 나온다. 이는 페이지가 없기 때문이다.

 

그럼 페이지를 만들어주면 된다.

그런데 여기서는 페이지를 만들기에 앞서, 간단한 문구를 먼저 출력해주는 것이 나을 것 같다.

const express = require('express'); // Express 불러오기
const app = express(); // Express 생성
const port = 3000; // Port 초기화

// 라우팅 추가
app.get('/', (req, res) => {
    res.send("Hello, Node.js!");
})

// Express 서버 생성
app.listen(port, () => {
    console.log(`Server is running at ${port}`);
})

이는 위에 있는 코드와 동일하나, 주석으로 "// 라우팅 추가" 부분만 추가되었다.

 

이것이 의미하는 바는, 클라이언트 측으로부터 "/", 즉 http://localhost:3000/ 으로 접근하였을 때 보여줄 내용을 정의한 것이다.

 

여기서는 res.send()를 통해 단순 텍스트를 보여주도록 설정해주었다. 그럼 실행 결과를 확인해보자.

참, 그런데 서버 단이 수정되었으므로 이미 실행 중인 서버가 있다면 이를 종료해주고, 재실행해주어야 한다.

 

누누히 말하지만 Node.js 서버 개발에 대한 내용이 아니라, Pyodide 사용을 위한 전처리 작업이므로 서버 개발에 대한 자세한 내용은 다른 좋은 블로그들이 많으니 이들을 참고하도록 하자!

 

아무튼 이제 터미널에서 "node index.js" 명령어를 통해 서버를 재실행 후 다시 확인해보자.

 

Fig. 11. 서버 재실행 후 결과

우리는 방금 res.send()에 "Hello, Node.js" 텍스트를 인자로 넣어주었기 때문에 <그림 11>과 같은 결과를 얻어낼 수 있었다.

 

그런데 생각해보자, 서버를 변경할 때마다 이렇게 직접 서버를 끈 후, 다시 키는게 여간 번거로운 일이 아닐 수 없다.

따라서 우리가 방금 NPM을 통해 설치한 Nodemon을 활용해보도록 하자!

 

Fig. 12. nodemon 활용을 위한 package.json 수정

package.json 파일을 살펴보면, script 라는 key가 존재한다. 여기 하단에 "dev" 라는 key를 생성하고, 이 key에 대한 value로 "nodemon index.js"를 적어준다.

 

이때 key의 역할을 하는 "dev"는 아무런 이름으로 적어주면 되고, "dev" key에 대한 value로는 "nodemon index.js"를 적어주었는데, 여기에서 파일명은 본인이 정의한 서버 파일을 적어주면 된다.

 

Fig. 13. Nodemon 실행

package.json에 script를 정의하였으면, "npm run dev"를 통해 실행시켜주면 된다.

 

만일 "dev"가 아닌 "start"로 정의하였으면, "npm run start"를 적어주면 된다.

 

이제 서버 로직이 변경되면 수동으로 서버 재시작을 해 줄 필요가 없이, 자동으로 감지를 발견해서 서버를 알아서 재구동해준다! (개편한 정도)

 

아무튼 여기까지 했으니, 이제 클라이언트 측으로부터 어떠한 경로에 대한 요청이 들어왔을 때, 요청된 경로에 대해서 알맞은 페이지를 보여주어야한다. 이를 해보도록 하자!

 

Fig. 14. test.html 파일 생성

나는 views 라는 폴더를 생성 후, test.html 파일을 생성해주었다. 그리고 이 test.html 파일은 매우 단순하게 다음과 같은 코드로 작성하였다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Pyodide Test Page</h1>
</body>
</html>

뭐 그냥 h1 태그로 이게 파이오다이드 페이지라는 것을 나타내주었다.

 

추후 작성...