루비 온 레일즈에서 devise gem 없이 로그인 기능 구현하기 3 (How to build authentication system without devise gem in Ruby on Rails)



## 루비 온 레일즈에서 devise gem 없이 로그인 기능 구현하기 3 (How to build authentication system without devise gem in Ruby on Rails)

[지난 포스트](https://ghkdgh2365.blogspot.com/2020/07/devise-gem-2-how-to-build.html) 에서 쿠키(Cookie)를 이용한 로그인, 로그아웃을 구현했습니다. 이번에는 세션을 이용한 로그인, 로그아웃을 구현하겠습니다. 차이점은 다음과 같습니다. 쿠키를 이용했을 때는 사용자 브라우저에 아이디, 비밀번호를 저장하고 이를 서버에 보내서 검증했다면, 세션을 이용할 때에는 서버에서 검증에 필요한 정보를 저장한 뒤 그 정보를 사용자 브라우저에게 보내주고, 다시 그 정보를 서버에 보내 검증한다는 점이 차이점입니다. 아래 구현 방법을 보시면서 차이점을 확인해보면 이해가 더 잘 될 것입니다.

#### 3. 세션을 이용한 로그인

세션을 이용한 로그인, 로그아웃 구현을 위해 새로운 컨트롤러를 생성합니다. `rails g controller session` 으로 생성하거나, 직접 디렉토리(`controllers`)에 파일(`sessions_controller.rb`)을 만들어도 됩니다. 만들고 나면 `controller/sessions_controller.rb` 파일이 생성되고 아래와 같은 코드가 보일 것입니다.

```
class SessionsController < ApplicationController
end
```

그 다음 Cookie를 이용한 로그인 때와 같이 `new`, `create`, `destroy` 액션을 만들어 로그인 화면을 보여주고(`new`), 아이디와 비밀번호를 입력 후 로그인을 시도하고(`create`), 로그아웃(`destroy`)을 할 수 있도록 만들 것입니다. 먼저 `new` 부터 진행하겠습니다. `new` 액션을 정의해줍니다.

```
class SessionsController < ApplicationController
 def new
 end
end
```

그 다음, `routes.rb` 에 가서 아래와 같이 정의합니다.

```
get 'sessions/sign_in', to: 'sessions#new'
```

그리고 `views/sessions/new.html.erb` 파일을 생성한 뒤 아래와 같이 입력합니다. 그 다음 `localhost:3000/sessions/sign_in`에 들어가 확인해봅니다.

```
<h2>세션 로그인</h2>

<%= form_with(url: "/sessions/sign_in") do |f|%>
    <%= f.label :email %>
    <%= f.text_field :email %>

    <%= f.label :password %>
    <%= f.password_field :password %>

    <%= f.submit "로그인" %>
<% end %>
```

확인이 되었으면 `home/index.html.erb` 에 아래와 같이 추가합니다.

```
<h2> Hello World ! </h2>

<% if current_user.present? %>
  <%= link_to "로그아웃", cookie_sign_out_path, method: :delete %>
<% else %>
  <%= link_to "로그인", cookie_new_path %>
  <%= link_to "세션 로그인", sessions_sign_in_path %>
<% end %>
<hr/>
<%= link_to "회원가입", new_user_path %>
```

이제 로그인 화면이 생겼으니 로그인할 수 있도록 `controllers/sessions_controller.rb` 에 가서 아래와 같이 입력합니다.

```
  def create
    if params[:email].present? && params[:password].present?
      user = User.find_by(email: params[:email])
      if user
        if user.authenticate(params[:password])
          session[:user_id] = user.id
          flash[:notice] = "세션 로그인 성공"
          redirect_to '/home/index'
          return
        else
          flash[:notice] = "잘못된 비밀번호 입니다. 다시 확인해주세요."
        end
      else
        flash[:notice] = "잘못된 이메일입니다. 다시 확인해주세요."
      end
    else
      flash[:notice] = "이메일, 비밀번호 모두 입력해주세요"
    end
    redirect_to sessions_sign_in_path
  end
```

그 다음, `routes.rb` 에 가서 아래와 같이 입력하면 로그인 기능이 완성되었습니다.

```
post 'sessions/sign_in', to: 'sessions#create'
```

 이를 확인하기 위해서 `controllers/application_controller.rb` 에 가서 아래와 같이 입력합니다.

```
class ApplicationController < ActionController::Base
  helper_method :current_user
  def current_user
    @current_user ||= User.find_by(email: cookies[:email], password_digest: cookies[:password]) || User.find_by(id: session[:user_id])
  end
end
```

그 다음, `views/home/index` 에 가서 아래와 같이 수정합니다. 이로써 로그인이 된 것을 확인할 수 있습니다. 현재는 `sessions_sign_out_path`가 없으므로 세션 로그아웃 버튼을 누르면 오류가 날 것입니다. 이제 세션 로그아웃 기능을 만들겠습니다.

```
<h2> Hello World ! </h2>

<% if current_user.present? %>
  <%= link_to "로그아웃", cookie_sign_out_path, method: :delete %>
  <%= link_to "세션 로그아웃", sessions_sign_out_path, method: :delete %>
<% else %>
  <%= link_to "로그인", cookie_new_path %>
  <%= link_to "세션 로그인", sessions_sign_in_path %>
<% end %>
<hr/>
<%= link_to "회원가입", new_user_path %>
```

`controllers/sessions_controller.rb` 에 가서 아래와 같이 입력합니다.

```
  def destroy
    if current_user.present?
      reset_session
      flash[:notice] = "세션 로그아웃 성공"
      redirect_to '/home/index'
    end
  end
```

그리고 다시 `views/home/index` 에 가서 세션 로그인을 한 뒤, 세션 로그아웃을 해보면 로그아웃이 되어있는 것을 확인할 수 있습니다.

다음은 JWT(JSON Web Token)를 이용한 로그인을 구현하겠습니다.

참고 : https://pragmaticstudio.com/tutorials/rails-session-cookies-for-api-authentication


댓글

이 블로그의 인기 게시물

부트스트랩 사용 시 버튼 오른쪽 정렬하는 방법 (How to use float-right for right align in bootstrap)

맥(Mac)에서 MySql 사용 시 Error: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) 오류가 발생하는 경우 해결 방법

HTML, CSS - footer fixed (foot 하단 고정 시키기)