Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Angular.js의 ngResource에서 URL 경로를 옵션으로 처리해서 재사용하기

Angular.js에는 HTTP 요청을 처리하는 $http 모듈이 존재하지만 별도의 모듈로 제공하는 ngResource를 사용하면 RESTful API를 사용할 때 훨씬 편하게 사용할 수 있다. ngResource를 설명하는 글은 아니지만 간단히 ngResource를 사용하는 방법을 설명하면 다음과 같이 사용한다.

var app = angular.module('app', ['ngResource']);

app.controller('MainCtrl', function($scope, $resource) {
    var Team = $resource('http://api.example.com/teams/:teamName', {
      teamName: 'defaultName'
    });

    Team.get({  // GET -> /teams/test
        teamName: 'test'
    });
});

일반적으로는 $resource를 사용하는 서비스를 별도로 만들겠지만 여기서는 간결함을 위해서 컨트롤러에 넣었다. ngResource로 특정 API에 대한 URL을 정의해 놓고 사용할 수 있다. 그래서 특정 API를 인스턴스를 만들어 놓고 상황에 따라 GET, POST, PUT, DELETE를 메서드 사용하듯이 간단하게 사용할 수 있어서 편하다. URL별로 GET/POST/PUT/DELETE를 사용한다는 생각에 처음에는 URL별로 리소스 인스턴스를 따로 만들었는데 일반적으로 RESTful은 계층적인 구조를 가지기 때문에 상당히 중복적인 인스턴스를 만들게 되었다.

예를 들어 /teams라는 URI는 팀 목록을 반환하고 /teams/:teamName는 특정 팀의 정보를 반환하고 /teams/:teamName/:playerName은 특정 팀의 특정 선수의 정보를 반환한다. 이런 경우 위 세 URI별로 따로 리소스 인스턴스를 만들면 종류별로 많이 만들어야 하는데(난 이렇게 만들었다.) 만들고 보니 무척 중복적으로 느껴져서 뭔가 해결방법이 있을꺼라는 생각에 스택오버플로우에 질문을 올렸더니 역시나 ngResource가 이런 부분까지 고려해서 잘 만들어져 있었다.

var Team = $resource('http://api.example.com/teams/:teamName/:playerName', {
  teamName: '@teamName',
  playerName: '@playerName'
});

Team.get(); // GET -> /teams

Team.get({  // GET -> /teams/anything
  teamName: 'anything'
});

Team.get({ // GET -> /teams/something/johndoe
  teamName: 'something',
  playerName: 'johndoe'
});

이런 경우 리소스의 paramDefaults를 정의할 때 기본값에 @를 접두사로 지정하면 원래는 GET이 아닌 요청에 대해서 객체에서 추출한다고 문서에 나와 있는데 위와 같이 사용하면 사용할 때 해당 파라미터를 지정하지 않으면 URL에서 무시한다. 그래서 계층을 가지는 URL에서 하위 부분을 위와 같이 처리하면 하나의 리소스 인스턴스를 이용해서 다양한 URI 패턴별로 HTTP 요청을 보낼 수 있다.

2013/11/26 01:19 2013/11/26 01:19