Nodejs

 

생활 코딩 강의 목록 :  https://opentutorials.org/module/3590

인프런 강의 목록 https://www.inflearn.com/course/node-js-express/dashboard

 

 

 

이 수업은 CC 라이센스를 따르고 있으며, 아래 링크 에서도 볼 수 있습니다.
Node.js-Express https://opentutorials.org/course/3370
쿠키와 인증 https://opentutorials.org/course/3387
세션과 인증 https://opentutorials.org/course/3400 passpor.js
https://opentutorials.org/course/3402
다중 사용자 https://opentutorials.org/course/3411 google login https://opentutorials.org/course/3413 facebook login
https://opentutorials.org/course/3414

 

 

WEB2 - Node.js 수업의 예제 코드 바로가기

 

 

 

소스 : https://github.com/braverokmc79/Nodejs-master

 

Express

 

 

1. 수업 소개

 

 

 

2. 실습환경 준비

 

1 ) Nodemon 설치하기

Nodemon은 프로젝트 폴더의 파일들을 모니터링 하고 있다가 파일이 수정되면 서버를 자동으로 restart 시켜주는 패키지이다.

 

다음 명령어를 이용하여 설치한다. (-dev를 붙이면, development mode, 즉 local에서만 사용하겠다는 의미)

npm install nodemon --save-dev

 

 

scripts 에 아래 스크립트를 추가해준다.
"dev"부분에는 본인이 원하는 name을 넣으면 된다.

"dev" : "nodemon main.js",

 

npm run dev 명령어로 서버를 실행시킨다.

 

2)  sanitize-html 설치

$ npm i sanitize-html
또는

$ yarn add sanitize-html

 

$ npm run dev

http://localhost:3000/

 

 

 

 

 

3. Hello world 1

 

expressjs 공식문서   설치  :  https://expressjs.com/en/starter/installing.html

 

Express 설치는 npm 커맨드를 사용해 인스톨

npm i express

 

yarn 사용시

$ yarn add express


 

expressjs 공식문서   Hello world  : https://expressjs.com/en/starter/hello-world.html

 

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})


app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

 

 

 

 

 

4. Hello world 2

 

main.js

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})


app.get('/page', (req, res) => {
  res.send("/page");
});


app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

 

 

 

 

 

5. Hello world 2

 

main.js

const express = require('express')
const template = require('./lib/template.js')
const fs = require('fs');
const app = express()
const port = 3000

app.get('/', (req, res) => {

  fs.readdir('./data', function (error, filelist) {
    const title = 'Welcome';
    const description = 'Hello, Node.js';
    const list = template.list(filelist);
    const html = template.HTML(title, list,
      `<h2>${title}</h2>${description}`,
      `<a href="/create">create</a>`
    );
    res.send(html);
  });

})

 

 

 

 

 

6. 상세보기 페이지 구현 1

 

main.js

app.get('/page/:pageId', (req, res) => {
  res.send(req.params);
});

 

http://localhost:3000/page/HTML

{
"pageId": "HTML"
}

 

 

 

 

 

 

 

 

7. 상세보기 페이지 구현 2

 

main,js

const express = require('express')
const template = require('./lib/template.js');
const path = require('path');
const sanitizeHtml = require('sanitize-html');
const fs = require('fs');
const app = express()
const port = 3000




app.get('/page/:pageId', (req, res) => {

  fs.readdir('./data', function (error, filelist) {
    const filteredId = path.parse(req.params.pageId).base;
    fs.readFile(`data/${filteredId}`, 'utf8', function (err, description) {
      const title = filteredId;
      const sanitizedTitle = sanitizeHtml(title);
      const sanitizedDescription = sanitizeHtml(description, {
        allowedTags: ['h1']
      });
      const list = template.list(filelist);
      const html = template.HTML(sanitizedTitle, list,
        `<h2>${sanitizedTitle}</h2>${sanitizedDescription}`,
        ` <a href="/create">create</a>
                <a href="/update?id=${sanitizedTitle}">update</a>
                <form action="delete_process" method="post">
                  <input type="hidden" name="id" value="${sanitizedTitle}">
                  <input type="submit" value="delete">
                </form>`
      );
      res.send(html);
    });
  });

});

 

 

lib/template.js

list: function (filelist) {
    var list = '<ul>';
    var i = 0;
    while (i < filelist.length) {
      list = list + `<li><a href="/page/${filelist[i]}">${filelist[i]}</a></li>`;
      i = i + 1;
    }
    list = list + '</ul>';
    return list;
  }

 

 

 

 

 

 

 

 

8. 페이지 생성 구현

 

main.js

app.post("/create_process", (req, res) => {
  let body = '';
  req.on('data', function (data) {
    body = body + data;
  });
  req.on('end', function () {
    const post = qs.parse(body);
    const title = post.title;
    const description = post.description;
    fs.writeFile(`data/${title}`, description, 'utf8', function (err) {
      res.redirect(`/page/${title}`);
    })
  });

})

 

 

 

 

 

 

 

9. 페이지 수정 기능 구현

 

경로 수정

 

main.js

app.get('/page/:pageId', (req, res) => {
~

   <a href="/update/${sanitizedTitle}">update</a>


~

 

 

main.js

app.get("/update/:pageId", (req, res) => {

  fs.readdir('./data', function (error, filelist) {
    const filteredId = path.parse(req.params.pageId).base;

    fs.readFile(`data/${filteredId}`, 'utf8', function (err, description) {
      const title = filteredId;
      const list = template.list(filelist);
      const html = template.HTML(title, list,
        `
              <form action="/update_process" method="post">
                <input type="hidden" name="id" value="${title}">
                <p><input type="text" name="title" placeholder="title" value="${title}"></p>
                <p>
                  <textarea name="description" placeholder="description">${description}</textarea>
                </p>
                <p>
                  <input type="submit">
                </p>
              </form>
              `,
        `<a href="/create">create</a> <a href="/update/${title}">update</a>`
      );
      res.send(html);
    });
  });

});


app.post("/update_process", (req, res) => {
  let body = '';
  req.on('data', function (data) {
    body = body + data;
  });
  req.on('end', function () {
    const post = qs.parse(body);
    const id = post.id;
    const title = post.title;
    const description = post.description;
    fs.rename(`data/${id}`, `data/${title}`, function (error) {
      fs.writeFile(`data/${title}`, description, 'utf8', function (err) {
        res.redirect(`/page/${title}`);
      })
    });
  });

})

 

 

 

 

 

 

 

10. 페이지 삭제 기능 구현

 

main.js

~

app.get('/page/:pageId', (req, res) => {

~
              <a href="/update/${sanitizedTitle}">update</a>
                <form action="/delete_process" method="post">
                  <input type="hidden" name="id" value="${sanitizedTitle}">
                  <input type="submit" value="delete">
                </form>`


~

 

 

main.js

app.post("/delete_process", (req, res) => {
  let body = '';
  req.on('data', function (data) {
    body = body + data;
  });
  req.on('end', function () {
    const post = qs.parse(body);
    const id = post.id;
    const filteredId = path.parse(id).base;
    fs.unlink(`data/${filteredId}`, function (error) {
      res.redirect("/");
    })
  });
});

 

 

 

 

 

 

 

 

11. 미들웨어의 사용 - body parser

 

body-parser

https://www.npmjs.com/package/body-parser

 

https://github.com/expressjs/body-parser

 

설치 :

$ npm i body-parser

 

main.js

const express = require('express')
const template = require('./lib/template.js');
const path = require('path');
const sanitizeHtml = require('sanitize-html');
const fs = require('fs');
const bodyParser = require('body-parser')
const app = express()
const port = 3000


app.use(bodyParser.urlencoded({ extended: false }));


app.post("/create_process", (req, res) => {
  const post = req.body;
  const title = post.title;
  const description = post.description;
  fs.writeFile(`data/${title}`, description, 'utf8', function (err) {
    res.redirect(`/page/${title}`);
  });

})


app.post("/update_process", (req, res) => {
  const post = req.body;
  const id = post.id;
  const title = post.title;
  const description = post.description;
  fs.rename(`data/${id}`, `data/${title}`, function (error) {
    fs.writeFile(`data/${title}`, description, 'utf8', function (err) {
      res.redirect(`/page/${title}`);
    })
  });

})




app.post("/delete_process", (req, res) => {
  const post = req.body;
  const id = post.id;
  const filteredId = path.parse(id).base;
  fs.unlink(`data/${filteredId}`, function (error) {
    res.redirect("/");
  })
});


 

 

 

 

 

 

 

12. 미들웨어의 사용 - compression

 

https://www.npmjs.com/package/compression

 

$ npm i compression

 

 

const express = require('express')
const template = require('./lib/template.js');
const path = require('path');
const sanitizeHtml = require('sanitize-html');
const fs = require('fs');
const bodyParser = require('body-parser')
const compression = require('compression')
const app = express()
const port = 3000


app.use(bodyParser.urlencoded({ extended: false }));
app.use(compression());

 

 

 

 

 

 

 

13. Express 미들웨어 만들기

 

Using middleware

공식문서   :  http://expressjs.com/en/guide/using-middleware.html

 

커스텀 미들웨어 생성

app.get('*', (req, res, next) => {
  fs.readdir('./data', function (error, filelist) {
    req.list = filelist;
    next();
  });

});

 

main.js

const express = require('express')
const template = require('./lib/template.js');
const path = require('path');
const sanitizeHtml = require('sanitize-html');
const fs = require('fs');
const bodyParser = require('body-parser')
const compression = require('compression')
const app = express()
const port = 3000


app.use(bodyParser.urlencoded({ extended: false }));
app.use(compression());
app.get('*', (req, res, next) => {
  fs.readdir('./data', function (error, filelist) {
    req.list = filelist;
    next();
  });

});



app.get('/', (req, res) => {
  const title = 'Welcome';
  const description = 'Hello, Node.js';
  const list = template.list(req.list);
  const html = template.HTML(title, list,
    `<h2>${title}</h2>${description}`,
    `<a href="/create">create</a>`
  );
  res.send(html);
})


app.get('/page/:pageId', (req, res) => {

  const filteredId = path.parse(req.params.pageId).base;
  fs.readFile(`data/${filteredId}`, 'utf8', function (err, description) {
    const title = filteredId;
    const sanitizedTitle = sanitizeHtml(title);
    const sanitizedDescription = sanitizeHtml(description, {
      allowedTags: ['h1']
    });
    const list = template.list(req.list);
    const html = template.HTML(sanitizedTitle, list,
      `<h2>${sanitizedTitle}</h2>${sanitizedDescription}`,
      ` <a href="/create">create</a>
                <a href="/update/${sanitizedTitle}">update</a>
                <form action="/delete_process" method="post">
                  <input type="hidden" name="id" value="${sanitizedTitle}">
                  <input type="submit" value="delete">
                </form>`
    );
    res.send(html);
  });


});


app.get("/create", (req, res) => {

  const title = 'WEB - create';
  const list = template.list(req.list);
  const html = template.HTML(title, list, `
            <form action="/create_process" method="post">
              <p><input type="text" name="title" placeholder="title"></p>
              <p>
                <textarea name="description" placeholder="description"></textarea>
              </p>
              <p>
                <input type="submit">
              </p>
            </form>
          `, '');
  res.send(html);

});

app.post("/create_process", (req, res) => {
  const post = req.body;
  const title = post.title;
  const description = post.description;
  fs.writeFile(`data/${title}`, description, 'utf8', function (err) {
    res.redirect(`/page/${title}`);
  });

})


app.get("/update/:pageId", (req, res) => {


  const filteredId = path.parse(req.params.pageId).base;

  fs.readFile(`data/${filteredId}`, 'utf8', function (err, description) {
    const title = filteredId;
    const list = template.list(req.list);
    const html = template.HTML(title, list,
      `
              <form action="/update_process" method="post">
                <input type="hidden" name="id" value="${title}">
                <p><input type="text" name="title" placeholder="title" value="${title}"></p>
                <p>
                  <textarea name="description" placeholder="description">${description}</textarea>
                </p>
                <p>
                  <input type="submit">
                </p>
              </form>
              `,
      `<a href="/create">create</a> <a href="/update/${title}">update</a>`
    );
    res.send(html);
  });



});


app.post("/update_process", (req, res) => {
  const post = req.body;
  const id = post.id;
  const title = post.title;
  const description = post.description;
  fs.rename(`data/${id}`, `data/${title}`, function (error) {
    fs.writeFile(`data/${title}`, description, 'utf8', function (err) {
      res.redirect(`/page/${title}`);
    })
  });

})


app.post("/delete_process", (req, res) => {
  const post = req.body;
  const id = post.id;
  const filteredId = path.parse(id).base;
  fs.unlink(`data/${filteredId}`, function (error) {
    res.redirect("/");
  })
});



app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})






 

 

 

 

 

 

 

14. Express 미들웨어의 실행순서

 

 

 

 

 

 

 

 

 

15. 정적인 파일의 서비스

 

 

express 공식문서 : http://expressjs.com/en/starter/static-files.html

 

app.get('/', (req, res) => {
  const title = 'Welcome';
  const description = 'Hello, Node.js';
  const list = template.list(req.list);
  const html = template.HTML(title, list,
    `<h2>${title}</h2>${description}   
     <img src="/images/hello.jpg" style="width:300px; display:block; margin-top:10px" >
    `,
    `<a href="/create">create</a>`
  );
  res.send(html);
})

 

 

 

 

 

 

 

16. 에러처리

 

공식문서 :   https://expressjs.com/en/guide/error-handling.html

 

main.js  하단에

app.use(function (req, res) {
  res.status(400).send("Sorry cant find that!");
});

app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

 

 

 

 

 

 

 

17. 라우터 - 주소체계변경

 

공식문서 :    http://expressjs.com/en/api.html#router

 

 

main.js

const express = require('express')
const template = require('./lib/template.js');
const path = require('path');
const sanitizeHtml = require('sanitize-html');
const fs = require('fs');
const bodyParser = require('body-parser')
const compression = require('compression')
const app = express()
const port = 3000

app.use(express.static('public'))
app.use(bodyParser.urlencoded({ extended: false }));
app.use(compression());
app.get('*', (req, res, next) => {
  fs.readdir('./data', function (error, filelist) {
    req.list = filelist;
    next();
  });

});



app.get('/', (req, res) => {
  const title = 'Welcome';
  const description = 'Hello, Node.js';
  const list = template.list(req.list);
  const html = template.HTML(title, list,
    `<h2>${title}</h2>${description}   
     <img src="/images/hello.jpg" style="width:300px; display:block; margin-top:10px" >
    `,
    `<a href="/topic/create">create</a>`
  );
  res.send(html);
})

app.get("/topic/create", (req, res) => {

  const title = 'WEB - create';
  const list = template.list(req.list);
  const html = template.HTML(title, list, `
            <form action="/topic/create_process" method="post">
              <p><input type="text" name="title" placeholder="title"></p>
              <p>
                <textarea name="description" placeholder="description"></textarea>
              </p>
              <p>
                <input type="submit">
              </p>
            </form>
          `, '');
  res.send(html);

});


app.post("/topic/create_process", (req, res) => {
  const post = req.body;
  const title = post.title;
  const description = post.description;
  fs.writeFile(`data/${title}`, description, 'utf8', function (err) {
    res.redirect(`/topic/${title}`);
  });

});



app.get("/topic/update/:pageId", (req, res) => {
  const filteredId = path.parse(req.params.pageId).base;

  fs.readFile(`data/${filteredId}`, 'utf8', function (err, description) {
    const title = filteredId;
    const list = template.list(req.list);
    const html = template.HTML(title, list,
      `
              <form action="/topic/update_process" method="post">
                <input type="hidden" name="id" value="${title}">
                <p><input type="text" name="title" placeholder="title" value="${title}"></p>
                <p>
                  <textarea name="description" placeholder="description">${description}</textarea>
                </p>
                <p>
                  <input type="submit">
                </p>
              </form>
              `,
      `<a href="/topic/create">create</a> <a href="/topic/update/${title}">update</a>`
    );
    res.send(html);
  });

});


app.post("/topic/update_process", (req, res) => {
  const post = req.body;
  const id = post.id;
  const title = post.title;
  const description = post.description;
  fs.rename(`data/${id}`, `data/${title}`, function (error) {
    fs.writeFile(`data/${title}`, description, 'utf8', function (err) {
      res.redirect(`/topic/${title}`);
    })
  });

})


app.post("/topic/delete_process", (req, res) => {
  const post = req.body;
  const id = post.id;
  const filteredId = path.parse(id).base;
  fs.unlink(`data/${filteredId}`, function (error) {
    res.redirect("/");
  })
});


app.get('/topic/:pageId', (req, res, next) => {

  const filteredId = path.parse(req.params.pageId).base;
  fs.readFile(`data/${filteredId}`, 'utf8', function (err, description) {
    if (err) return next(err);

    const title = filteredId;
    const sanitizedTitle = sanitizeHtml(title);
    const sanitizedDescription = sanitizeHtml(description, {
      allowedTags: ['h1']
    });
    const list = template.list(req.list);
    const html = template.HTML(sanitizedTitle, list,
      `<h2>${sanitizedTitle}</h2>${sanitizedDescription}`,
      ` <a href="/topic/create">create</a>
                  <a href="/topic/update/${sanitizedTitle}">update</a>
                  <form action="/topic/delete_process" method="post">
                    <input type="hidden" name="id" value="${sanitizedTitle}">
                    <input type="submit" value="delete">
                  </form>`
    );
    res.send(html);


  });
});



app.use(function (req, res) {
  res.status(400).send("Sorry cant find that!");
});

app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

 

 

 

 

 

 

 

 

18. 라우터 - 파일로 분리 1

 

 

main.js

const express = require('express')
const template = require('./lib/template.js');
const fs = require('fs');
const bodyParser = require('body-parser')
const compression = require('compression')
const topicRouter = require("./routes/topic");

const app = express()
const port = 3000

app.use(express.static('public'))
app.use(bodyParser.urlencoded({ extended: false }));
app.use(compression());
app.get('*', (req, res, next) => {
  fs.readdir('./data', function (error, filelist) {
    req.list = filelist;
    next();
  });

});

app.use('/topic', topicRouter);


~

~

 

/routes/topic.js

const express = require('express');
const router = express.Router();
const template = require('../lib/template.js');
const path = require('path');
const sanitizeHtml = require('sanitize-html');
const fs = require('fs');



router.get("/create", (req, res) => {

    const title = 'WEB - create';
    const list = template.list(req.list);
    const html = template.HTML(title, list, `
            <form action="/topic/create_process" method="post">
              <p><input type="text" name="title" placeholder="title"></p>
              <p>
                <textarea name="description" placeholder="description"></textarea>
              </p>
              <p>
                <input type="submit">
              </p>
            </form>
          `, '');
    res.send(html);

});


~~
`

 

 

 

 

 

 

 

 

 

 

20. 라우터 - 파일로 분리 2

 

main.js

const express = require('express')
const template = require('./lib/template.js');
const fs = require('fs');
const bodyParser = require('body-parser')
const compression = require('compression')
const indexRouter = require("./routes/index");
const topicRouter = require("./routes/topic");
const app = express()
const port = 3000


app.use(express.static('public'))
app.use(bodyParser.urlencoded({ extended: false }));
app.use(compression());
app.get('*', (req, res, next) => {
  fs.readdir('./data', function (error, filelist) {
    req.list = filelist;
    next();
  });

});

app.use("/", indexRouter);
app.use('/topic', topicRouter);

app.use(function (req, res) {
  res.status(400).send("Sorry cant find that!");
});

app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

 

 

routes/index.js

const express = require('express');
const router = express.Router();
const template = require('../lib/template.js');


router.get('/', (req, res) => {
    const title = 'Welcome';
    const description = 'Hello, Node.js';
    const list = template.list(req.list);
    const html = template.HTML(title, list,
        `<h2>${title}</h2>${description}   
     <img src="/images/hello.jpg" style="width:300px; display:block; margin-top:10px" >
    `,
        `<a href="/topic/create">create</a>`
    );
    res.send(html);
});


module.exports = router;

 

 

 

 

 

 

21. 보안

 

보안   :  http://expressjs.com/en/advanced/best-practice-security.html

 

Use Helmet

공식문서 :    http://expressjs.com/en/advanced/best-practice-security.html#use-helmet

 

$ npm install --save helmet

Then to use it in your code:

// ...

const helmet = require('helmet')
app.use(helmet())

// ...

 

 


 

애플리케이션의 취약점을 테스트    snyk

 

https://docs.snyk.io/getting-started/create-a-snyk-account

 

 

npm을 사용하여 애플리케이션의 종속성을 관리하는 것은 강력하고 편리합니다. 그러나 사용하는 패키지에는 애플리케이션에도 영향을 줄 수 있는 심각한 보안 취약점이 포함될 수 있습니다. 앱의 보안은 종속성에서 "가장 약한 링크"만큼만 강력합니다.

npm@6 이후로 npm은 모든 설치 요청을 자동으로 검토합니다. 또한 'npm 감사'를 사용하여 종속성 트리를 분석할 수 있습니다.

$ npm audit

더 안전하게 유지하려면 Snyk 를 고려하십시오 .

Snyk는 명령줄 도구 와 Github 통합 을 제공하여 Snyk의 오픈 소스 취약성 데이터베이스 에 대해 응용 프로그램에서 종속성의 알려진 취약성을 확인합니다. 다음과 같이 CLI를 설치합니다.

$ npm install -g snyk
$ cd your-app

다음 명령을 사용하여 애플리케이션의 취약점을 테스트합니다.

$ snyk test

이 명령을 사용하여 발견된 취약점을 수정하기 위해 업데이트 또는 패치를 적용하는 프로세스를 안내하는 마법사를 엽니다.

$ snyk wizard

 

 

 

 

 

 

 

 

 

 

22. express generator

 

Express application generator

 

공식 문서 : http://expressjs.com/en/starter/generator.html

 

$ npm install -g express-generator

 

 

애플리케이션 생성기 도구인 express-generator를 사용하여 애플리케이션 스켈레톤을 빠르게 만듭니다.

npx 명령어(Node.js 8.2.0에서 사용 가능)로 애플리케이션 생성기를 실행할 수 있습니다.

$ npx express-generator

이전 노드 버전의 경우 애플리케이션 생성기를 전역 npm 패키지로 설치한 다음 실행합니다.

$ npm install -g express-generator
$ express

-h 옵션을 사용하여 명령 옵션을 표시합니다.

$ express -h

  Usage: express [options] [dir]

  Options:

    -h, --help          output usage information
        --version       output the version number
    -e, --ejs           add ejs engine support
        --hbs           add handlebars engine support
        --pug           add pug engine support
    -H, --hogan         add hogan.js engine support
        --no-view       generate without view engine
    -v, --view <engine> add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
    -c, --css <engine>  add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
        --git           add .gitignore
    -f, --force         force on non-empty directory

예를 들어 다음은 myapp이라는 Express 앱을 만듭니다. 앱은 현재 작업 디렉터리의 myapp이라는 폴더에 생성되고 보기 엔진은 Pug로 설정됩니다.

$ express --view=pug myapp

   create : myapp
   create : myapp/package.json
   create : myapp/app.js
   create : myapp/public
   create : myapp/public/javascripts
   create : myapp/public/images
   create : myapp/routes
   create : myapp/routes/index.js
   create : myapp/routes/users.js
   create : myapp/public/stylesheets
   create : myapp/public/stylesheets/style.css
   create : myapp/views
   create : myapp/views/index.pug
   create : myapp/views/layout.pug
   create : myapp/views/error.pug
   create : myapp/bin
   create : myapp/bin/www

그런 다음 종속성을 설치합니다.

$ cd myapp
$ npm install

MacOS 또는 Linux에서 다음 명령으로 앱을 실행합니다.

$ DEBUG=myapp:* npm start

Windows 명령 프롬프트에서 다음 명령을 사용합니다.

> set DEBUG=myapp:* & npm start

Windows PowerShell에서 다음 명령을 사용합니다.

PS> $env:DEBUG='myapp:*'; npm start

그런 다음 브라우저에서 http://localhost:3000/을 로드하여 앱에 액세스합니다.

생성된 앱의 디렉터리 구조는 다음과 같습니다.

.
├── app.js
├── bin
│   └── www
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── index.js
│   └── users.js
└── views
    ├── error.pug
    ├── index.pug
    └── layout.pug

7 directories, 9 files

 

 

 

 

 

 

23. 수업을 마치며

 

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

Go home and kick the dog. (종로에서 뺨 맞고 한강에서 눈 흘긴다.)

댓글 ( 4)

댓글 남기기

작성