1주일만에 Sails.js로 웹서비스 만들기

1. Introducing Sails.js


OpenShop 으로 만든 FLIT SHOP

이 포스트는 기본적인 Node.js 및 MongoDB 에 대한 지식이 있는 것을 가정하고 작성하였다. 전체 소스는 Github를 참고. (일부 내용이 다를 수 있음)

최근 소프트웨어 개발 이라는 것은 사실상 웹, 앱 서비스를 만드는 것을 지칭한다고 해도 과언이 아닐 정도로, 많은 서비스들이 서버에서 작동하도록 개발되어 웹 브라우저나 스마트폰을 통해 사용되고 있다. 뉴스 피드, 동영상 재생, 사진 등등 다양하게 서비스는 발전해 왔지만, 개발 과정은 그렇게 다양하진 않다.

물론 그 중심이 되는 기능에서는 상이하지만 아주 기본적으로 갖추어야할 기능들, 예를 들어 회원가입, 로그인, 정보 등록, 수정, 입력 등에 있어서는 대부분의 과정을 공유하고 있다. 이는 실제 개발을 들여다보면 더욱더 그렇다. 서버의 기능은 크게는 두가지로 중계 기능과 기록 기능이다.

다시 말하자면 서버는 회원과 회원을 혹은 회원과 서버를 이어주는 중간자로서의 어플리케이션 기능과, 그 회원이 가지고 있어야 하는 정보를 기록하는 데이터베이스의 기능으로 나누어지게 된다. 결국 정보를 받아 가공하여 데이터베이스에 기록하고 다시 그 내용을 보여주는 것을 반복하여 만들면 그것을 우리는 개발한다고 말할 수 있다. (물론 이 과정이 서비스에 따라 극히 복잡할 수 있지만, 어쨋든 기본 구조는 그렇다.)

그렇다보니 사실 반복하는 과정은 어느정도 익숙해지면 매우 귀찮아지게 마련이고, 이를 어떻게 하면 편하고 쉽게 할 수 있을까 하는 것을 궁리하게 되었다. 그렇게 편하게 만들 수 있도록 도와주는 코드(라이브러리)의 셋을 일반적으로 프레임워크 라고 지칭하며 최근 만들어진 Node.js MVC 프레임워크 중 하나가 Sails.js 이다. Sails.js Node On Sails? 는 이름에서부터 알 수 있듯이 Ruby On Rails 와 유사한 구조를 목표로 만들어졌다.

서론은 이쯤하고 실제 Sails.js 를 사용해보도록 하자. Node.js 의 설치와 활용은 Installing Node.js via package manager 를 참고하도록 하자.

How to install Sails.js

대부분의 Node Module 들이 그렇듯이 Sails.js 또한 NPM(Node Package Manager) 를 통해 매우 편리하게 설치할 수 있다.

$ sudo npm install -g sails

Global 옵션으로 설치하면 되고, 설치하는 순간부터 Sails 콘솔을 사용할 수 있다. 아래 명령어처럼 버젼을 확인하자.

$ sails --version

결과

Create New Sails Project

Sails.js 를 사용하여 새로운 프로젝트를 만들자.

$ sails new Store

새로운 프로젝트가 만들어졌다. sails.js로 프로젝트를 생성하면 여러가지 복잡한 디렉토리와 파일들을 자동으로 만들게 된다. 자세한 설명은 이곳에서 확인할 수 있으나 영어로 복잡하게 작성되어 있어서 다소 어려울 수 있으니 이해할 수 있는 것부터 하나씩 이해하도록 하자.

$ cd Store
$ sails lift

Sails.js 로 만들어진 프로젝트는 일반적인 node app.js 형태로 실행하는 것도 가능하지만 Sails 커맨드 라인 명령어인 Lift 로 실행하는 것도 가능하다. Grunt Task Runner 도 실행하는 등 개발 과정에서 귀찮은 것을 대신해주니 개발 중에는 Lift 시키도록하자.

위와 같은 화면이 나오면 웹 브라우저에 http://localhost:1337 를 입력하여 접속이 되는지 확인하자. 아래와 같은 화면이 나오면 정상이다.

Define Model

Lift 시켰을때 나오는 첫 화면을 조금 더 따라해보자. 우선 API 를 작성하자. Sails.js 의 경우 기본적으로 REST API 를 만들 수 있는데 CMD+c(ctrl+c) 로 Sails 를 중지시키고 써있는데로 아래의 명령어를 입력한다.

$ sails generate api user

새로운 API가 생성되었다는 메시지가 보일 것이다.

우선 API 를 생성하게 되면 /api/model 폴더에 User.js 가 /api/controllers 폴더에는 UserController.js 가 자동적으로 생성되게 된다. 막상 에디터로 내용을 읽어봐도 주석과 module.exports = {} 정도만 적혀 있을 뿐 별 내용은 없다. 그러면 이제 재밌는 것을 시도해보자. Lift 시키고 웹브라우저에서 http://localhost:1337/user 로 이동한다. (migrate 옵션을 지정하라는 경우가 나오면 1번 safe 를 선태하자)

아무런 화면이 나오지 않고 보통 [] 라고 빈 배열만 나타날 것이다. 이는 우리가 만들어논 user 가 당연히 한명도 없기 때문이다. User 를 만들기 위해 http://localhost:1337/user/create?name=홍길동&age=20 를 주소창에 입력한다.

{
  "name": "홍길동",
  "age": "20",
  "createdAt": "2014-10-15T13:52:18.882Z",
  "updatedAt": "2014-10-15T13:52:18.882Z",
  "id": 1
}

이번엔 결과값이 조금 달라졌다. 다시 http://localhost:1337/user 로 이동하면 이제 방금 만들어논 홍길동이라는 User 가 나타났다. 같은 방식으로 몇 명 더 입력해보자. 이제 /user 로 이동하면 아래와 같은 결과가 보인다.

[
  {
    "name": "홍길동",
    "age": "20",
    "createdAt": "2014-10-15T13:52:18.882Z",
    "updatedAt": "2014-10-15T13:52:18.882Z",
    "id": 1
  },
  {
    "name": "꽃분이",
    "age": "18",
    "createdAt": "2014-10-15T13:53:23.744Z",
    "updatedAt": "2014-10-15T13:53:23.744Z",
    "id": 2
  },
  {
    "name": "강감찬",
    "age": "52",
    "createdAt": "2014-10-15T13:53:32.235Z",
    "updatedAt": "2014-10-15T13:53:32.235Z",
    "id": 3
  }
]

대충 보니 지금까지 입력한 User 가 전부 보이는 것 같다. 그럼 강감찬만 보고 싶은 경우는 어떻게 할까. 간단하다. http://localhost:1337/user/3 이라고 입력하면 해당하는 User 를 검색할 수 있다. (강감찬의 id 값이 3이다.) http://localhost:1337/user?name=강감찬 이런 식으로 입력하면 이름으로 검색할 수 있다. 단 /user/3 과는 결과값이 다른데, 이는 중복되는 이름이 있을 수 있기 때문에 복수의 값을 보여줄 수 있도록 배열로 응답이 보여진다.

우리는 sails generate api user 만 입력했을 뿐인데 Sails 의 Blueprint 기능을 통해 자동적으로 REST API 가 작성되었다. REST 측면에서 다시 정리해보면 아래와 같다.

  • Find : GET
  • Create : POST
  • Update : PUT
  • Delete : DELETE

Sails.js 의 Blueprint 기능은 GET, POST, PUT, DELETE 요청을 받으면 자동적으로 Find, Create, Update, Delete 의 기능을 수행한다. (물론 연습한 것과 같이 /Model/create?query=data 와 같은 형태로 Create 기능을 수행할 수 있기도 하다.) 다만, 이 값의 검증을 위해서는 코드 입력이 필요하다.

쇼핑몰에서 필요한 고객 정보를 나열해보자.

  • 이름
  • 이메일
  • 비밀번호
  • 전화번호
  • 주소
  • 우편번호

이정도가 꼭 필요한 정보일 것 같다. 하지만 가입시에 굳이 이름이나 전화번호는 저장해야 할 이유가 없으니, 필수 항목은 이메일과 비밀번호 정도만 되면 될 것 같다. 이메일은 중복되면 로그인시 구분할 수 없으니, 가입 시 체크해야 할 것 같다. 이러한 내용을 우리는 User.js의 attribute(속성) 부분에 입력해주면 된다.

module.exports = {
  attributes: {
    name: {
      type: 'STRING',
    },
    email: {
      type: 'EMAIL',
      required: true,
      unique: true
    },
    password: {
      type: 'STRING',
      required: true
    },
    phone: {
      type: 'STRING'
    },
    address: {
      type: 'STRING'
    },
    postcode: {
      type: 'STRING'
    }
  },
};

이것으로 끝. 이제 우리가 새로운 User 를 입력할때 Sails.js 는 자동으로 해당 항목들을 체크하여, 잘못된 값이 들어오면 오류를 보여줄 것이다. 잘못된 값을 입력해보자. http://localhost:1337/user/create?email=emai1&password=1234

{
  "error": "E_VALIDATION",
  "status": 400,
  "summary": "1 attribute is invalid",
  "model": "User",
  "invalidAttributes": {
    "email": [
      {
        "rule": "email",
        "message": "`undefined` should be a email (instead of \"email\", which is a string)"
      }
    ]
  }
}

결과는 1가지 속성이 잘못되었고, email 은 메일 주소의 형태가 아니라는 설명이 나온다. 사실 개발에서 이러한 단순 값 검증 및 단순 데이터 저장 과정은 매우 귀찮고도 재미없는 부분인데 Sails.js 는 직관적이고 간단하게 처리할 수 있도록 Model 에서 attributes 옵션으로 제어할 수 있다. 자세한 검증 옵션 및 종류는 이곳 을 참고하자.

다음번 포스트에선 User 데이터 저장 전후로 할 수 있는 행동과, Association 부분을 알아보도록 하자.