Skip to content

Instantly share code, notes, and snippets.

@zion830
Last active March 8, 2019 09:26
Show Gist options
  • Save zion830/525ce208801e3feb18c6b14286431462 to your computer and use it in GitHub Desktop.
Save zion830/525ce208801e3feb18c6b14286431462 to your computer and use it in GitHub Desktop.
node.js 를 이용한 웹앱 제작 실습 단계별 코드

간단한 TODO 앱 만들기

사용하는 npm

  • express
  • body-parser
  • jade (생코에선 jade지만 지금은 pug로 이름 변경, 선택)
  • supervisor (선택)

express-generator 사용 없이 빈프로젝트에서 시작.

app_file.js

STEP 1

// express 모듈 객체 불러오기
var express = require('express');
var app = express();

// 3000번 포트에 연결되면 callback 함수가 호출된다.
app.listen(3000, function () {
    console.log('Connected, port 3000');
});

STEP 2

var express = require('express');
var app = express();

app.set('views', './views_file'); // 템플릿 엔진의 view가 views_file 폴더 안에 있음을 설정
app.set('view engine', 'pug'); // view engine으로 pug 사용을 명시

app.listen(3000, function () {
    console.log('3000번 포트에 연결');
});

./views_file/new.pug

views_file 폴더를 만들어 new.pug 파일 생성

STEP 3

간단한 입력 폼

html
    head
        meta(charset='utf-8')
    body
        h1 New topic
        
        form(action='/topic')
            p
                input(type='text' name='title' placeholder='제목')
            p
                input(type='textarea' name='content' placeholder='본문')
            p
                input(type='submit' value="제출")

app_file.js

STEP 4

var express = require('express');
var body_parser = require('body-parser'); // body-parser 추가
var app = express();

app.set('views', './views_file');
app.set('view engine', 'pug');

// new.pug 파일을 렌더링할 라우트를 추가
app.get('/topic/new', function (req, res) {
    res.render('new');
});

app.listen(3000, function () {
    console.log('3000번 포트에 연결');
});

STEP 5

var express = require('express');
var body_parser = require('body-parser'); // body-parser 추가
var app = express();

app.use(body_parser.urlencoded({extended: false})); // body-parser 사용 설정
app.set('views', './views_file');
app.set('view engine', 'pug');

// new.pug 파일을 렌더링할 라우트를 추가
app.get('/topic/new', function (req, res) {
    res.render('new');
});

app.listen(3000, function () {
    console.log('3000번 포트에 연결');
});

STEP 6

var express = require('express');
var body_parser = require('body-parser');
var app = express();

app.use(body_parser.urlencoded({extended: false})); // request 객체에 body라는 property를 만들어 post data에 접근할 수 있게 해준다.
app.locals.pretty = true; // 소스코드를 정리해준다.

app.set('views', './views_file');
app.set('view engine', 'pug');

app.get('/topic/new', function (req, res) {
    res.render('new');
});

app.listen(3000, function () {
    console.log('3000번 포트에 연결');
});

STEP 7

var express = require('express');
var body_parser = require('body-parser');
var app = express();

app.use(body_parser.urlencoded({extended: false}));
app.locals.pretty = true;

app.set('views', './views_file');
app.set('view engine', 'pug');

app.get('/topic/new', function (req, res) {
    res.render('new');
});

// 입력폼 new.pug에서 submit 버튼 눌렀을 경우의 라우팅 설정
app.post('/topic', function (req, res) {
    var title = req.body.title;
    var content = req.body.description;

    res.send("title : " + title + "<br>content : " + content);
});

app.listen(3000, function () {
    console.log('3000번 포트에 연결');
});

./data/

/topic/new에서 작성된 내용이 저장될 디렉토리를 생성한다.

STEP 8

fs 모듈을 사용해 data에 작성한 내용이 텍스트 파일로 저장되게 하는 코드 작성

var express = require('express');
var body_parser = require('body-parser');
var fs = require('fs'); // fs 모듈을 사용한다.
var app = express();

app.use(body_parser.urlencoded({extended: false}));
app.locals.pretty = true;

app.set('views', './views_file');
app.set('view engine', 'pug');

app.get('/topic/new', function (req, res) {
    res.render('new');
});

app.post('/topic', function (req, res) {
    var title = req.body.title;
    var content = req.body.description;
    
    // 파일로 저장
    fs.writeFile('data/' + title, content, 'utf8', function (err) {
        if (err) {
            console.log(err);
            res.status(500).send('Server Error');
        }
    
        res.send("title : " + title + "<br>content : " + content);
    });
});

app.listen(3000, function () {
    console.log('3000번 포트에 연결');
});

./views_file/show.pug

Topic list가 출력될 페이지 작성

STEP 9

html
    head
        meta(charset='utf-8')
    body
        h1 Topic list

        ul
            each topic in topics
                li
                    a(href='/topic/' + topic)= topic

        a(href='/topic/new') 새로운 Topic 생성

app_file.js

STEP 10

var express = require('express');
var body_parser = require('body-parser');
var fs = require('fs');
var app = express();

app.use(body_parser.urlencoded({extended: false}));
app.locals.pretty = true;

app.set('views', './views_file');
app.set('view engine', 'pug');

app.get('/topic/new', function (req, res) {
    res.render('new');
});

// 사용자가 topic page로 들어왔을 때의 라우팅 설정
app.get('/topic', function (req, res) {
    res.render('show');
});

app.post('/topic', function (req, res) {
    var title = req.body.title;
    var content = req.body.content;
    fs.writeFile('data/' + title, content, 'utf8', function (err) {
        if (err) {
            console.log(err);
            res.status(500).send('Server Error');
        }
        
        res.send("title : " + title + "<br>content : " + content);
    });
});

app.listen(3000, function () {
    console.log('3000번 포트에 연결');
});

STEP 11

var express = require('express');
var body_parser = require('body-parser');
var fs = require('fs');
var app = express();

app.use(body_parser.urlencoded({extended: false}));
app.locals.pretty = true;

app.set('views', './views_file');
app.set('view engine', 'pug');

app.get('/topic/new', function (req, res) {
    res.render('new');
});

app.get('/topic', function (req, res) {
    fs.readdir('data', function (err, files) { // 디렉토리 안을 읽는 함수
        if (err) {
            console.log(err);
            res.status(500).send('Server Error');
        }
        res.render('show', {topics: files}); // 템플릿 파일의 이름, 넘겨줄 데이터 순으로 매개변수 작성
    });
});

app.post('/topic', function (req, res) {
    var title = req.body.title;
    var content = req.body.content;
    fs.writeFile('data/' + title, content, 'utf8', function (err) {
        if (err) {
            console.log(err);
            res.status(500).send('Server Error');
        }
        
        res.send("title : " + title + "<br>content : " + content);
    });
});

app.listen(3000, function () {
    console.log('3000번 포트에 연결');
});

STEP 12

var express = require('express');
var body_parser = require('body-parser');
var fs = require('fs');
var app = express();

app.use(body_parser.urlencoded({extended: false}));
app.locals.pretty = true;

app.set('views', './views_file');
app.set('view engine', 'pug');

app.get('/topic/new', function (req, res) {
    res.render('new');
});

app.get('/topic', function (req, res) {
    fs.readdir('data', function (err, files) {
        if (err) {
            console.log(err);
            res.status(500).send('Server Error');
        }
        res.render('show', {topics: files});
    });
});

app.post('/topic', function (req, res) {
    var title = req.body.title;
    var content = req.body.content;
    fs.writeFile('data/' + title, content, 'utf8', function (err) {
        if (err) {
            console.log(err);
            res.status(500).send('Server Error');
        }
        res.redirect('/topic'); // 리다이렉트 경로 설정
    });
});

app.listen(3000, function () {
    console.log('3000번 포트에 연결');
});

./views_file/check.pug

STEP 13

html
    head
        meta(charset='utf-8')
    body
        article
            h2= title
            =content

        br
        a(href='/topic') 뒤로가기

app_file.js

STEP 14

선택한 개별 topic 내용 출력

var express = require('express');
var body_parser = require('body-parser');
var fs = require('fs');
var app = express();

app.use(body_parser.urlencoded({extended: false}));
app.locals.pretty = true;

app.set('views', './views_file');
app.set('view engine', 'pug');

app.get('/topic/new', function (req, res) {
    res.render('new');
});

// params로 넘어온 파일 내용을 읽어서 전달해주는 기능 구현
app.get('/topic/:title', function (req, res) {
    var title = req.params.title;
    
    fs.readFile('data/' + title, 'utf8', function (err, data) {
        if (err) {
            console.log(err);
            res.status(500).send('Server Error!');
        }
        res.render('check', {title: title, content: data});
    });

});

app.get('/topic', function (req, res) {
    fs.readdir('data', function (err, files) {
        if (err) {
            console.log(err);
            res.status(500).send('Server Error');
        }
        res.render('show', {topics: files});
    });
});

app.post('/topic', function (req, res) {
    var title = req.body.title;
    var content = req.body.content;
    fs.writeFile('data/' + title, content, 'utf8', function (err) {
        if (err) {
            console.log(err);
            res.status(500).send('Server Error');
        }
        res.redirect('/topic');
    });
});

app.listen(3000, function () {
    console.log('3000번 포트에 연결');
});

실행하기

node app_file.js

실행결과

localhost:3000/topic 접속 시 화면 : Topic 리스트

capture1

localhost:3000/topic/new 접속 시 화면 : 새로운 Topic 생성

capture2

localhost:3000/topic/:title 접속 시 화면 : 개별 Topic 내용 조회

capture3

소스코드 개선하기 (선택)

소스코드는 중복되는 코드가 없을수록 좋다. get() 메서드의 url 파라미터를 배열로 넘겨서 중복되는 코드를 제거해보자. 아래는 /topic/topic/:title을 하나의 함수로 합치는 코드이다.

app.get(['/', '/topic', '/topic/:title'], function (req, res) {
    var title = req.params.title;

    if (title) {
        // title 값이 있을 때
        fs.readFile('data/' + title, 'utf8', function (err, data) {
            if (err) {
                console.log(err);
                res.status(500).send('Server Error!');
            }
            res.render('check', {title: title, content: data});
        });
    } else {
        // title 값이 없을 때
        fs.readdir('data', function (err, files) {
            if (err) {
                console.log(err);
                res.status(500).send('Server Error');
            }
            res.render('show', {topics: files});
        });
    }
});

간단한 블로그 만들기

구현할 기능

기본적인 CRUD를 갖출 것

  • 글 목록 보기
  • 새로운 글 생성
  • 개별 글 조회
  • 개별 글 삭제
  • 개별 글 수정 (옵션)

STEP 1 : Database 설정

  • MySQL 설치
  • user라는 이름의 schema 생성
  • 아이디, 작성자, 제목, 본문, 작성일시 정보를 담을 posts table 생성

테이블 생성 문

CREATE TABLE `user`.`posts` (
  `post_id` INT NOT NULL,
  `post_owner` VARCHAR(45) NOT NULL,
  `post_title` TEXT NOT NULL,
  `post_content` TEXT NOT NULL,
  `post_date` DATETIME NOT NULL,
  PRIMARY KEY (`post_id`))

STEP 2

프로젝트 구조 생성(생략가능)

express-generator 사용으로 package.json이 자동으로 생성된다.

express blog-app

STEP 3

cd blog-app으로 경로 이동 후, 프로젝트 구조 생성 및 필요한 npm 설치(생략 가능)

npm install --save mysql
npm install --save body-parser

STEP 4

STEP 5

STEP 6

STEP 7

STEP

STEP

STEP

@zion830
Copy link
Author

zion830 commented Mar 7, 2019

  • JSON과 DB 사용하지 않고 개발하였음.
  • title을 id처럼 사용했기 때문에 삭제기능은 구현하지 않았다. (삭제를 넣으려면 중복 방지 처리까지 해야하기 때문)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment