[Rails] Devise 이메일 인증 구현하기

오승환
6 min readApr 25, 2016

--

들어가기 전에

  1. 이 포스트는 development 모드를 기준으로 합니다. production에 올릴 땐 반드시 Sidekiq, Resque와 같은 백그라운드로 Job을 처리할 수 있는 젬을 사용해야 합니다. 그렇지 않으면 메일을 보낼 때 걸리는 시간동안 서버가 멈춰버립니다.
  2. Devise 3.5.3 버전 기준입니다.

보통 Rails로 User를 구현할 때 Devise를 많이 사용한다. Devise는 정말 많은 기능을 제공하는데, 몇 가지 읊어보자면 회원가입, 로그인, 로그아웃, 비밀번호찾기, 이메일 인증, 소셜 로그인 등이 있다. 이번 글에서는 Devise의 많은 기능 중에서 이메일 인증 기능을 구현해보려고 한다. 코드만 보고싶다면 여기서 보도록 하자.

먼저 일반적인 회원가입이 어떻게 이루어지는지 보자.

  1. 유저가 회원가입 폼을 통해 가입 신청
  2. 필요한 값을 올바르게 채워서 보냈다면 새로운 유저를 생성
  3. 가입 완료

그렇다면 이메일 인증이 추가되면 어떻게 달라질까?

  1. 유저가 회원가입 폼을 통해 가입 신청
  2. 필요한 값을 올바르게 채워서 보냈다면 인증되지 않은 새로운 유저를 생성
  3. 해당 이메일로 인증메일을 전송
  4. 유저에게 이메일을 확인해달라는 메시지 띄움
  5. 유저가 이메일 확인 후 이메일에 첨부되어있는 링크 클릭
  6. 해당 링크에 접속하면 인증이 완료되며 2번에서 생성한 유저는 인증된 유저로 변경됨
  7. 가입 완료

유저가 가입을 완료하기 위해 무려 5단계가 늘어났다. 하지만 Devise가 대부분 구현해놓았기 때문에 우리가 할 일은 많지 않다.

유저 모델에 인증 관련 컬럼 추가하기

Devise가 기본적으로 만들어주는 유저모델에는 이메일 인증에 관련된 컬럼이 없다. 따라서 직접 User migration 파일에 컬럼을 추가해줘야하는데, 친절한 Devise는 이미 주석으로 코드를 작성해놓았다.

db/migrate/~~~~_devise_create_users.rb...
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
...

Confirmable 코드 4줄을 주석해제한 뒤에 rake db:migrate해주면 User테이블에 이메일 인증에 필요한 컬럼이 생성된다. (컬럼을 추가하기 전에 이미 마이그레이트를 해버렸다면 새로운 마이그레이션 파일을 생성하고 위의 4가지 컬럼을 직접 추가해주면 된다.)

Devise는 confirmed_at 컬럼의 값이 nil인 경우 인증되지 않은 유저로 판단한다. 새로운 유저가 생성되었을 경우 confirmed_at의 값이 nil이기 때문에 인증되지 않은 유저가 만들어진 것이다. 그리고 이메일 인증을 완료했을 때 confirmed_at컬럼에 인증 완료된 시간(DateTime)이 채워지게 됨으로써 인증된 유저로 변경된다.

이메일로 인증 메일 전송

Rails는 메일을 보내기 위해 Mailer라는 것을 사용한다. Mailer는 어떤 SMTP서버를 사용할 것인지, 누구에게 보낼 것인지, 어떤 내용을 보낼 것인지 등 메일에 관련된 모든 것을 담당한다. 우리의 Devise는 역시 Mailer도 제공하고 있다. 우리가 할 일은 단지 몇 가지의 설정 뿐이다.

유저 모델 설정

Devise는 여러가지 기능들을 모델에 명시함으로써 on/off할 수 있다. 기본적으로 registerable, rememberable, validatable 등이 명시되어 있다. 이메일 인증을 위한 confirmable는 기본옵션이 아니기 때문에 직접 명시해주자.

app/models/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable
end

이 부분을 건너뛰면 밑의 설정을 정상적으로 하더라도 이메일이 발송되지 않으므로 주의하도록 하자.

SMTP 설정

메일을 보내기 위해서는 반드시 메일을 보내주는 SMTP서버가 필요하다. 직접 구축하는 것은 힘들기 때문에 메일서비스로 Mailgun을 사용한다. (다른 SMTP 서버를 사용해도 된다.) Mailgun에 가입하면 1개의 샌드박스 도메인을 주는데 샌드박스 도메인으로 테스트를 하다가, 자신만의 도메인을 등록해서 사용하면 된다.(샌드박스 도메인은 하루 300건의 제한이 있다.)

config/environments/development.rbRails.application.configure do
...
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:authentication => :plain,
:address => "smtp.mailgun.org",
:port => 587,
:domain => "sandbox93ac32d21a89c992f...d103.mailgun.org
",
:user_name => "postmaster@sandbox93ac32d21a89c992f...d103.mailgun.org",
:password => "4321098765431abcdef12345.."
}
end

자신의 샌드박스 도메인 정보를 입력하면 된다. git으로 코드를 관리할 때 위와 같이 민감한 정보를 하드코딩하는 일은 없도록 하는 것이 좋지만, remote repo(예를 들면 깃헙)에 push할 것이 아니라면 일단은 하드코딩해도 좋다. 예제를 보면 민감한 정보를 dotenv 젬을 사용해서 환경변수로 관리하고 있다.

Host 설정

유저가 이메일에 첨부된 링크를 눌렀을 때 어떤 주소로 접속이 되어야 할까? 우리는 개발중이니 localhost:3000으로 접속이 되어야 할테고, production의 경우에는 서비스의 domain으로 접속이 되어야 한다. 이렇게 이메일에 첨부된 링크를 눌렀을 때, 어떤 주소(host)로 이동해야할 지 알려주어야 한다.

config/environments/development.rbRails.application.configure do
...
...
config.action_mailer.default_url_options = {host:'localhost:3000'}
end

개발모드에서 확인하기 위해 localhost:3000으로 설정했다.

여기까지 따라왔다면 가입했을 때 해당 이메일로 confirmation instructions라는 제목의 이메일이 발송되고, 이메일에 첨부된 링크를 클릭하면 유저가 정상적으로 인증된 유저로 바뀌는 것을 볼 수 있을 것이다.

유저가 인증되었는지 확인하는 코드는 다음과 같다.

user.confirmed?

--

--