ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 21장 Angular.js , Express (앵귤러js, 익스프레스) CRUD 모듈 만들기
    MeanStack (deprecated) 2016. 7. 20. 22:39


    이전 장에 이어서 이번엔 RESTful API 아키텍처 설계를 간단하게 만들자.

    RESTful API는 애플리케이션 자원에서 수행할 수 있는 행동 집합을 표현하게 일관성 있는 서비스 구조를 제공한다.

    RESTful API는 몇가지 단순한 규칙을 따른다.


    - 자원별 기초 URI : 여기서는 http://localhost:3000/articles

    - 자료 구조 : 일반적으로 JSON이며, 요청내용으로 전달 된다.

    - 표준 HTTP 메소드 사용 : 예로 GET , POST, PUT , DELETE 


    이런 세가지 규칙을 사용해, 올바른 컨트롤러 메소드를 사용하게 HTTP 요청을 적절히 라우트 할 수 있다.

    따라서 articles API 는 다음의 라우트를 포함 할 것이다.


    - GET http://localhost:3000/articles  : 글 목록 반환

    - POST http://localhost:3000/articles  : 새로운 글 생성과 반환

    - GET http://localhost:3000/articles/:articleId  :  이미 존재하는 글 한 개 반환

    - PUT http://localhost:3000/articles/:articleId  :  이미 존재하는 글 한개를 갱신하고 반환 

    - DELETE http://localhost:3000/articles/:articleId  : 이미 존재하는 글 한 개를 삭제하고 반환


    위 라우트를 보면 알겠지만 대부분 이미 컨트롤러 메소드를 만들어 놓았다. 

    심지어 articleId 라우트 매개변수 미들웨어도 이미 구현했으므로, 익스프레스 라우트를 구현하기만 하면 끝난다.

    이를 위해 app/routes 폴더로 가서 articles.server.routes.js 라는 새로운 파일을 생성하고, 코드를 넣자.


    var users = require('../../app/controllers/users.server.controller'),
        articles = require('../../app/controllers/articles.server.controller');
    
    module.exports = function(app) {
        app.route('/api/articles')
        .get(articles.list)
        .post(users.requiresLogin, articles.create);
    
        app.route('/api/articles/:articleId')
        .get(articles.read)
        .put(users.requiresLogin, articles.hasAuthorization, articles.update)
        .delete(users.requiresLogin, articles.hasAuthorization, articles.delete);
    
        app.param('articleId', articles.articleByID);
    };
    
    
    

    위 코드를 보면 먼저 users와 articles 컨트롤러를 require 하였고, app.route() 메소드를 사용해 CRUD 연산을 위한

    기초 라우트를 정의했다. 그리고 익스프레스 라우팅 메소드를 사용해 각 컨트롤러 메소드를 특정 HTTP 메소드에

    배선하였다.  

    또한 POST 메소드가 users.requiresLogin() 미들웨어를 사용하는 방식을 보자. 새로운 글을 생성하기에 앞서서 

    사용자가 로그인을 할 필요가 있기 때문이다. 비슷한 방식으로 PUT과 DELETE 메소드도 users.requiresLogin() 과

    articles.hasAuthorization() 미들웨어를 사용한다.

    사용자는 자신이 생성한 글만 편집하고 삭제 할 수 있기 때문이다. 마지막으로 app.param() 메소드를 사용해 

    articleId 매개변수를 포함한 모든 라우트가 articles.articleByID() 미들웨어를 먼저 호출하게 보충한다.

    이제 익스프레스 애플리케이션을 구성해 새로운 Article 모델과 라우트 파일을 올리게 만드는 작업만 남았다.


    새로운 익스프레스 자원을 사용하기 위해 익스프레스 애플리케이션을 구성해 라우트 파일을 올리게 만들어야 

    한다. 이를 위해 config/ 폴더의 config_express.js 파일을 변경하자.


    var express = require('express'),
        morgan = require('morgan'),
        compress = require('compression'),
        bodyParser = require('body-parser'),
        methodOverride = require('method-override'),
        config = require('./config'),
        session = require('express-session'),
        passport = require('passport'),
        flash = require('connect-flash')
        ;
    
    module.exports = function() {
        var app = express();
    
        if(process.env.NODE_ENV === 'development') {
            app.use(morgan('dev'));
        } else if (process.env.NODE_ENV === 'production') {
            app.use(compress());
        }
    
        app.use(bodyParser.urlencoded({
            extended : true
        }));
        app.use(bodyParser.json());
        app.use(methodOverride());
    
        app.use(session({
            saveUninitialized : true,
            resave : true,
            secret : config.sessionSecret
        }));
    
        app.set('views','./app/views');
        app.set('view engine', 'ejs');
    
        app.use(flash());
        app.use(passport.initialize());
        app.use(passport.session());
    
        require('../app/routes/index.server.routes.js')(app);
        require('../app/routes/users.server.routes.js')(app);
        require('../app/routes/articles.server.routes.js')(app);    // 추가
    
        app.use(express.static('./static'));
    
        return app;
    }
    
    
    


    이제 articles RESTful API 준비가 끝났다. 다음으로 ngResource 모듈을 사용해서 Angular.js 엔티티가 RESTful API

    와 얼마나 쉽게 통신하는지를 설명할 것 이다. 


    ngResource 는 RESTful API와 관련해 개발자에게 제대로 도움을 주기 위해 Angular.js 팀이 만든 모듈이다.

    설명에 앞서 먼저 ngResource 모듈을 설치하자. ngResource 모듈은 bower 로 설치할 것이다.

    bower.json 에 ngResource 를 추가하고 bower update 명령으로 설치를 하자. 

    {
        "name" : "Mean",
        "version" : "0.0.7",
        "dependencies" : {
            "angular" : "latest",
            "angular-route" : "latest",
            "angular-resource" : "latest"
        }
    }
    
    


    설치가 완료되면 애플리케이션의 주 페이지에 모듈파일을 포함해야 한다. app/views/ 폴더의 index.ejs 파일을 

    편집하자. 


    <!DOCTYPE html>
    <html>
    <head>
        <title><%= title %></title>
    </head>
    <body>
        <% if (user) { %>
        <a href="/signout">Sign out</a>
        <% } else { %>
        <a href="/signup">Signup</a>
        <a href="/signin">Signin</a>
        <% } %>
        <section ng-view></section>
    
        <script type="text/javascript">
              window.user = <%- user || 'null' %>
        </script>
    
        <br>
        <img src="images/overwatchlogo.png" alt="logo">
    
        <script type="text/javascript" src="/lib/angular/angular.js"></script>
        <script type="text/javascript" src="/lib/angular-route/angular-route.js"></script>
        <script type="text/javascript" src="/lib/angular-resource/angular-resource.js"></script>   <!-- 추가 -->
    
        <script type="text/javascript" src="/example/example.client.module.js"></script>
        <script type="text/javascript" src="/example/controllers/example.client.controller.js"></script>
        <script type="text/javascript" src="/example/config/example.client.routes.js"></script>
    
        <script type="text/javascript" src="/users/users.client.module.js"></script>
        <script type="text/javascript" src="/users/services/authentication.client.service.js"></script>
    
        <script type="text/javascript" src="/application.js"></script>
    
    </body>
    </html>
    


    마지막으로 주 애플리케이션 모듈을 위한 의존성으로 ngResource 모듈을 추가 할 필요가 있으므로 

    static/ 폴더의 application.js 파일을 변경하자. 

    var mainApplicationModuleName = 'mean';
    
    var mainApplicationModule = angular.module(mainApplicationModuleName,
      ['ngResource','ngRoute','users','example']);                               // ngResource 추가
    
    mainApplicationModule.config(['$locationProvider',
        function($locationProvider) {
        $locationProvider.hashPrefix('!');
    }
    ]);
    
    if(window.location.hash === '#_=_') window.location.hash = '#!';
    
    angular.element(document).ready(function(){
        angular.bootstrap(document, [mainApplicationModuleName]);
    });
    
    


    이제 ngResource 모듈을 사용 할 준비가 되었다.

    그전에 ngResource 모듈에 설명을 덧 붙이자면 ngResource 모듈은 Angular.js 엔티티에 주입 가능한 새로운 

    팩토리를 개발자에게 제공한다. $resource 팩토리는 기초 URL 과 개발자가 손쉽게 RESTful 종단점과 통신하게 

    만드는 구성 옵션 집합을 사용한다. ngResource 모듈을 사용하기 위해, $resource 객체를 반환하는 $resource 

    팩토리 메소드를 호출해야 한다. $resource 팩토리 메소드는 4개의 인수를 받아들인다.


    - Url : /users/:userId 와 같은 콜론(:)이 접두어로 붙은 매개변수가 포함된 기초 URL 

    - ParamDefaults : URL 매개변수를 위한 기본값이며, 하드코딩 값이나 데이터 객체에서 매개변수 값을 추출 할 수 

                       있게 @가 접두어로 붙은 문자열을 포함할 수 있다.

    - Actions : 자원동작의 기본 집합을 확장하기 위해 사용 가능한 맞춤식 메소드를 표현하는 객체

    - Options : $resourceProvider의 기본 동작 방식을 확장하기 위한 맞춤식 옵션을 표현하는 객체


    그리고 기본자원 메소드는 다음과 같다.


    - get() : GET HTTP 메소드를 사용하며, JSON 객체 응답을 기대한다.

    - save() : POST HTTP 메소드를 사용하며, JSON 객체 응답을 기대한다.

    - query() : GET HTTP 메소드를 사용하며, JSON 객체 응답을 기대한다.

    - remove() : DELETE HTTP 메소드를 사용하며, JSON 객체 응답을 기대한다.

    - delete() : DELETE HTTP 메소드를 사용하며, JSON 객체 응답을 기대한다.


    각 메소드 호출은 $http 서비스를 사용하며, 명세된 HTTP 메소드, URL, 매개변수로 HTTP를 요청한다.

    $resource 인스턴스 메소드는 서버에서 데이터가 반환되고 나면 나중에 채워질 빈 참조 객체를 반환할 것 이다.

    또한 참조 객체기 채워지고 나면 호출 될 콜백 함수를 전달 할 수도 있다. $resource 팩토리 메소드의 기본 사용법

    은 다음과 같다.


    var Users = $resource('/users/:userId', {
         userId : '@_id'
    });
    
    var user = Users.get({
         userId: 123
    }, function() {
       user.abc = true;
       user.$save();
    });
    


    채워진 참조 객체에서 $resource 메소드를 사용할 수 있다는 사실에도 주목하자. 이런 방식이 가능한 이유는 

    $resource 메소드가 데이터 필드로 채워진 $resource 인스턴스를 반환하기 때문이다. 

    혹여 지금 무슨 말인지 지금 이해가 안가도 사용하다보면 이해가 될 것 이다.


    다음 장에는 Angular.js MVC 모듈을 구현 할 것 이다. 


    (끝)

    (최근 너무 바빠서 글 업데이트도 느리고...부가 설명도 못 적고..책을 많이 참고만 하고 있네요 ..ㅜ) 

    댓글