Rails devise,paperclip을 이용해서 프로필 이미지 업로드하기

Posted by negabaro kim on Wednesday, May 2, 2018 Tags: rails devise   4 minute read

Rails devise인스톨 방법에서 devise를 이용해 User모델을 만들어 봤다. 이 포스트에서는 devise로 만든 User모델에 paperclip을 이용해서 프로필 이미지를 업로드하는 방법을 정리해봤다.

paperclip이란?

우선 간단히 paperclip에 대해서 소개하면 Rails에서 간단히 이미지를 업로드하고 여러 사이즈의 이미지를 가공해 이미지를 관리할 수 있는 Gem이다.

이미지를 가공하는건 뒷단에서 ImageMagick을 이용하고 있다. 그러므로 paperclip이 실행되는 환경에 ImageMagick을 인스톨해야 하는 번거러움이 있긴하다. (이 부분은 docker를 이용해 개선 가능)

paperclip을 인스톨해보자

ImageMagick인스톨

mac일 경우

brew install imagemagick

로 간단히 인스톨 가능하다. ImageMagick가 정상적으로 인스톨되면 convert라는 커맨드가 생기므로 확인해준다.

which convert
/usr/local/bin/convert

or
convert --version

paperclip인스톨

Gemfile에 이하 설정을 추가하고 bundle install해준다.

#Gemfile
gem "paperclip"

기존의User모델에 프로필 이미지용 컬럼 추가

Users테이블에 avatar라는 컬럼을 추가했다.

rails g paperclip users avatar
rake db:migrate

실제로는 이런식으로 컬럼이 추가된다.

    t.string "avatar_file_name"
    t.string "avatar_content_type"
    t.integer "avatar_file_size"
    t.datetime "avatar_updated_at"

컨트롤 단에서는 avatar라는 컬럼에 파일을 업로드 하기만 하면 paperclip에서 위의 컬럼의 내용을 전부 갱신해준다.

모델 설정

마지막으로 기존의 user모델에 이하의 설정을 추가해줘야한다.

#app/models/user.rb
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/missing_profile_img.png"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/

default_url부분은 기본적으로 사용되는 이미지파일을 설정해준다. 위의 설정대로라면public/images/missing_profile_img.png에 적당한 이미지파일을 업로드 해둘 필요가 있다.

여기까지 설정이 끝나면devise에서 current_user.avatar와 같은 방법으로 접근할 수있게된다.

프로필 이미지 업로드하기

이어서 레일즈에서 프로필 이미지를 업로드하는 로직을 만들어보자.

config/routes.rb

#config/routes.rb
scope module: :front do
    namespace :my do
      resource :profiles
    end
  end

rake routes결과

    edit_my_profiles GET    /my/profiles/edit(.:format)               front/my/profiles#edit
               my_profiles GET    /my/profiles(.:format)                    front/my/profiles#show
                           PATCH  /my/profiles(.:format)                    front/my/profiles#update
                           PUT    /my/profiles(.:format)                    front/my/profiles#update

View설정

#app/views/front/my/profiles/edit.html.erb
<div class="main users-edit">
  <div class="container">
    <div class="form-heading">프로필 변경</div>
    <div class="form users-form">
      <div class="form-body">
        <% current_user.errors.full_messages.each do |message| %>
          <div class="form-error">
            <%= message %>
          </div>
        <% end %>
      
        <%= form_for current_user, url: my_profiles_path do |f| %>
          <p>유저명</p>
          <%= f.text_field :nickname, value: current_user.nickname %>
          <p>프로필 이미지</p>
          <%= image_tag current_user.avatar(:thumb) %>
          <%= f.file_field :avatar, lang: "ko" %>
          <p>메일어드레스</p>
          <%= f.text_field :email, value: current_user.email %>
          <%= f.submit "저장" %>
        <% end %>
      </div>
    </div>
  </div>
</div>

controller설정

#app/controllers/front/my/profiles_controller.rb
class Front::My::ProfilesController < ApplicationController
    def edit
    end
    
    def update
      current_user.assign_attributes(user_params)
      if current_user.valid?
        current_user.save!
        flash[:success] = "saved!"
        redirect_to action: :edit
      else
        render :edit
      end
    end
    
  private
  def user_params
    params.require(:user).permit(:nickname,:avatar,:email)
  end
end

동작확인

http://localhost/my/profiles/edit 에 억세스해서 이미지를 업로드해봤다.

image

정상적으로 업로드가 되면

Rails Log에서 이하와 같이 update되었다고 표시된다.

 UPDATE `users` SET `avatar_file_name` = '2pWUcQg.png', `avatar_content_type` = 'image/png', `avatar_file_size` = 2297463, `avatar_updated_at` = '2018-05-03 00:19:39', `updated_at` = '2018-05-03 00:1 :40' WHERE `users`.`id` = 5

이하 캡쳐를 보면 ImageMagick에 의해서 크기별로 가공된 이미지가 업로드 되어있는것도 확인할 수 있다.

image

paperclip에서 이미지 변경이 일어나면 이전 파일을 삭제해줘서 유저가 자신의 이미지를 몇번을 변경해도 dummy파일이 생기지 않는다.

여기까지 devise,paperclip을 이용한 프로필 이미지 업로드 방법에 대해서 알아봤다.