TinyMCE와 AWS S3를 이용한 게시판 이미지 업로드 연동

TinyMCE + AWS S3 For bulletin board Image upload (AWS server standard : Korea)

이제 본격적으로 TinyMCE와 사전에 준비한 AWS S3을 이용해서 게시글에 이미지 업로법에 대해 알아보겠습니다!

잠깐, TinyMCE가 뭐에요??▲ 게시판 텍스트 에디터 (TinyMCE)

Before...

이번 작업을 하기 전에 앞서, TinyMCE가 기본적으로 깔려있어야 합니다.

Before... 2

AWS S3가 기본적으로 가입 및 User/Bucket이 세팅 되어 있어야 합니다!

  • AWS S3 가입, User/Bucket 세팅방법 [클릭]

주의

이번 작업은 AWS와 연동되는 작업입니다. C9이랑 Git 저장소 등 프로젝트가 Public이신 분은 모두 'Private'으로 전환을 강력 권유 드립니다. 다른 사람이 마음먹고 당신 서버 앞으로 악의적인 자료 업로드를 하게되면 엄청난 서버 요금이 부과될 수 있습니다.

TinyMCE + AWS S3를 이용한 이미지 업로드 구현

TinyMCE ↔ AWS S3연동

  • Gemfile에 다음 내용을 추가합니다.
gem 'tinymce-rails-imageupload', '~> 4.0.0.beta'
gem 'carrierwave'
gem 'fog'

그리고 이어서 터미널에다음을 입력합니다.

bundle install

  • 'bundle install'을 끝낸 후, 또 다시 터미널에 입력해 새로운 DB를 추가합니다. rails g model image alt:string hint:string file:string

그러면 /db/migrate 에 'image' 라는 새로운 DB가 생성된게 보일겁니다.

새로운 DB가 생겼으니, 이를 적용시켜야 겠죠?

아래 명령어를 1줄씩 순서대로 명령어 입력창(터미널)에 입력해주세요!

rake db:drop
rake db:migrate
  • /config/tinymce.yml 파일을 열람하시고, toolbar와 plugins에 'uploadimge'를 추가해 줍니다.

  • 적용 예시

toolbar: undo redo | forecolor | bold italic | alignleft aligncenter alignright | fontselect | code | link | uploadimage | table |
plugins:
  - link
  - uploadimage
  - textcolor
  - code
  - table
  • /config/initializers에서 'fog.rb'라는 새로운 파일을 생성해주고, 다음 내용을 입력해줍니다.
CarrierWave.configure do |config|
  config.fog_provider = 'fog/aws'                        # required
  config.fog_credentials = {
    provider:              'AWS',                        # required
    aws_access_key_id:     'xxx',                        # required
    aws_secret_access_key: 'yyy',                        # required
    region:                'ap-northeast-2',             # 아시아-한국서버 명칭
    endpoint:              'https://s3-ap-northeast-2.amazonaws.com' # 아시아-한국서버
  }
  config.fog_directory  = '아까 자신이 S3에서 만든 bucket 명칭'                          # required
  config.fog_public     = true                                        # optional, defaults to true
  config.fog_attributes = { } # optional, defaults to {}
end

여기서, aws_access_key_id, aws_secret_access_key 이 부분에는 자신의 AWS user에서 부여받은 id와 Key를,

config.fog_directory에는 자신이 생성한 Bucket의 이름을 입력해 줍니다.

주의

저 코드가 절대로 다른 사람에게 노출되지 않게 하시고, 자신의 C9 프로젝트나 Git에서 AWS Key 자료 등이 업로드 된게 'Public(공개)' 상태라면은 비공개 상태로 전환시키세요.다른 사람이 마음먹고 당신 서버 앞으로 악의적인 자료업로드를 하게되면 엄청난 서버 요금이 부과될 수 있습니다.

  • /app/models 폴더에 있는 image.rb 파일을 열람하시고, 다음을 입력합니다.
class Image < ApplicationRecord
  mount_uploader :file, ImageUploader
end
  • /app 하위에 uploaders 폴더를 생성 해내고, uploaders 폴더 안에 새로운 파일인 image_uploader.rb을 생성해내고, 다음을 입력합니다.
#/app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base

    # 자료 저장방식 (AWS 연동은 'fog' 방식으로)
    storage :fog

    # AWS S3 Bucket 저장 경로
    # 이미지가 동일한 경로에 저장되면 똑같은 이름의 이미지가 업로드 할 시 덮어씌어질 수 있어서 이미지가 새로 추가될 때 서로 다른 경로에 이미지가 생성되게 함.
    def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
    end

    # 이미지 업로드 시 허용 확장자
    def extension_white_list
    %w(jpg jpeg gif png)
    end

end
  • /app/controllers 폴더에 새로운 파일인 images_controller.rb을 생성해내고, 다음을 입력합니다.
class ImagesController < ApplicationController

  def new
    @image = Image.build.params(image_params)
  end

  def show
    @image = Image.find(params[:id])
  end

  private

  def image_params
    params.require(:image).permit(
      :file,
      :hint,
      :alt,
      )
  end

end
  • /app/controllers 폴더에 새로운 파일인 tinymce_assets_controller.rb을 생성해내고, 다음을 입력합니다.
class TinymceAssetsController < ApplicationController
  def create
    # Take upload from params[:file] and store it somehow...
    # Optionally also accept params[:hint] and consume if needed
    image = Image.create params.permit(:file, :alt, :hint)

    render json: {
      image: {
        url: image.file.url
      }
    }, content_type: "text/html"
  end
end
  • /config/routes.rb 파일을 열람하고, 다음 내용을 추가적으로 입력해줍니다.
post '/tinymce_assets' => 'tinymce_assets#create'
  • 완성입니다! 잘 되는지 확인해보세요!!

▲ TinyMCE 이미지 업로드

▲ TinyMCE 이미지 업로드 후의 게시글

▲ TinyMCE 이미지 URL 경로
▲ AWS S3 Bucket에 업로드 되어있는 이미지들

문제점 및 해결방법

하지만 이미지를 업로드 할 때 작은 사이즈의 이미지는 상관없는데.. 만약 게시글 내용이 나오는 영역 범위를 초과하는 그림을 업로드 하게 되면....▲ 이미지가 영역을 초과하게 된다...

이렇게 됩니다......

처음에는 그냥 단순히 /app/assets/stylesheets/application.css에서

// app/assets/stylesheets/application.css
img {
    width : 100%;
}

위 처럼 이미지 가로 크기를 100%로 주는 방식으로 해봤습니다.

일단, 큰 이미지는 성공입니다만(content 범위를 초과하지 않고, content 내에 이미지가 보여짐.)..

▲ 위의 이미지가 원본 이미지라면 (391 × 214)

▲ 실패예제

단순히 이미지 가로 크기를 100%로 설정할 경우 작은 이미지에 대해선 강제로 저렇게 크기가 늘어나는 문제가 발생하게 됩니다.

제가 이 것 때문에 약 3-5일은 고생했을겁니다.. 거의 포기할려던 찰나,멋쟁이 사자처럼 5기의 '노종원'님께서 답변을 주셨습니다..

다시한번 감사합니다.

우선 이분이 제시한 방법은 content 영역에 class 명을 지정해주는 겁니다.

저 같은 경우는게시글을 보는 영역인 app/views/posts/show.html.erb에서 'panel-body' 라는 이름으로 지어줬습니다.

참고 : class명을 다른걸로 줘봤는데 안되는 것 같습니다.

/app/views/posts/show.html.erb에서 게시글 내용이 나오는 부분에 대한 코딩내용을 아래처럼 입력하고 (class 설정 포함)

<%= content_tag(:div, @post.content.html_safe, :class => "panel-body") %>

/app/assets/stylesheets/application.css에 가셔서 다음 코드를 추가합니다.

.panel-body img{
    max-width : 100%;
    max-height : 100%;
}

혹은, 따로 public 파일 내에 CSS파일을 만들고, 위 CSS내용을 넣은 뒤, /app/views/layouts/application.html.erb에 해당 CSS 파일에 대해 <link rel="stylesheet" href="..."> 를 추가해서 연동을 해주는것도 하나의 방법이 되겠습니다.

이렇게 하시고, 다시 (사이즈가 큰 이미지를 업로드 후) 게시글을 보시면..▲ 이미지가 content 영역 내에 잘 출력이 됨.

이제 이미지가 content 영역 크기에 맞게 잘 출력이 되는것을 보실 수 있습니다!

이슈 : C9에서는 Tinymce가 잘 되는데, 헤로쿠에서 안보인다면?

  • 명령어 입력창(터미널)에 다음 명령어를 입력합니다.

rake assets:precompile

  • /app/views/layouts/application.html.erb에서 <%= yield %> 바로 윗 줄에 다음 코드를 입력해보세요.

<%= tinymce_assets %>

  • 됐습니다!

참고로 이 방법을 적용하면 C9 환경에서 '글쓰기(new)' 에서 글 작성 하실 때 바로 TinyMCE가 안나타날 수 있습니다. TinyMCE가 안나타날 경우 'F5 새로고침'을 한번 하시면 나올겁니다.

참고 1) Github : https://gist.github.com/dannyvassallo/f0fff53bfd88114ec4e7

2) 블로그 - AWS S3 셋팅 : http://blog.naver.com/xmfpes/221011068315

3) 멋쟁이 사자 5기 : 노종원 님

Git자료실 업로드

해당 내용에 대해 이해가 안간다는 글이 종종 보이더라고요.. 'TinyMCE+이미지 업로드'를 활용해서 제작했던 사이트를

이해도를 돕고자 아예 Git자료실에 올렸습니다. 참고 바랍니다.

Git 자료실 : https://github.com/kbs4674/example_final

예제사이트 : https://kcm-lion.herokuapp.com

Git 저장실 혹은 해당 자료 안에 있는 Readme를 꼭 참고해주세요.

results matching ""

    No results matching ""