티스토리 뷰

MEAN이 뭘 의미하는지는 안다는 가정하에 설치 및 세팅에 대한 설명을 생략하고 바로 코드로 들어가겠다.



TODO File Structure

-- public
------ core.js
------ index.html

-- controllers
------ todos.controller.js

-- models
------ todos.js

-- server.js
-- routers.js


1. package.json을 작성해준 다음, npm install을 해주자

{
"name": "Todo",
"version": "0.0.0",
"description": "MEAN STACK MVC MODEL TODO SINGLE PAGE APP",
"author": "leibniz55",
"dependencies": {
"body-parser": "^1.4.3",
"express": "^4.13.4",
"method-override": "^2.1.3",
"mongoose": "^4.4.12",
"morgan": "^1.1.1"
}
}


npm install 하고서, TODO 폴더에 node_modules 가 생성된다면 기본 세팅은 된 것이다. 이제 코딩만 하면된다.


2. server.js

- 서버의 루트가 되는 파일이며, 이 파일을 통해, 라우터 및 Express 세팅을 할 것이다.

/**
* path: /server.js
*
* login
* 1. 사용할 모듈들을 로드
* 2. express객체 (app)를 세팅
* 3. 라우터를 app 객체에 연결해준다
* 4. default 페이지를 연결해준다.
* 5. 서버를 연다.
*/

// setup ========================================
const express = require('express'),
bodyParser = require('body-parser'), // pull infomation from HTML POST (express4)
morgan = require('morgan'), // log requests to the console (express4)
methodOverride = require('method-override'); // simulate DELETE and PUT (express4)

let app = express();

// configuration ================================

app.use(express.static(__dirname + '/public')); // set the static files location
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({ extended: true })); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use(methodOverride());

// router module ===============================
require('./routers')(app);

// application =================================
app.get('/*', (req, res) => {
res.sendfile('./public/index.html');
});

app.listen(8000, (err) => {
if (err) console.error(err);
else console.log('MEAN STACK TODO PAGE on port 8000');
});

자, 이제 우리 서버는 8000 포트를 이용하고, json 형식으로 데이터를 주고 받을 수 있으며, 기본  default 페이지는 /public/index.html 파일이 되는 싱글페이지 앱의 서버를 작성하였다.


이제 세부적으로 들어가보자, 먼저 express의 객체인 app을 router와 연결 해주었는데, 실제 router.js를 작성하여 어떤 일을 하는지 알아보자.


3. router.js

/**
* path : /router.js
*
* logic
* 1.controller 모듈을 불러와, 각 route 마다 controller의 메소드를 연결해준다.
*/

const todosController = require('./controllers/todos.controller');

module.exports = (app) => {
app.get('/todos', todosController.readTodos);
app.post('/todos', todosController.addTodos);
app.delete('/todos/:todo_id', todosController.deleteTodos);
}

 router.js를 보면, 각 라우트에 해당하는 todoController 모듈에 있는 함수들을 호출해준다.

딱 보니, get을 통해 todo리스트를 읽어들이고

post를 통해 todo를 추가, delete를 통해 todo를 삭제하는 것을 알 수 있다.


이제, todos.controller.js 에서 작성된 함수들이 정확히 어떻게 구현되어있는지 보자.


4. todos.controllers.js

/**
* path: /controllers/todos.controllers.js
*
* logic
* 1. model object todo 데이터 모델을 load
* 2. readTodos (get)
* 3. addTodos (post)
* 4. deleteTodos (delete)
*/
let model = require('../models/todos').model;

exports.readTodos = (req, res) => {
model.find((err, todos) => {
if (err) res.send(err);
res.json(todos);
});
};

exports.addTodos = (req, res) => {
model.create({
text: req.body.text,
done: false
}, (err, todos) => {
if (err) res.send(err);

model.find((err, todos)=>{
if(err) res.send(err);
res.json(todos);
});
});
};
exports.deleteTodos = (req, res) => {
model.remove({
_id: req.params.todo_id
}, (err, todos) => {
if (err) res.send(err);

model.find((err, todos) => {
if (err) res.send(err);
res.json(todos);
});
});
};

코드를 보니, 각 함수들은, mongodb에 데이터를 읽고, 쓰고, 삭제 하는 것을 볼 수 가 있다.

맨 위, model에 모듈을 통해 mongodb model을 얻어오는 것을 볼 수 있다. 이제 어떤 식으로 데이터 모델을 생성하는지 보자.


5. todos.js

/**
* path: /models/todos.js
*
* logic
* 1. mongoose 모듈을 불러 mogodb를 로컬로 연결한다.
* 2. mongoose.model을 사용하여 데이터 모델을 만든다.
* 3. 만들 모듈을 export하여 사용할 수 있도록 한다.
*/
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost',(err) => {
if (err) console.error(err);
else console.log('connected mongodb');
});

let model = mongoose.model('todos', {
text: String
});

exports.model = model;

mongoose를 사용하여, mongodb를 로컬로 연결해 주고, 모델을 생성하여(text필드를 가지는) export를 하는 것을 볼 수 있다.


여기 까지 왔으면 백엔드는 모두 작성 된 것이다.

이제 AngularJS를 사용하여 프론트 엔드를 작성해보자.


6. core.js


/**
* path: /public/core.js
*/

let todo = angular.module('todo', []);

function mainController($scope, $http) {
$scope.formData = {};

// when landing on the page, get all todos and show them
$http.get('/todos')
.success((data) => {
$scope.todos = data;
$scope.length = data.length;
console.log(data);
})
.error((data) => {
console.log('Error: ' + data);
});

// when submitting the add form, send the text to the node API
$scope.createTodo = () => {
$http.post('/todos', $scope.formData)
.success((data) => {
$scope.formData = {}; // clear the form so our user is ready to enter another
$scope.todos = data;
console.log(data);
})
.error((data) => {
console.log('Error: ' + data);
});
};
// delete a todo after checking it
$scope.deleteTodo = (id) => {
$http.delete('/todos/' + id)
.success(function (data) {
$scope.todos = data;
console.log(data);
})
.error((data) => {
console.log('Error: ' + data);
});
};

}

core.js는 angular 모듈을 작성해준 것이다. $http를 통하여 서버로 부터 요청을 하고, 데이터를 받아와서 index.html에 뿌려주는 역할을 한다.


7. index.html

<!-- path: /public/index.html -->
<!DOCTYPE html>

<!-- Assign our angularJS Module -->
<html ng-app="todo">

<head>
<!-- META -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Optimize mobile viewport -->

<title> Node/angularJS Todo App </title>

<!-- SCROLLS -->

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<!-- load bootstrap -->
<style>
html {
overflow-y: scroll;
}

body {
padding-top: 50px;
}

#todo-list {
margin-bottom: 30px;
}
</style>

<!-- SPELLS -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<!-- load jquery -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<!-- load angular -->
<script src="core.js"></script>
</head>

<!-- SET THE CONTROLLER AND GET ALL TODOS -->

<body ng-controller="mainController">
<div class="container">

<!-- HEADER AND TODO COUNT -->
<div class="jumbotron text-center">
<h1>TODO <span class="label label-info">{{ length }}</span></h1>
</div>

<!-- TODO LIST -->

<div id="todo-list" class="row">
<div class="col-sm-4 col-sm-offset-4">

<!-- LOOP OVER THE TODOS IN $scope.todos -->
<div class="checkbox" ng-repeat="todo in todos">
<label>
<input type="checkbox" ng-click="deleteTodo(todo._id)"> {{ todo.text }}
</label>
</div>

</div>
</div>

<!-- FORM TO CREATE TODOS -->
<div id="todo-form" class="row">
<div class="col-sm-8 col-sm-offset-2 text-center">
<form>
<div class="form-group">

<!-- BIND THIS VALUE TO formData.text IN ANGULAR -->
<input type="text" class="form-control input-lg text-center" placeholder="Input a Todo"
ng-model="formData.text">
</div>

<!-- createToDo() WILL CREATE NEW TODOS -->
<button type="submit" class="btn btn-primary btn-lg" ng-click="createTodo()">Add</button>
</form>
</div>
</div>
</div>
</body>

</html>

앞서 작성한 AngularJS 모듈(core.js)을 불러와, maincController를 통하여 데이터를 주고 받는 것을 작성해주었다.


8. 구동 화면


공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
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
글 보관함