lecture 라는 디렉토리를 생성하고 npm init 으로 시작

 

D:\code\node\lecture>npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (lecture) nodebird
version: (1.0.0) 0.0.1
description: 익스프레스를 만드는 SNS 서비스
entry point: (index.js) app.js
test command:
git repository:
keywords:
author:
license: (ISC) MIT
About to write to D:\code\node\lecture\package.json:    

{
  "name": "nodebird",
  "version": "0.0.1",
  "description": "익스프레스를 만드는 SNS 서비스",      
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "MIT"
}


Is this OK? (yes) yes

 

// 필요한 모듈 설치
D:\code\node\lecture>npm i sequelize mysql2 sequelize-cli

D:\code\node\lecture>npx sequelize init

D:\code\node\lecture>npm i express cookie-parser express-session morgan multer dotenv nunjucks

D:\code\node\lecture>npm i -D nodemon

 

app.js 가 메인 파일이다.

 

router 에서 필요한 것들은 res.locals를 사용한다.

 

// routes/page.js

const express = require('express');
const router = express.Router();
const {renderJoin, renderMain, renderProfile} = require('../controllers/page');

router.use((req, res, next)=>{
    res.locals.user = null;
    res.locals.follerCount = 0;
    res.locals.followingCount = 0;
    res.locals.followingIdList = [];
    next();
})

router.get('/profile', renderProfile);
router.get('/join', renderJoin);
router.get('/', renderMain);


module.exports = router;

 

미들웨어 마지막에 위치하는 것들을 컨트롤러라고 부른다.

// controllers/page.js

exports.renderProfile = (req, res, next) =>{
    // 서비스를 호출
    res.redner('profile', {title : '내 정보 - NoreBird'});
};

exports.renderJoin = (req, res, next )=>{
    res.render('join', {title : '회원 가입 - NodeBird'});
};

exports.renderMain = (req, res, next )=>{
    res.render('main', {
        title : 'Nodebird',
        twits: [],
    });
};

// 라우터 -> 컨트롤러 -> 서비스(요청, 응답 모른다.)

 

아래와 같이 app.js 를 작성한다.

 

// app.js 파일

const express = require('express');
const cookieParser = require('cookie-parser');
const morgan = require('morgan');
const path = require('path');
const session = require('express-session');
const nunjucks = require('nunjucks');
const dotenv = require('dotenv');

dotenv.config(); // process.env
const pageRouter = require('./routes/page')

const app = express();
app.set('port', process.env.PORT || 8001);
app.set('view engine','html');
nunjucks.configure('views',{
    express: app,
    watch: true,
});

app.use(morgan('dev'));
app.use(express.static(path.join(__dirname,'public')));
app.use(express.json());
app.use(express.urlencoded({extended : false}));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
    resave : false,
    saveUninitialized :false,
    secret: process.env.COOKIE_SECRET,
    cookie : {
        httpOnly : true,
        secret : false,
    }
}));

app.use('/', pageRouter);
app.use((req,res,next)=>{ // 404 NOT FOUND
    const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
    error.status = 404;
    next(error);
});

app.use((err, req, res, next)=>{
    res.locals.message = err.message;
    res.locals.error = process.env.NODE_ENV !== 'production' ? err : {}; // 에러 로그를 서비스한테 넘김
    res.status(err.status || 500);
    res.render('error');
});

app.listen(app.get('port'),()=>{
    console.log(app.get('port'),'번 포트에서 대기 중');
});

 

에러 발생! 다행히 검색해서 빨리 해결함 (오타..)

// 아래와 같이 에러 발생, 알려주는 위치로 갔는데 내가 작성한 파일이 아니므로
// 구글 검색 후 app.js 에서 engine 설정하는 부분에서 오타 발견하여 해결함.

[nodemon] starting `node app.js`
8001 포트에서 대기
GET / 500 9.394 ms - 1190
Error: No default engine was specified and no extension was provided.
    at new NunjucksView (D:\code\node\lecture\node_modules\nunjucks\src\express-app.js:11:13)
   

// engine 오타 였음..    
app.set('view engine','html');

 

에러 해결하고 다행히 아래와 같이 프로젝트 구성 후 실행 성공

sequelize 설정과 models 디렉토리 , config\config.json 에서 DB 설정을 완료한 후에 아래처럼 DB를 생성해준다.

 

 

D:\code\node\lecture>npx sequelize db:create

Sequelize CLI [Node: 20.16.0, CLI: 6.6.2, ORM: 6.37.3]

Loaded configuration file "config\config.json".
Using environment "development".
Database nodejs created.

 

그 이후에 npm start 했는데 아래와 같이 에러 발생

D:\code\node\lecture>npm start

> nodebird@0.0.1 start
> nodemon app.js

[nodemon] 3.1.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node app.js`
hashtag.js Hashtag
post.js Post
D:\code\node\lecture\models\index.js:24
    model.initiate(sequelize);
          ^

TypeError: model.initiate is not a function

 

해당 파일인 index.js 파일 찾았는데도 오타 발견 못하였고, models 안에 있는 다른 .js 문제라고 생각되어 제로초님 깃허브와 비교한 결과 models 안에 있는 다른.js 에서 오타 찾아서 다시 수행하니 에러 해결되고 테이블 생성됨.

 

Node.js v20.16.0
[nodemon] app crashed - waiting for file changes before starting...
[nodemon] restarting due to changes...
[nodemon] starting `node app.js`
hashtag.js Hashtag
post.js Post
user.js User
8001 포트에서 대기
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'hashtags' AND TABLE_SCHEMA = 'nodejs'
Executing (default): CREATE TABLE IF NOT EXISTS `hashtags` (`id` INTEGER NOT NULL auto_increment , `title` VARCHAR(15) NOT NULL UNIQUE, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY
KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
Executing (default): SHOW INDEX FROM `hashtags` FROM `nodejs`
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'users' AND TABLE_SCHEMA = 'nodejs'
Executing (default): CREATE TABLE IF NOT EXISTS `users` (`id` INTEGER NOT NULL auto_increment , `email` VARCHAR(40) UNIQUE, `nick` VARCHAR(15) NOT NULL, `password` VARCHAR(100), `provider` ENUM('local', 'kakao') NOT NULL DEFAULT 'local', `snsId` VARCHAR(30), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `deletedAt` DATETIME, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
Executing (default): SHOW INDEX FROM `users` FROM `nodejs`
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'posts' AND TABLE_SCHEMA = 'nodejs'
Executing (default): CREATE TABLE IF NOT EXISTS `posts` (`id` INTEGER NOT NULL auto_increment , `content` VARCHAR(140) NOT NULL, `img` VARCHAR(200), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `UserId` INTEGER, PRIMARY KEY (`id`), FOREIGN KEY (`UserId`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
Executing (default): SHOW INDEX FROM `posts` FROM `nodejs`
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'PostHashtag' AND TABLE_SCHEMA = 'nodejs'
Executing (default): CREATE TABLE IF NOT EXISTS `PostHashtag` (`createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `HashtagId` INTEGER , `PostId` INTEGER , PRIMARY KEY (`HashtagId`, `PostId`), FOREIGN KEY (`HashtagId`) REFERENCES `hashtags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (`PostId`) REFERENCES `posts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
Executing (default): SHOW INDEX FROM `PostHashtag` FROM `nodejs`
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'Follow' AND TABLE_SCHEMA = 'nodejs'
Executing (default): CREATE TABLE IF NOT EXISTS `Follow` (`createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `followingId` INTEGER , `followerId` INTEGER , PRIMARY KEY (`followingId`, `followerId`), FOREIGN KEY (`followingId`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN
KEY (`followerId`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
Executing (default): SHOW INDEX FROM `Follow` FROM `nodejs`
데이터베이스 연결 성공

 

위와 같이 테이블 생성된 것 확인.

 

passport 설정하고 회원 가입하는 코드까지만 작성하고 서버 시작해서 잘 가입되는지 확인

 

D:\code\node\lecture>npm start

> nodebird@0.0.1 start
> nodemon app.js

[nodemon] 3.1.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node app.js`
hashtag.js Hashtag
post.js Post
user.js User
8001 포트에서 대기
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'hashtags' AND TABLE_SCHEMA = 'nodejs'
Executing (default): SHOW INDEX FROM `hashtags` FROM `nodejs`
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'users' AND TABLE_SCHEMA = 'nodejs'
Executing (default): SHOW INDEX FROM `users` FROM `nodejs`
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'posts' AND TABLE_SCHEMA = 'nodejs'
Executing (default): SHOW INDEX FROM `posts` FROM `nodejs`
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'PostHashtag' AND TABLE_SCHEMA = 'nodejs'
Executing (default): SHOW INDEX FROM `PostHashtag` FROM `nodejs`
Executing (default): SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'Follow' AND TABLE_SCHEMA = 'nodejs'
Executing (default): SHOW INDEX FROM `Follow` FROM `nodejs`
데이터베이스 연결 성공

 

아래와 같이 회원 가입되면 insert into 구문이 보이고 302 코드를 반환한 것을 보면 성공적으로 가입된 것을 확인할 수 있다.

 


GET /main.css 200 3.224 ms - 2715
GET /join 200 2.651 ms - 2510
GET /main.css 304 0.854 ms - -
Executing (default): SELECT `id`, `email`, `nick`, `password`, `provider`, `snsId`, `createdAt`, `updatedAt`, `deletedAt` FROM `users` AS `User` WHERE (`User`.`deletedAt` IS NULL AND `User`.`email` = 'a@b.com');
Executing (default): INSERT INTO `users` (`id`,`email`,`nick`,`password`,`provider`,`createdAt`,`updatedAt`) VALUES (DEFAULT,?,?,?,?,?,?);
POST /auth/join 302 555.560 ms - 46
Executing (default): SELECT `Post`.`id`, `Post`.`content`, `Post`.`img`, `Post`.`createdAt`, `Post`.`updatedAt`, `Post`.`UserId`, `User`.`id` AS `User.id`, `User`.`nick` AS `User.nick` FROM `posts` AS `Post` LEFT OUTER JOIN `users` AS `User` ON `Post`.`UserId` = `User`.`id` AND (`User`.`deletedAt` IS NULL) ORDER BY `Post`.`createdAt` DESC;
GET / 200 20.424 ms - 3247

 

실제 DB에서도 정상적으로 잘 입력된 것 확인 가능.

 

 

로그인 기능까지 코드 작성한 뒤에 로그인 했을 때 성공한 화면

실제로 DB에서도 정상적으로 입력된 것도 확인

 

카카오톡 로그인 코드 작성한 뒤에 로그인 했을 때 성공한 화면

하지만 카카오톡 로그인이 강의 시점과 달라져서 아래와 같이 이메일은 권한이 없어서 못 받아오는 것으로 보인다. 비즈앱으로 등록을 해야만 권한이 허용되는 것 같다.

 

 

그래도 이름, snsID는 받아와서 로그인은 되었지만 아래와 같이 DB에는 이름만 받아오는 것을 확인할 수 있었다.

 

해시태그를 게시판 내용 안에서 추출하는 정규표현식 node 로 직접 수행해보면 아래와 같다

D:\code\node\lecture>node
Welcome to Node.js v20.16.0.
Type ".help" for more information.
> const str = '노드 교과서 너무 재밌어요. #노드교과서 #익스프레스 짱짱'
undefined
> str.match(/#[^\s#]*/g);
[ '#노드교과서', '#익스프레스' ]

 

해시태그 포함해서 게시판 글쓰기 코드 작성 후에 아래와 같이 이미지 올린 결과는 아래와 같다.

게시판 업로드까지 완료한 화면은 아래와 같다.

아래와 같이 DB에도 잘 들어간 것을 확인

'Javascript > Node' 카테고리의 다른 글

노드 교과서 섹션 5  (0) 2023.08.29
노드 교과서 섹션 6  (0) 2023.08.27
노드 교과서 섹션 9  (0) 2023.08.22
노드 교과서 섹션 10  (0) 2023.08.19
노드 교과서 섹션 11  (0) 2023.08.18

테스트 해보기

jest 를 설치한다. (기존에 있는 서비스에 테스트를 붙이는 방식)

D:\code\node\lecture>npm i -D jest

added 238 packages, changed 4 packages, and audited 504 packages in 16s

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

 

처음 상태에서 test를 실행하면 아래와 같이 test가 없다고 나온다.

D:\code\node\lecture>npm test

> nodebird@0.0.1 test
> jest

No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0
In D:\code\node\lecture
  20 files checked.
  testMatch: **/__tests__/**/*.[jt]s?(x), **/?(*.)+(spec|test).[tj]s?(x) - 0 matches
  testPathIgnorePatterns: \\node_modules\\ - 20 matches
  testRegex:  - 0 matches
Pattern:  - 0 matches

 

test 파일을 만들 때는 test나 spec 이 들어가게 만들면 된다.

index.test.js 파일을 만들고 다시 test를 수행하면 index.test.js 는 찾았는데 테스트가 없다고 나온다.

 

D:\code\node\lecture>npm test

> nodebird@0.0.1 test
> jest

 FAIL  middlewares/index.test.js
  ● Test suite failed to run

    Your test suite must contain at least one test.

      at onResult (node_modules/@jest/core/build/TestScheduler.js:133:18)
      at node_modules/@jest/core/build/TestScheduler.js:254:19
      at node_modules/emittery/index.js:363:13
          at Array.map (<anonymous>)
      at Emittery.emit (node_modules/emittery/index.js:361:23)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.972 s
Ran all test suites.

 

test 문법은 첫번째는 test의 설명이고, 그 다음은 실제로 어떤 일을 할지 입력한다.(코드와 결과값을 입력한다.)

 

// index.test.js 파일 내용

test("1+1 은 2입니다.", () => {
    expect(1 + 1).toEqual(2);
  });

 

위와 같이 입력 후 테스트를 실행하면 성공했다고 출력 된다.

D:\code\node\lecture>npm test

> nodebird@0.0.1 test
> jest

 PASS  middlewares/index.test.js
  √ 1+1 2입니다. (4 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.692 s
Ran all test suites.

 

expect 를 여러개 한번에 사용도 가능하다.

expect(res.status).toBeCalledWith(403);
expect(res.send).toBeCalledWith("로그인 필요");

 

index.test.js 를 작성하고 아래처럼 test를 수행해보면 성공한 것을 확인해볼 수 있다.

// middlewares/index.test.js 파일 내용
const { isLoggedIn, isNotLoggedIn } = require("./");

describe("isLoggedIn", () => {
  const res = {
    status: jest.fn(() => res),
    send: jest.fn(),
  };
  const next = jest.fn();

  test("로그인 되어있으면 isLoggedIn이 next를 호출해야 함", () => {
    const req = {
      isAuthenticated: jest.fn(() => true),
    };
    isLoggedIn(req, res, next);
    expect(next).toBeCalledTimes(1);
  });

  test("로그인 되어있지 않으면 isLoggedIn이 에러를 응답해야 함", () => {
    const req = {
      isAuthenticated: jest.fn(() => false),
    };
    isLoggedIn(req, res, next);
    expect(res.status).toBeCalledWith(403);
    expect(res.send).toBeCalledWith("로그인 필요");
  });
});

describe("isNotLoggedIn", () => {
  const res = {
    redirect: jest.fn(),
  };
  const next = jest.fn();

  test("로그인 되어있으면 isNotLoggedIn이 에러를 응답해야 함", () => {
    const req = {
      isAuthenticated: jest.fn(() => true),
    };
    isNotLoggedIn(req, res, next);
    const message = encodeURIComponent("로그인한 상태입니다.");
    expect(res.redirect).toBeCalledWith(`/?error=${message}`);
  });

  test("로그인 되어있지 않으면 isNotLoggedIn이 next를 호출해야 함", () => {
    const req = {
      isAuthenticated: jest.fn(() => false),
    };
    isNotLoggedIn(req, res, next);
    expect(next).toHaveBeenCalledTimes(1);
  });
});

 

결과화면

D:\code\node\lecture>npm test

> nodebird@0.0.1 test
> jest

 PASS  middlewares/index.test.js
  isLoggedIn
    √ 로그인 되어있으면 isLoggedIn이 next를 호출해야 (4 ms)
    √ 로그인 되어있지 않으면 isLoggedIn이 에러를 응답해야 (3 ms)
  isNotLoggedIn
    √ 로그인 되어있으면 isNotLoggedIn이 에러를 응답해야 (1 ms)
    √ 로그인 되어있지 않으면 isNotLoggedIn이 next를 호출해야 (1 ms)

Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total
Snapshots:   0 total
Time:        2.022 s
Ran all test suites.

 

DB에서 불러오는 파일들은 jes.mock 을 통해서 가짜로 변경해서 테스트를 진행할 수 있다.

mockReturnValue 사용.

// user.js 에 있는  내용
const User = require('../models/user');

// user.test.js 에 있는 내용
jest.mock("../models/user");


  test("사용자를 찾아 팔로잉을 추가하고 success를 응답해야 함", async () => {
    User.findOne.mockReturnValue({
      addFollowing(id) {
        return Promise.resolve(true);
      },
    });
    await follow(req, res, next);
    expect(res.send).toBeCalledWith("success");
  });

 

user.test.js 작성한 후에 테스트 결과 화면

D:\code\node\lecture>npm test

> nodebird@0.0.1 test
> jest

 PASS  middlewares/index.test.js
 PASS  controllers/user.test.js    
  ● Console

    console.error
      DB에러

      11 |     }
      12 |   } catch (error) {
    > 13 |     console.error(error);
         |             ^
      14 |     next(error);
      15 |   }
      16 | };

      at error (controllers/user.js:13:13)
      at Object.<anonymous> (controllers/user.test.js:36:5)


Test Suites: 2 passed, 2 total
Tests:       7 passed, 7 total
Snapshots:   0 total
Time:        3.428 s
Ran all test suites.

 

테스트 커버리지 살펴보기

package.json 에 아래와 같이 추가하고 실행 결과는 아래와 같다.

test 파일을 만든 것 중에서 얼마나 테스트가 되었는지 확인 가능하다.

"scripts": {
    "start": "nodemon app",
    "test": "jest",
    "coverage": "jest --coverage"
  },

 

D:\code\node\lecture>npm run coverage

> nodebird@0.0.1 coverage
> jest --coverage

 PASS  middlewares/index.test.js
 PASS  controllers/user.test.js
  ● Console

    console.error
      DB에러

      11 |     }
      12 |   } catch (error) {
    > 13 |     console.error(error);
         |             ^
      14 |     next(error);
      15 |   }
      16 | };

      at error (controllers/user.js:13:13)
      at Object.<anonymous> (controllers/user.test.js:36:5)

-------------|---------|----------|---------|---------|-------------------
File         | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------|---------|----------|---------|---------|-------------------
All files    |      84 |      100 |      60 |      84 |                  
 controllers |     100 |      100 |     100 |     100 |                  
  user.js    |     100 |      100 |     100 |     100 |                  
 middlewares |     100 |      100 |     100 |     100 |                  
  index.js   |     100 |      100 |     100 |     100 |                  
 models      |   33.33 |      100 |       0 |   33.33 |
  user.js    |   33.33 |      100 |       0 |   33.33 | 5-47
-------------|---------|----------|---------|---------|-------------------

Test Suites: 2 passed, 2 total
Tests:       7 passed, 7 total
Snapshots:   0 total
Time:        2.246 s, estimated 4 s
Ran all test suites.

 

통합 테스트

통합 테스트를 위해서 supertest를 설치한다.

 

D:\code\node\lecture>npm i -D supertest

added 24 packages, changed 5 packages, and audited 528 packages in 5s

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

 

테스트를 위해 DB 설정을 해주고 아래와 같이 db 를 생성해준다.

D:\code\node\lecture>npx sequelize db:create --env test

Sequelize CLI [Node: 20.16.0, CLI: 6.4.1, ORM: 6.29.0]

Loaded configuration file "config\config.json".
Using environment "test".
Database nodejs_test created.

 

routes/auth.test.js 파일에 test 내용을 작성해주고 실행하면 아래와 같이 결과를 알려준다.

D:\code\node\lecture>npm test

> nodebird@0.0.1 test
> jest

 PASS  middlewares/index.test.js
 PASS  controllers/user.test.js    
......

POST /auth/join 302 342.534 ms - 23
POST /auth/login 302 249.889 ms - 23
POST /auth/join 302 14.069 ms - 115
POST /auth/login 302 3.168 ms - 136
POST /auth/login 302 242.653 ms - 23
POST /auth/login 302 245.272 ms - 154
POST /auth/login 302 246.092 ms - 23
GET /auth/logout 403 2.080 ms - 16  
POST /auth/login 302 7.814 ms - 115
GET /auth/logout 302 6.094 ms - 23  
 PASS  routes/auth.test.js (7.015 s)
  ● Console

......
Test Suites: 3 passed, 3 total
Tests:       14 passed, 14 total
Snapshots:   0 total
Time:        8.013 s
Ran all test suites.

 

부하테스트를 위해 artillery를 설치해준다.

D:\code\node\lecture>npm i -D artillery

 

실제 수행을 해본다.

100명이 50번씩 수행한다는 의미 (—count 100 -n 50)

 

D:\code\node\lecture>npx artillery quick --count 100 -n 50 http://localhost:8001
Test run id: t5xdb_xrpacx8tc4mh993pg9jp357yby3m4_mta3
Phase started: unnamed (index: 0, duration: 1s) 02:08:04(+0900)

Phase completed: unnamed (index: 0, duration: 1s) 02:08:05(+0900)

--------------------------------------
Metrics for period to: 02:08:10(+0900) (width: 5.328s)
--------------------------------------

http.codes.200: ................................................................ 3129
http.downloaded_bytes: ......................................................... 11195562
http.request_rate: ............................................................. 608/sec
http.requests: ................................................................. 3229
http.response_time:
  min: ......................................................................... 23
  max: ......................................................................... 261
  mean: ........................................................................ 151.7
  median: ...................................................................... 147
  p95: ......................................................................... 198.4
  p99: ......................................................................... 214.9
http.responses: ................................................................ 3129
vusers.created: ................................................................ 100
vusers.created_by_name.0: ...................................................... 100


--------------------------------------
Metrics for period to: 02:08:20(+0900) (width: 2.594s)
--------------------------------------

http.codes.200: ................................................................ 1871
http.downloaded_bytes: ......................................................... 6694438
http.request_rate: ............................................................. 689/sec
http.requests: ................................................................. 1771
http.response_time:
  min: ......................................................................... 23
  max: ......................................................................... 188
  mean: ........................................................................ 128.2
  median: ...................................................................... 133
  p95: ......................................................................... 162.4
  p99: ......................................................................... 179.5
http.responses: ................................................................ 1871
vusers.completed: .............................................................. 100
vusers.failed: ................................................................. 0
vusers.session_length:
  min: ......................................................................... 6934.4
  max: ......................................................................... 7363.9
  mean: ........................................................................ 7174
  median: ...................................................................... 7117
  p95: ......................................................................... 7407.5
  p99: ......................................................................... 7407.5


All VUs finished. Total time: 9 seconds

--------------------------------
Summary report @ 02:08:14(+0900)
--------------------------------

http.codes.200: ................................................................ 5000
http.downloaded_bytes: ......................................................... 17890000
http.request_rate: ............................................................. 649/sec
http.requests: ................................................................. 5000
http.response_time:
  min: ......................................................................... 23
  max: ......................................................................... 261
  mean: ........................................................................ 142.9
  median: ...................................................................... 141.2
  p95: ......................................................................... 194.4
  p99: ......................................................................... 210.6
http.responses: ................................................................ 5000
vusers.completed: .............................................................. 100
vusers.created: ................................................................ 100
vusers.created_by_name.0: ...................................................... 100
vusers.failed: ................................................................. 0
vusers.session_length:
  min: ......................................................................... 6934.4
  max: ......................................................................... 7363.9
  mean: ........................................................................ 7174
  median: ...................................................................... 7117
  p95: ......................................................................... 7407.5
  p99: ......................................................................... 7407.5

D:\code\node\lecture>

 

loadtest.json에 주로 사용될 만한 시나리오를 작성해서 부하 테스트도 가능하다.

결과는 아래와 같다.

D:\code\node\lecture>npx artillery run loadtest.json
Test run id: tqepa_rt48nfkae5zb6xp6jynb53p6x4y6w_a3jj
Phase started: unnamed (index: 0, duration: 30s) 02:33:04(+0900)

--------------------------------------
Metrics for period to: 02:33:10(+0900) (width: 4.575s)
--------------------------------------

http.codes.200: ................................................................ 182
http.codes.302: ................................................................ 91
http.downloaded_bytes: ......................................................... 616343
http.request_rate: ............................................................. 71/sec
http.requests: ................................................................. 273
http.response_time:
  min: ......................................................................... 2
  max: ......................................................................... 45
  mean: ........................................................................ 3.7
  median: ...................................................................... 3
  p95: ......................................................................... 6
  p99: ......................................................................... 13.1
http.responses: ................................................................ 273
vusers.completed: .............................................................. 91
vusers.created: ................................................................ 91
vusers.created_by_name.0: ...................................................... 91
vusers.failed: ................................................................. 0
vusers.session_length:
  min: ......................................................................... 12.9
  max: ......................................................................... 112.9
  mean: ........................................................................ 22.1
  median: ...................................................................... 16.9
  p95: ......................................................................... 51.9
  p99: ......................................................................... 67.4


--------------------------------------
Metrics for period to: 02:33:20(+0900) (width: 9.95s)
--------------------------------------

http.codes.200: ................................................................ 400
http.codes.302: ................................................................ 200
http.downloaded_bytes: ......................................................... 1354600
http.request_rate: ............................................................. 60/sec
http.requests: ................................................................. 600
http.response_time:
  min: ......................................................................... 1
  max: ......................................................................... 10
  mean: ........................................................................ 2.9
  median: ...................................................................... 3
  p95: ......................................................................... 4
  p99: ......................................................................... 6
http.responses: ................................................................ 600
vusers.completed: .............................................................. 200
vusers.created: ................................................................ 200
vusers.created_by_name.0: ...................................................... 200
vusers.failed: ................................................................. 0
vusers.session_length:
  min: ......................................................................... 10.5
  max: ......................................................................... 37
  mean: ........................................................................ 14.2
  median: ...................................................................... 13.6
  p95: ......................................................................... 17.6
  p99: ......................................................................... 27.4


Phase completed: unnamed (index: 0, duration: 30s) 02:33:34(+0900)

--------------------------------------
Metrics for period to: 02:33:30(+0900) (width: 9.952s)
--------------------------------------

http.codes.200: ................................................................ 400
http.codes.302: ................................................................ 200
http.downloaded_bytes: ......................................................... 1354600
http.request_rate: ............................................................. 60/sec
http.requests: ................................................................. 600
http.response_time:
  min: ......................................................................... 1
  max: ......................................................................... 6
  mean: ........................................................................ 2.7
  median: ...................................................................... 3
  p95: ......................................................................... 4
  p99: ......................................................................... 5
http.responses: ................................................................ 600
vusers.completed: .............................................................. 200
vusers.created: ................................................................ 200
vusers.created_by_name.0: ...................................................... 200
vusers.failed: ................................................................. 0
vusers.session_length:
  min: ......................................................................... 10.3
  max: ......................................................................... 18.8
  mean: ........................................................................ 12.9
  median: ...................................................................... 12.6
  p95: ......................................................................... 16
  p99: ......................................................................... 17.6


--------------------------------------
Metrics for period to: 02:33:40(+0900) (width: 5.493s)
--------------------------------------

http.codes.200: ................................................................ 218
http.codes.302: ................................................................ 109
http.downloaded_bytes: ......................................................... 738257
http.request_rate: ............................................................. 71/sec
http.requests: ................................................................. 327
http.response_time:
  min: ......................................................................... 1
  max: ......................................................................... 6
  mean: ........................................................................ 2.5
  median: ...................................................................... 2
  p95: ......................................................................... 4
  p99: ......................................................................... 4
http.responses: ................................................................ 327
vusers.completed: .............................................................. 109
vusers.created: ................................................................ 109
vusers.created_by_name.0: ...................................................... 109
vusers.failed: ................................................................. 0
vusers.session_length:
  min: ......................................................................... 9.9
  max: ......................................................................... 17.6
  mean: ........................................................................ 12.1
  median: ...................................................................... 11.8
  p95: ......................................................................... 14.4
  p99: ......................................................................... 15.3


All VUs finished. Total time: 31 seconds

--------------------------------
Summary report @ 02:33:36(+0900)
--------------------------------

http.codes.200: ................................................................ 1200
http.codes.302: ................................................................ 600
http.downloaded_bytes: ......................................................... 4063800
http.request_rate: ............................................................. 71/sec
http.requests: ................................................................. 1800
http.response_time:
  min: ......................................................................... 1
  max: ......................................................................... 45
  mean: ........................................................................ 2.9
  median: ...................................................................... 3
  p95: ......................................................................... 4
  p99: ......................................................................... 6
http.responses: ................................................................ 1800
vusers.completed: .............................................................. 600
vusers.created: ................................................................ 600
vusers.created_by_name.0: ...................................................... 600
vusers.failed: ................................................................. 0
vusers.session_length:
  min: ......................................................................... 9.9
  max: ......................................................................... 112.9
  mean: ........................................................................ 14.6
  median: ...................................................................... 13.1
  p95: ......................................................................... 19.9
  p99: ......................................................................... 49.9

'Javascript > Node' 카테고리의 다른 글

노드 교과서 섹션 8  (0) 2023.08.23
노드 교과서 섹션 9  (0) 2023.08.22
노드 교과서 섹션 11  (0) 2023.08.18
노드 교과서 섹션 12  (0) 2023.08.17
노드 교과서 섹션 13  (0) 2023.08.09

+ Recent posts