가이드 개발 가이드

고성능 웹 애플리케이션 사례

소개하다

fibjs는 주로 웹 백엔드 개발을 위해 설계된 고성능 애플리케이션 서버 프레임워크입니다. Google v8 JavaScript 엔진을 기반으로 구축되었으며 기존 콜백과 다른 동시성 솔루션을 선택합니다. fibjs는 파이버를 사용하여 프레임워크 계층에서 비동기 호출로 인해 발생하는 비즈니스 복잡성을 격리함으로써 개발 어려움을 크게 줄이고 사용자 공간에서 빈번한 비동기 처리로 인해 발생하는 성능 문제를 줄입니다.

fibjs는 성능에 중점을 두고 설계되었으며, 내장된 네트워크 IO 및 HTTP 모듈은 이벤트 중심의 비차단 I/O 모델을 채택하므로 개발자는 신뢰성이 높은 서버 애플리케이션을 쉽게 구현할 수 있습니다. 그리고 최하위 레이어가 C++로 구현되었기 때문에 fibjs는 성능이 매우 뛰어나고 높은 동시 접속에도 쉽게 대처할 수 있으며 매우 안정적이고 신뢰할 수 있는 서비스를 제공할 수 있습니다.

동시에 fibjs는 TCP 프로토콜 기반의 전이중 통신 프로토콜인 WebSocket도 지원하여 브라우저와 서버 사이에 중단 없는 연결을 설정하고 실시간 양방향 데이터 전송이 가능하며 데이터를 지원할 수 있습니다. 어떤 형식으로든 전송됩니다. WebSocket을 사용하면 더 나은 통신 효과로 실시간 통신 응용 프로그램을 쉽게 구현할 수 있습니다.

한마디로 fibjs는 고성능, 고신뢰성을 강조할 뿐만 아니라 WebSocket과 같은 실시간 통신 기능도 제공하여 고속 웹 애플리케이션 개발에 매우 ​​적합한 프레임워크입니다.

개발 환경 설정

fibjs 개발을 시작하기 전에 개발 환경을 준비해야 합니다. 이번 장에서는 fibjs를 설치하는 방법, fibjs 도구를 사용하여 프로젝트를 초기화하는 방법, IDE 통합 개발 환경을 사용하는 방법을 소개합니다.

fibjs 설치

운영 체제에 따라 fibjs를 설치하는 방법이 약간 다릅니다.

Linux 및 macOS 사용자의 경우 다음 명령을 사용하여 fibjs를 설치할 수 있습니다.

1
curl -s https://fibjs.org/download/installer.sh | sh

macOS를 사용하고 Homebrew 패키지 관리자를 사용하는 경우 다음 명령을 사용하여 설치할 수도 있습니다.

1
brew install fibjs

Windows 사용자의 경우 fibjs 공식 웹사이트에서 설치 프로그램을 다운로드한 후 지침에 따라 설치해야 합니다.

fibjs –init를 사용하여 새 프로젝트 만들기

fibjs를 설치한 후 fibjs 도구를 사용하여 새 프로젝트를 빠르게 만들 수 있습니다. 기본 프로젝트 템플릿을 생성하려면 다음 명령을 사용하십시오.

1
fibjs --init

이 명령은 프로젝트의 기본 정보와 종속성 정보를 저장하는 데 사용되는 package.json을 포함하여 현재 디렉터리에 새 프로젝트 구조를 생성합니다.

웹 애플리케이션 작성

웹 애플리케이션 개발은 현재 가장 일반적으로 사용되는 fibjs 애플리케이션 시나리오입니다. fibjs는 웹 애플리케이션을 보다 빠르게 구축하는 데 도움이 되는 일련의 도구와 모듈을 제공합니다.

HTTP 서버 작성

  • 먼저 http 모듈을 가져옵니다.
  • http.Server를 인스턴스화하고 요청을 수신합니다.
  • 서버는 start 함수를 통해 시작됩니다.
1 2 3 4 5 6
const http = require('http'); const server = new http.Server(8080, (req) => { req.response.write('Hello World!'); }); server.start();

URL 매개변수 및 요청 본문 구문 분석

URL 매개변수와 요청 본문을 구문 분석하는 것은 매우 중요하며 다양한 서버 측 애플리케이션에서 사용됩니다. fibjs에서는 들어오는 URL 매개변수를 req.query를 통해 직접 구문 분석할 수 있으며, 요청 본문은 req.body를 통해 읽습니다.

1 2 3 4 5 6 7 8
const http = require('http'); const server = new http.Server(8080, (req) => { var name = req.query.get('name'); var msg = name ? `Hello ${name}!` : 'Hello world!'; req.response.write(msg); }); server.start();

인터페이스 액세스 제어 구현

인터페이스를 통해 사용자 액세스를 제한하는 것은 매우 일반적인 시나리오입니다. 아래는 간단한 예입니다.

1 2 3 4 5 6 7 8 9 10
const http = require('http'); const server = new http.Server(8080, (req) => { if (req.headers.get('auth') === 'ok') { req.response.write('Hello World!'); } else { req.response.write('Access Denied!'); } }); server.start();

라우팅 처리 추가

라우팅은 웹 애플리케이션에서 가장 중요한 개념 중 하나이며, 특정 규칙에 따라 수신된 요청을 프로세서에 배포하는 것을 의미합니다. fibjs에서는 자신만의 라우팅 모듈을 작성하고 이를 http 서버에 바인딩한 다음 맞춤형 경로 분석을 통해 URL 일치 및 해당 처리를 수행할 수 있습니다.

1 2 3 4 5 6 7 8 9
const http = require('http'); const { Router } = require('mq'); var router = new Router(); router.get('/hello/:name', function (req, name) { req.response.write('hello, ' + name); }); var svr = new http.Server(8080, router); svr.start();

위의 예는 더 간단한 구문으로 구현할 수도 있습니다.

1 2 3 4 5 6 7 8
const http = require('http'); var svr = new http.Server(8080, { '/hello/:name': function (req, name) { req.response.write('hello, ' + name); } }); svr.start();

오류 처리 및 로깅

fibjs에서는 try-catch 블록을 통해 논리적 예외를 캡처하고 디버깅 및 기록을 위해 로그 파일로 출력할 수 있으며, 치명적인 예외인 경우 처리를 위해 상위 프레임워크에 직접 발생시킬 수 있습니다.

1 2 3 4 5 6 7 8 9 10
const console = require('console'); const http = require('http'); const server = new http.Server(8080, (req) => { try { // ... } catch (e) { console.log(e.message, e.stack); } });

도메인 간 요청

fibjs에서는 활성화CrossOrigin 메소드를 사용하여 도메인 간 요청을 허용할 수 있습니다. 다음은 http 서버를 생성하고 도메인 간 요청을 허용하는 방법에 대한 샘플 코드입니다.

1 2 3 4 5 6 7 8
const http = require('http'); const server = new http.Server(8080, (req) => { req.response.write('Hello World!'); }); server.enableCrossOrigin(); // enable cross domain request server.start();

위의 예에서는 포트 8080을 사용하여 http 서버를 만들었습니다. 활성화CrossOrigin() 메서드는 교차 출처 요청을 허용합니다.

크로스 도메인 요청을 허용하기 위해 활성화 크로스오리진(enableCrossOrigin)을 사용하는 경우, 매개변수 허용 헤더(allowHeaders)를 전달하여 수신이 허용되는 크로스 도메인 헤더를 지정할 수 있습니다. 기본적으로 allowedHeaders 값은 Content-Type입니다.

샘플 코드는 다음과 같습니다.

1 2
// enable "Content-Type" and "Authorization" headers in cross domain request server.enableCrossOrigin("Content-Type, Authorization");

위 코드에서 허용헤더 값은 "Content-Type, Authorization"입니다. 이는 서버가 두 개의 크로스 도메인 헤더 "Content-Type" 및 "Authorization"을 수신하도록 허용됨을 의미합니다. 요청에 다른 헤더가 포함되어 있으면 서버에서 거부됩니다.

활성화CrossOrigin을 사용하여 크로스 도메인 헤더 수신 기능을 설정할 때 크로스 도메인 요청을 보낼 때 해당 요청 헤더도 설정해야 합니다. 그렇지 않으면 서버에서도 거부됩니다.

웹소켓

WebSocket 프로토콜은 TCP 프로토콜을 기반으로 한 전이중 통신 프로토콜로 브라우저와 서버 사이에 중단 없는 연결을 설정하고 실시간 양방향 데이터 전송을 실현할 수 있으며 모든 형식의 데이터 전송을 지원할 수 있습니다. fibjs에서 WebSocket 지원 모듈은 WebSocket 서버 및 클라이언트 개발을 실현할 수 있는 해당 API 인터페이스를 제공합니다.

fibjs 기본 WebSocket 모듈을 사용하여 WebSocket 서버 측 구현

서버 측에서는 업그레이드 기능을 통해 HTTP 요청을 WebSocket 연결로 변환할 수 있습니다. http 서버 객체를 생성할 때 ws.upgrade(callback)를 사용하고 이를 http.start() 메서드에 전달하여 http 요청을 WebSocket으로 변환할 수 있습니다.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
var ws = require('ws'); var http = require('http'); var server = new http.Server(8080, { '/ws': ws.upgrade(function(conn, req) { console.log('a client connected.'); // listening for message events conn.onmessage = function(evt) { console.log('received message: ', evt.data); // echo the message back to client conn.send('Server: ' + evt.data); }; // listening for close events conn.onclose = function(code, reason) { console.log('closed.'); }; // listening for error events conn.onerror = function(err) { console.log(err); }; }) }); server.start();

위의 예에서는 클라이언트가 보낸 메시지 이벤트와 서버와 클라이언트 간의 연결 종료 이벤트를 모니터링할 수 있습니다. 서버가 클라이언트 메시지를 받으면 동일한 메시지를 클라이언트에 다시 보냅니다. 이 시점에서 간단한 WebSocket 지점 간 통신이 구현됩니다.

데이터 저장소와의 상호 작용 구현

통신을 위해 WebSocket을 사용하는 경우 단순히 메시지를 보내고 받는 것 외에도 영구 저장, 데이터 쿼리 등의 작업도 고려해야 합니다. 이때 데이터베이스를 사용해야 하는데, fibjs에 내장된 db 모듈을 사용하여 데이터베이스와 상호작용할 수 있습니다.

샘플 코드는 다음과 같습니다.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
var ws = require("ws"); var http = require("http"); var db = require("db"); // open a mysql connection var mysql = db.openMySQL("mysql://root:password@localhost/dbname"); var server = new http.Server(8080, { "/ws": ws.upgrade(function(conn, req) { console.log("a client connected."); // listening for message events conn.onmessage = function(evt) { console.log("received message: ", evt.data); // use execute to query the data var rs = mysql.execute("SELECT * FROM user WHERE name=?", evt.data.toString()); conn.send(JSON.stringify(rs)); }; // listening for close events conn.onclose = function(code, reason) { console.log("closed."); }; // listening for error events conn.onerror = function(err) { console.log(err); }; }) }); server.start();

위의 예에서는 먼저 db 모듈의 openMySQL 메소드를 사용하여 MySQL 데이터베이스 연결 객체 mysql을 생성한 후 클라이언트로부터 메시지를 청취한 후 실행 메소드를 사용하여 직접 SQL 쿼리를 실행하고 해당 레코드를 획득했습니다. 조건을 충족하세요. 마지막으로 쿼리 결과는 WebSocket 프로토콜을 통해 클라이언트로 다시 전송됩니다.

실제 개발에서는 예외 처리와 데이터 보안이 잘 이루어져야 한다는 점에 유의해야 한다.

요약하면, db 모듈을 통해 WebSocket 프로토콜과 결합된 데이터베이스와 쉽고 쉽게 상호 작용하여 실시간 고성능 웹 애플리케이션을 구현할 수 있습니다.

WebSocket 클라이언트-서버 통신 구현

클라이언트 측에서는 WebSocket 인스턴스를 생성하고 URL을 지정하여 WebSocket 서버에 연결한 다음 서버에 메시지를 보낼 수 있습니다.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
var ws = require('ws'); // create a WebSocket object and connect to ws://localhost:8080/ws var conn = new ws.Socket('ws://localhost:8080/ws'); // listening for open events conn.onopen = function() { conn.send('hello'); } // listening for message events conn.onmessage = function(evt) { console.log('received message:', evt.data); } // listening for close events conn.onclose = function(code, reason) { console.log('closed.'); } // listening for error events conn.onerror = function(err) { console.log(err); }

위의 클라이언트 코드에서는 WebSocket 인스턴스를 생성하고 해당 URL을 지정하며, 연결이 성공적으로 설정된 후 서버에 메시지를 보낼 수 있습니다. 서버가 클라이언트 메시지를 받으면 동일한 메시지를 클라이언트에 다시 보냅니다. 이 시점에서 간단한 WebSocket 지점 간 통신이 구현됩니다.

WebSocket의 장점 및 사용 시나리오

WebSocket 프로토콜은 전형적인 양방향 통신 모델을 가지고 있어 서버가 클라이언트에 데이터를 적극적으로 푸시할 수 있으며 채팅, 온라인 게임 및 실시간 및 높은 즉시성을 요구하는 기타 상황을 구현하는 데 자주 사용됩니다. 다른 전송 프로토콜과 비교하여 WebSocket 프로토콜은 다음과 같은 장점이 있습니다.

• 높은 실시간 성능, 양방향 통신 지원 • 간단한 프로토콜 사양, 사용 용이성 • 많은 수의 동시 연결 처리 가능 • 긴 연결 지원, 네트워크 전송 시간 단축

WebSocket의 가장 일반적인 사용 시나리오에는 웹 채팅, 게임 전투, 온라인 재생 및 인스턴트 메시징이 포함됩니다.

요약하면 WebSocket 지원 모듈을 통해 구현이 매우 간단하며 개발자는 자신의 웹 애플리케이션을 빠르게 구축할 수 있습니다.

단위 테스트

테스트 프레임워크 및 테스트 방법

소프트웨어 개발 프로세스에서 테스트는 매우 중요한 연결고리이며, 단위 테스트는 중요한 부분입니다. 단위 테스트는 코드가 설계 및 요구 사항을 충족하는지 효과적으로 검증하고 코드 수정 시 발생하는 오류를 방지할 수 있습니다. 일반적으로 단위 테스트의 원칙은 각 기능과 메소드를 테스트하여 각 기능과 메소드의 입력과 출력이 올바른지 확인하는 것입니다.

테스트 프레임워크는 테스트 케이스를 작성, 실행 및 검증하는 데 사용되는 코드 베이스로, 테스트 케이스 관리, 실행 및 보고 기능을 제공합니다. JavaScript 및 Node.js에서 널리 사용되는 단위 테스트 프레임워크로는 Mocha, Jest 및 Jasmine이 있습니다. fibjs에는 자체 테스트 프레임워크인 테스트 모듈도 있습니다.

단위 테스트 프로세스에서 일반적으로 사용되는 테스트 방법에는 블랙 박스 테스트와 화이트 박스 테스트가 있습니다.

블랙박스 테스트는 함수 내부의 구현 세부 사항을 고려하지 않고 함수의 입력과 출력만 고려하는 테스트 방법입니다. 블랙박스 테스트는 요구사항 분석 및 설계 사양을 기반으로 테스트 케이스 분석 및 실행을 통해 프로그램에 논리 오류, 경계 오류, 보안 문제 등이 있는지 판단합니다. 테스트 과정이 간단하고 테스트 결과를 신뢰할 수 있다는 장점이 있지만, 모든 프로그램 경로를 테스트할 수 없다는 단점이 있습니다.

화이트박스 테스트는 조건문, 루프문, 재귀, 코드 적용 범위 등 함수의 내부 구현 세부 사항을 고려하는 테스트 방법입니다. 이러한 테스트를 통해 공유 데이터와 코드 간의 상호 작용에서 발생할 수 있는 문제를 식별할 수 있습니다. 화이트박스 테스트의 장점은 모든 프로그램 경로를 포괄할 수 있다는 점이지만, 단점은 테스트 프로세스가 더 복잡하고 테스트 결과가 환경과 구현 방법에 따라 영향을 받는다는 것입니다.

테스트 모듈을 사용하여 테스트 케이스 작성

fibjs에서는 테스트 모듈을 사용하여 웹 서버에 대한 테스트 케이스를 작성할 수 있습니다. 간단한 예는 다음과 같습니다.

1 2 3 4 5 6 7 8 9 10 11 12 13 14
var test = require('test'); test.setup(); var http = require('http'); describe('Web server test', () => { it('should return hello world', () => { var r = http.get('http://localhost:8080/hello'); assert.equal(r.statusCode, 200); assert.equal(r.data.toString(), 'Hello World'); }); }); test.run();

이 예제에서는 설명 및 it 함수를 사용하여 각각 테스트 모듈과 테스트 케이스를 정의하고, 어설션 검증을 위해 Assert 함수를 사용합니다.

설명 기능에서 여러 it 기능을 정의하여 다양한 시나리오를 각각 테스트할 수 있습니다. 각 it 함수에서 http.get 함수를 사용하여 HTTP GET 요청을 시뮬레이션하고, 요청 응답을 얻고, AssertTrue 및 AssertEqual과 같은 어설션 확인을 수행할 수 있습니다.

테스트 케이스를 작성함으로써 기능과 모듈의 정확성을 효과적으로 테스트하고 제품 품질을 보장하며 코드의 유지 관리성을 향상시킬 수 있습니다.

핫 업데이트

핫 업데이트는 서비스를 중단하지 않고 서버 코드를 업데이트하는 것을 의미합니다. 프로그램 개발 과정에서는 빠른 반복을 위해 코드 조정과 새로운 기능이 필요한 경우가 많습니다. 핫 업데이트를 사용하면 새 코드를 사용하여 서비스를 중단하지 않고도 반복 작업을 보다 효율적으로 완료할 수 있습니다.

fibjs에서는 SandBox 모듈을 사용하여 원활한 핫 업데이트를 달성할 수 있습니다. SandBox 모듈은 안전한 실행 환경을 제공하고 전역 변수 및 기타 기능을 시뮬레이션할 수 있습니다. 구체적인 구현을 위해서는 다음 단계를 참조하세요.

  • 업데이트해야 하는 코드 파일(예: web.js)을 로드합니다.
  • SandBox를 통해 새로운 보안 모듈을 생성하고, 해당 모듈에 web.js를 로드하고, 보안 모듈을 생성합니다. 생성된 보안 모듈을 통해 실행 중인 서비스의 핸들러를 다시 마운트합니다.
  • 서버는 이전 요청을 계속 처리하고 새 요청이 새 핸들러에 마운트됩니다.

다음은 SandBox 모듈을 사용하여 원활한 핫 업데이트를 구현하는 샘플 코드입니다.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
const fs = require('fs'); const http = require('http'); const { SandBox } = require('vm'); let FILE_PATH = './web.js'; let handler = new SandBox().require(FILE_PATH).handler; const server = new http.Server(8080, handler); server.start(); fs.watch(FILE_PATH, (event, filename) => { handler = new SandBox().require(FILE_PATH).handler; server.handler = handler; console.log(`[${new Date().toLocaleString()}] server reloaded.`); });

이 코드에서는 프로그램이 시작될 때 먼저 web.js에 코드를 로드한 다음 SandBox 인스턴스를 생성하고 인스턴스에 코드를 로드합니다. 그런 다음 새 HTTP 서버를 만들고 핸들러의 메서드를 사용하여 요청을 처리했습니다.

코드에서는 fs.watch를 사용하여 web.js 파일의 변경 사항을 모니터링하고, 파일이 변경되면 코드를 다시 로드하고 핸들러의 구현을 업데이트합니다.

성능 최적화

개발 과정에서 성능 문제에 직면하는 경우가 많습니다. 코드 최적화 및 성능 향상은 개발자에게 필수적인 기술 중 하나입니다. fibjs에서는 CPU 프로파일러를 사용하여 프로그램의 실행 상태를 분석하고 코드를 최적화할 수 있습니다.

fibjs에서는 명령줄 매개변수 --prof만 사용하여 fibjs를 시작하고 CPU 프로파일러를 시작하면 됩니다(기본 간격은 1000ms). 더 높은 정밀도의 로그 분석이 필요한 경우 --prof-interval 매개변수를 사용하여 로그 간격을 설정할 수 있습니다. 예를 들어:

1 2
$ fibjs --prof test.js # 启动 CPU Profiler,默认以 1000ms 为间隔 $ fibjs --prof --prof-interval=10ms test.js # 启动 CPU Profiler,以 10000us(即 10ms)为间隔

fibjs 실행이 끝나면 소스 파일 이름 디렉터리가 현재 디렉터리에 생성됩니다. 이 디렉터리에는 로그 파일과 일부 보조 파일이 포함됩니다. 로그 파일의 기본 이름은 fibjs-xxxx.log입니다. 여기서 xxxx는 타임스탬프입니다. --log 옵션을 사용하여 로그 파일 이름을 지정할 수 있습니다. 이 시점에서 다음을 --prof-process사용하여 생성된 로그를 처리할 수 있습니다.

1
fibjs --prof-process fibjs-xxxx.log prof.svg

작업이 완료된 후 브라우저를 사용하여 prof.svg를 열어 이 로그의 불꽃 그래프를 볼 수 있습니다. 교수 클릭하면 전체 크기 이미지를 볼 수 있습니다. 전체 크기 이미지에서 마우스를 조작하면 더 자세한 내용을 볼 수 있습니다. 정보: prof.svg .

생성된 Flame 그래프에서 각 색상 블록은 기록 지점을 나타내며, 색상 블록이 길수록 더 많이 기록되며, 각 선은 호출 스택의 레이어를 나타내며, 레이어가 많을수록 더 많은 레이어를 호출합니다. 거꾸로 배치되어 있으며, 컬러 블록이 낮을수록 기능이 독창적입니다.

컬러 블록에는 두 가지 유형이 있습니다. 하나는 빨간색이고 다른 하나는 파란색입니다. fibjs 프로파일러에서 빨간색은 JavaScript 작업을 나타내고 파란색은 io 작업 또는 기본 작업을 나타냅니다. 해결해야 할 문제에 따라 집중해야 할 영역이 달라집니다. 예를 들어 높은 CPU 사용량 문제를 해결해야 한다면 빨간색 블록에 주의해야 하며, 애플리케이션의 CPU 사용량이 낮지만 응답이 느린 경우 파란색 블록에 주의해야 합니다. 상단 근처의 색상 블록이 클수록 더 많은 주의와 최적화가 필요합니다.

더 많은 CPU 리소스를 차지하는 기능을 조정하거나, IO 등을 비동기적으로 구현하거나, 작성할 때 코드를 최적화하려고 시도할 수 있습니다.

배포 및 온라인

프로젝트를 프로덕션 환경에서 실행하려면 프로젝트를 컴파일하고 배포해야 합니다. 여기에서는 package.json 파일을 사용하여 컴파일 및 배포를 구성하는 방법을 소개합니다.

프로젝트에서는 package.json을 사용하여 프로젝트 종속성을 관리하고 컴파일 및 배포를 구성할 수 있습니다. 간단한 샘플 package.json을 예로 들어 보겠습니다.

1 2 3 4 5 6 7
{ "name": "my-project", "version": "1.0.0", "dependencies": { "fib-pool": "^1.0.0" } }

프로젝트를 컴파일하고 배포해야 하는 경우 터미널에 프로젝트 디렉터리를 입력하고 다음 명령을 실행하기만 하면 됩니다.

1
fibjs --install

이 명령은 프로젝트가 의존하는 모듈을 자동으로 설치합니다. 이후 다음 명령을 사용하여 프로젝트를 시작할 수 있습니다.

1
fibjs app.js

👉【도메인 이름 라우팅