Bucket Place/Ruby on Rails

[Ruby on Rails] Devise gem

Cloud Travel 2014. 5. 22. 16:49


  들어가면서 


 오랜만에 글을 쓰는데, 왠지 갑자기 글씨체가 마음이 안들어서 "들어가면서"를 쓰면서 10분을 보낸 Cloud Travel 입니다. 오늘은 Rails의 Devise gem에 대해서 알아보도록 하려고 합니다. Devise gem은 참 좋은 것 같습니다. 회원가입부터 세션관리, e-mail 등 사이트에 접속하는 사용자에 대한 정보를 관리하는데 능통한 Gem인 것 같습니다.


 이전에는 사용자(User)모델, 세션(Session)모델 등을 만들어서 일일이 하였는데, 처리를 쉽게 하기 위해서 Devise Gem을 사용하게 되었습니다.




  Pre-Condition 


 Devise gem을 사용하기 위해서는 미리 설정해야 할 것이 있습니다.


 1. Rails 버젼 확인

   - Devise gem을 이용하기 위해서는 rails 버전이 3.2이상이어야 합니다.

   - 저는 4.1.1에서 사용하여 테스트를 하였습니다.


 2. Project 생성

$ rails new [Project-Name]

$ cd [Project-Name]

===============================================================================

[example]

$ rails new devise-test

$ cd devise-test


 


  Devise Gem 추가 및 설치 


 Gemfile에 devise를 추가합니다.

> Gemfile <

...

gem 'devise'

...


 bundle install 및 update를 실행합니다.

$ bundle install

$ bundle update


 generate를 실행하여 devise를 설치합니다.

$ rails generate devise install

      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environent
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost:3000' }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. If you are deploying on Heroku with Rails 3.2 only, you may want to set:

       config.assets.initialize_on_precompile = false

     On config/application.rb forcing your application to not access the DB
     or load models when precompiling your assets.

  5. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

===============================================================================

 

 인스톨을 하면은 자동으로 생성되는 파일 2개와 설정해야할 옵션의 목록이 나타납니다. 

 

 자동생성된 파일

 1. config/initializers/devise.rb : devise를 실행할때 초기화해주는 파일

 2. config/locales/devise.en.yml : 아래서 알아볼 I18n의 기능인데 오류나 성공시 메세지를 미리 정의한 파일


 설정해야 할 옵션은 아래의 절 "Devise 설정"에서 알아보도록 하겠다.




  Model 생성 


 devise generator를 사용하여 어플리케이션에서 사용할 모델을 작성해주면 된다.

$ rails generate devise [Model_Name]

===============================================================================

[example]

$ rails generate devise User

      invoke  active_record
      create    db/migrate/20140522035040_devise_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      insert    app/models/user.rb
       route  devise_for :users


 devise generator를 사용한 경우에는 모델 기본설정 및 필요한 모듈을 자동적으로 생성해줍니다. 또한, config/routes.rb에 devise controller의 루틴을 설정해줍니다. 위의 예의 경우 아래와 같이 추가됩니다.

> config/routes.rb <

...

devise_for :users

...


 보통의 경우에는 위에서 사용한 예와 같이 User를 사용하거나 Member를 사용한다. 또한, 관리자 계정이 필요한 경우에는 Admin이라는 모델을 하나더 생성해주시면 됩니다.


 궁금하거나 추가할 내용이 있다면 db/migrate/[ts]_devise_create_user.rb 를 확인하면된다. 그렇지 않다면 migrate를 실행하자.

$ rake db:migrate


 


  Devise 설정


 1. 로그인 후에 리다이렉션하는 페이지 설정 및 기본 페이지 설정

   - 이 내용은 위에서 나왔던 설정 2번에 관련된 내용입니다.

   - devise는 로그인시에 이전 페이지를 찾아가도록 도와준다.

   - 예외적으로 root 페이지로 이동하는 경우가 있는데 이를 위해서 root 경로를 설정해준다.

     ( 솔직히 이 이유만이 아니더라도 root 경로를 설정해야 하는 이유는 많다.)

   - 또한, root 경로를 위한 controller를 만들어 줄 필요가 있다.

$ rails generate controller home index       # controller 생성

...

> config/routes.rb <                               # routes.rb 설정 (root 페이지 설정)

...

root 'home#index'

...


 2. 메일을 위한 설정

   - 이 내용은 위에서 나왔던 설정 1번에 연관이 된 내용입니다.

   - 보통의 경우에는 위에서 설명과 같이 나온 예와 같이

     config.action_mailer.default_url_options = { :host => 'localhost:3000'} 만 설정해주면된다.

  - 여기서는 추가적으로 SMTP(simple mail transfer protocol)를 이용해 특정메일을 설정하는 것을 살펴보자.

  - 코드에 대한 설명은 주석으로 되어있다.

config.action_mailer.default_url_options = { :host => 'localhost:3000' }
# mailer 방법 설정 : smtp 사용
config.action_mailer.delivery_method = :smtp
# smtp 내용을 설정한다.
config.action_mailer.smtp_settings = {
  :address => 'smtp.gmail.com',		# smtp host 주소
  :port => 587,						# smtp 포트 
  :authentication => :plain,		# 인증 방식 설정
  :user_name => 'Account',			# 메일 계정명 
  :password => 'Password'			# 메일 비밀번호
}

 3. 실행시 오류내용과 성공 내용을 출력해줄 장소를 만들어준다.

   - 이 내용은 위에서 나왔던 설정 3번에 해당하는 내용입니다.

   - app/views/layouts/application.html.erb를 편집하여 아래의 내용을 원하는 위치에 추가합니다.

<% if notice %>

<p class="notice"><%= notice %></p>

<% end %>

<% if alert %>

<p class="alert"><%= alert %></p>

<% end %>

 

 4. 뷰 설정에 관련된 내용은 아래에서 다시 다루기로 하겠다.




  Devise helper method


 Devise에서는 기본적으로 제공해주는 Helper 함수가 존재한다. 그에 대해서 알아보도록 하자. 일단, 모델이름을 User로 해서 생성했다고 가정하고 작성하였다.


 1) before_action :authenticate_user!

   - 로그인시 특정 Controller의 Action을 사용자가 할 수 있는지 없는지를 판단해주는 역할을 한다.


 2) user_signed_in?

   - 사용자가 로그인 했는지 여부를 알려준다. (true and false return)

   - 이를 이용해서 app/views/layouts/application.html.erb에서 로그인 상태여부에 따른 페이지 설정을

     할 수 있다.


 3) current_user

   - 현재 사용자의 정보를 가져온다.

 

 4) user_session

   - 현재 사용자의 세션 정보를 가져온다.


 만약, 모델이름이 admin일 경우에는 각각의 메소드의 이름은 다음과 같이 변화합니다.

  1) before_action :authenticate_admin!

  2) admin_signed_in?

  3) current_admin

  4) admin_session


 Devise에서는 제공해주지 않는 것이 있는데 현재 사용자가 현재 접근하려는 페이지에 알맞은 사용자인지
판단해주는 부분이 빠져있다. 예를 들어, 사용자 1이 2의 정보를 바꾸려고 하면 이는 오류를 내야 한다. 하지만 위에서 제공해주는 기능만으로는 이것을 판단하기 불가능하다.


 이를 해결하기 위해선 다음과 같은 함수를 추가해 주면된다.

 일단 위에서 생성한 사용자를 위한 컨트롤러에 다음의 함수를 추가한다.

 app/controllers/users_controller.rb

private
  def correct_user
    @user = User.find(params[:id])
    redirect_to(root_path) unless current_user == @user
  end

 이 함수는 사용자가 접근하는 페이지의 파라미터값을 이용하여 접근하려는 사용자를 파악하고, 그 사용자가 실제로 허가된 사용자인지를 파악해준다.


 위의 설명을 파악하고 있다면, 이젠 devise에 의해 만들어진 User를 사용할 수 있게 된다.

 서버를 키고 오류를 내면 접근가능한 페이지에 대한 대략적인 정보를 얻을 수 있을 것이다.


열수 있는 페이지(GET method를 이용하는 곳)를 하나씩 둘러보면서 기능을 이용해보자.




  View 설정 


 이제 모델을 생성했고, 그에 대한 컨트롤러에 있는 메소드를 공부하고 추가적인 컨트롤러를 생성하였다. 그렇다면 마지막으로 우리가 해야 할 일은 View를 설정하는 것이다. 기본적으로 제공해주는 view는 아무런 css도 설정되지 않은 수수한 페이지들 이다.


 아쉽게도 우리는 Gem에서 자동으로 생성된 부분에 대해선 접근이 불가능하다. 하지만, devise는 Gem으로 정의된 기본적인 뷰 정보를 자신의 프로젝트로 복사하여 수정을 할 수 있게 해주었다.


 일단, Gem에 존재하는 뷰 정보를 자신의 프로젝트로 복사해오자.

$ rails generate devise:views

 

 이렇게 해서 가져온다면 모든 Devise 모델에 대한 view정보를 복사해 올 수 있습니다. 하지만, devise를 이용하는 모델이 2개 이상일 경우에는 문제가 발생합니다. 위의 명령으로 생성된 기본 셋팅은 모든 devise모델에 대해서 같은 뷰를 사용하게 됩니다. 각각의 모델에 대한 뷰를 설정하기 위해서는 아래의 추가적인 작업이 필요합니다.


 1. config/initializers/devise.rb 파일에서 config.scoped_views = false 줄을 찾습니다.

   - 주석을 해제하고 false 값을 true로 변경합니다.

  > config/initializers/devise.rb <

 ...

 config.scoped_views = true

 ...

 

 2. 각각의 devise 모델에 대해서 뷰를 생성해줍니다. (user와 admin의 뷰를 나눌경우)

$ rails generate devise:views users

...

$ rails generate devise:views admins


 이 후에는 우리가 지금까지 해왔던 방식을 이용하여 html를 정의하고 css를 정의해주면 뷰가 완성됩니다.




  Controller 설정


 지금까지는 기본적으로 생성된 컨트롤러만을 이용했는데, 사용자가 생성한 특정 컨트롤러와도 연결이 가능합니다. 이를 위해서는 app/controller/[model] 디렉토리를 생성하고, 그 안에 컨트롤러를 작성하고, routes.rb 파일을 수정하면 됩니다. 생성하는 컨트롤러는 "Devise::SessionsController"를 상속받아야 합니다.


 예를 들어, admin에 대한 session 컨트롤러를 사용자가 제작한 것으로 변경하려면 다음 작업을 하면 됩니다.

 1. 디렉토리 생성

 $ mkdir app/controller/admin


 2. 컨트롤러 생성 및 작성

> app/controller/admin/sessions.rb <

 class Admins::SessionController < Devise::SessionsController

 ...

 end


 3. routes.rb 파일에서 컨트롤러를 지정해주기

> config/routes.rb <

 ...

 devise_for :admins, controllers => { :sessions => "admins/sessions" }

 ...


 기본적으로 제공해주는게 우수해서 그닥 사용 여부에 대해선 감이 없지만, 알면 좋으니 알아두자.




  I18n 설정


 홈페이지에서 I18n에 대해서 설명을 한 적이 없기 때문에 간단히 설명을 하고 넘어가자.


 I18n이란, 국제화를 위한 언어정의 툴이라고 생각하면 된다. 이에 상반된 개념의 L10n이 존재하는데 이는 지역화를 위한 언어정의 툴이라고 할 수 있다.


 자신이 생성하고 있는 서비스가 국제화를 목표로 두고있지 않다면, 그냥 I18n파일에 한글로 언어를 미리 저장해두면 된다. 그게아니라면 약간 복잡하게 local에 접근을 해야 한다.


 devise에 대한 I18n 파일은 confing/locales/devise.en.yml 파일이다. 한국어에 맞는 I18n을 정의하기 위해서는 config/locales/devise.ko.yml을 만들고 en.yml의 구조를 가져와서 생성해주면 된다.




  마치며...


 먼가 길고긴 devise에 대한 설명을 마치려고한다. 위에서 설명한 기능이외에 devise에서는 facebook, twitter 로그인 인증을 도와주는 기능도 존재한다. 또한, 기존에 자동으로 생성된 devise모델에 추가적으로 attributes를 추가하여 생성하는 모델을 위한 기능도 존재한다.


 기타 등등 여러가지 기능이 매우 많이 있는 devise이다. 로그인을 위한 Gem에서는 최고의 수준의 Gem이라고 봐도 과언이 아니다.


 이 글을 쓰기 위해서 다음의 페이지를 참조하였다.

 http://easyramble.com/devise-on-rails.html

 또한, 더 많은 정보를 얻기 위한 사람들을 위해서 다음의 페이지를 링크한다.

 http://devise.plataformatec.com.br/


 이것으로 devise에 대한 설명글을 마치도록 한다.