[Ruby on Rails] 웹에디터 Summernote 사용시 서버로 로컬 이미지 업로드후 삽입



- Summernote 는 좋은 에디터입니다. 
상당히 이용하기 편리하면서, 클립보드에 있는 이미지도 복사되는 좋은 구조이지요. 

기존까지 약 140개의 글은 이미지 업로드를 이미지를 코드화 해서 넣었습니다. 

기존의 소스 코드를 보면 아래와 같이 data:image/   
와 같은 형태로 이루어져있습니다. 






지금은 사진 폴더를 따로 관리할 필요가 없이, 하나의 데이터베이스만 있으면 되고,
다른 ajax 를 통한 서버와의 통신이 필요 없습니다. 

하지만, 지금 같은 이미지 코드화 같은 경우에는 DB 사이즈가 너무 커지고 불러오는 속도가 너무 느린 단점이 있습니다. 
포스팅 한 글이 140 개 임에도 불구하고, DB 사이즈가 무려 200MB가 넘는 불상사가 발생한 것이죠. 

다른 곳에서 포스팅 한 정보를 가져와보았습니다. 
아래와 같은 특징을 가지고 있습니다. 


가. 서버에 업로드 방법(킴스큐 1.2 방식)

1) 장점    -  업로드되는 공간(폴더)을 관리할 수 있다.     -  이미지명을 컨트롤할 수 있고 길이를 조절할 수 있다.     -  이미지 소스에 해당 이미지 위치가 노출됨으로 향후 관리/가식성을 높일 수 있다.    -  별도의 모듈(1.2- upload/2.0-mediaset)을 통해서 이미지만 따로 관리할 수 있다. 2) 단점     - 이미지 갯수만큼 서버 커넥션이 이루져야 한다.

나. 이미지를 코드화해서 html 소스에 직접 삽입하는 방법(summernote 방식)

 1) 장점     - 별도의 업로드 과정이 필요 없다.    - 별도의 파일폴더명/파일명 관리를 하지 않아도 된다.(그냥 html 소스 중 일부로 융화)    - 페이지 로드시 이미지에 대한 추가 커넥션이 필요없다. (속도와 관련)    - 이미지에 대한 서버 커넥션이 없기 때문에 ssl 적용한 사이트에서 이미지 주소 url 로       보안에러 발생(특히 IE) 가능이 희박해진다.            2) 단점     - html 소스가 길어진다. 실제로 파일 사이즈가 커진다.(속도와 관련)    - 가식성이 떨어지고 소스를 직접 편집하거나 할 때 불편하다.     - 별도로 이미지만 관리하기가 불편하거나 어렵다.



사실 아래의 구조를 쓰다가 1년 2개월 만에 바꾸는 것은 속도였습니다.
불러오는 속도도 문제지만 그것보다는 작성할 때, 용량이 너무 커져서 속도가 느려지는게 문제였습니다. 

용량 4MB 만 넘어가도 급격히 에디터의 속도가 느려지는 문제가 발생하더라구요. 
이런 문제점을 극복하기 위해서 방법을 찾아보았고, 기존보다 지식도 많이 늘어나서 두려움도 적었고,
마침 좋은 포스팅 글을 발견해서 도전해보았습니다. 

summernote에서는 기본으로 이미지 파일을 Base64 dataURL 방식으로 인코딩하여 DB에 저장합니다.
따라서 이미지 크기가 클 경우 해당 글을 저장할 수 없게 되거나 DB에서 많은 용량을 차지하여 서버의 퍼포먼스를 떨어뜨리는
주범이 되기도 한다. 

가끔 서버가 죽는 경우가 있었는데, 이게 원인이 되는 것 같기도 합니다. 


마침, summernote에서는 몇가지 콜백 함수를 지원하여 가능한 작업이 되었습니다. 
다만, ruby on rails 에 대한 지식이 부족해서, 쉽게 하기는 어려웠습니다. 

하지만 이 기회에 블로그 수정도 결국 성공했고, coffescript도 체험해 볼 수 있었습니다. 
다만, 원글과 다소 다른 점이 있습니다. 

 


- 과정 설명 

>저 같은 경우 coffeescript를 잘 몰라서 찾아보니 javascript의 간편한 형태였습니다. 
http://js2coffee.thomaskalka.de/
해당 링크에 들어가면 coffeescript <--> javascript 동작이 수행 가능합니다. 

CoffeeScript 란 ?
 CoffeeScript 는 복잡한 문법을 가지고 있는 자바스크립트 언어의 특성 때문에 나오게된 일종의 언어 입니다. 좀 더 자세히 설명하자면 커피스크립트로 작성된 파일은 자바 스크립트로 변환되어 사용 되지만 좀더 간단한 문법으로 스크립트를 작성할수 있도록 해줍니다.
 사용의 용도는 당연히 Javascript 문서를 더욱 간결하게 작성하기 위해서 입니다. 간단한 예제를 아래의 코드로 확인해 보시기 바랍니다. 아래의 코드는 Coffeescript.org 에서 확인하실수 있습니다. 




app/assets/javascripts/ 디렉토리에 coffeescript 파일을 하나 생성하고 아래와 같이 코드를 작성한다.
여기서는 summernote_upload.coffee 라고 파일명을 정하기로 한다.

저는 원래 소스 코드에 툴바의 속성들을 추가해줬습니다 . 


sendFile = (file) ->
data = new FormData
data.append 'upload[image]', file
$.ajax
data: data
type: 'POST'
url: '/uploads'
cache: false
contentType: false
processData: false
success: (data) ->
$("#summernote").summernote "insertImage", data.url

$(document).ready ->
$("#summernote").summernote
lang: 'ko-KR'
height: 800
toolbar: [
[
'style'
[ 'style' ]
]
[
'font'
[
'bold'
'italic'
'underline'
'clear'
]
]
[
'fontname'
[ 'fontname' ]
]
[
'font'
[
'strikethrough'
'superscript'
'subscript'
]
]
[
'fontsize'
[ 'fontsize' ]
]
[
'color'
[ 'color' ]
]
[
'para'
[
'ul'
'ol'
'paragraph'
]
]
[
'height'
[ 'height' ]
]
[
'table'
[ 'table' ]
]
[
'insert'
[
'link'
'picture'
'video'
'hr'
]
]
[
'view'
[
'fullscreen'
'codeview'
]
]
[
'do'
[
'undo'
'redo'
]
]
[
'help'
[ 'help' ]
]
]
codemirror:
lineNumbers: true
tabSize: 2
theme: "solarized light"
callbacks: onImageUpload: (files) ->
sendFile files[0]




위의 코드가 작동하기 위한 서버 환경을 준비해 보자.
우선, 파일 업로드를 가능하게 하기 위해서 Gemfile에 paperclip 젬을 추가하고 설치한 후 기본 셋팅을 해야 한다.

gem "paperclip", "~> 4.2"
gem 'summernote-rails', '0.7.1.0'





번들 인스톨 명령을 실행 후(서버에 반영하기 위해서는 반드시 로컬웹서버를 다시 시작해야 함),
아래와 같이 빈 모델을 생성한다.

이름은 upload로 하자.

1
$ rails g model Upload




paperclip 젬이 설치되면 paperclip이라는 제너레이터를 사용할 수 있게 된다.
따라서 아래와 같이 명령을 실행하여 Upload 모델에 paperclip젬에서 사용하게 될 속성을 생성하기 위해서
마이그레이션 파일을 생성하도록 한다.

이 때 이미지를 업로드할 속성을 지정해야 하는데 여기서는 편의상 image로 정하도록 한다.

1
$ rails g paperclip Upload image




이제 마이그레이션 명령을 실행하여 실제 데이터베이스 테이블(uploads)를 생성한다.
이제 schema.rb  파일에서 uploads 테이블 코드 부분을 보면 아래와 같게 된다.

create_table "uploads", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
end




이제 방금 생성한 Upload 모델 클래스 파일을 열고 아래와 같이 작성한다.

class Upload < ActiveRecord::Base
has_attached_file :image
validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif", "image/JPG", "image/JPEG", "image/PNG", "image/GIF"]
end




다음은 Upload 모델에 대한 컨트롤러(uploads_controller.rb)를 아래와 같이 생성한다.
여기서는 우선 create 액션 하나만 생성하도록 한다.

1
$ rails g controller uploads create





그리고 방금 생성한 컨트롤러 파일을 열고 아래와 같이 작성한다.

class UploadsController < ApplicationController
protect_from_forgery except: :create

def create
@upload = Upload.new(upload_params)
@upload.save

respond_to do |format|
format.json { render :json => { url: @upload.image.url } }
end
end

private

def upload_params
params.require(:upload).permit(:image, :image_file_name, :image_content_type, :image_file_size, :image_updated_at)
end
end






uploads#create 액션이 제대로 라우팅되도록 config/routes.rb 파일을 열어 아래와 같이 추가해 준다.

1
post 'uploads' => 'uploads#create'




이로써 이 글의 시작 부분에서 작성했던 coffeescript 파일이 작동할 수 있도록 서버측 환경 셋팅이 완료되었다.
이제 실제로 브라우저에서 확인해 보자.
summernote 에디터를 열고 로컬 PC에 저장되어 있는 이미지를 마우스로 드래그하여 summernote 에디터로 드롭해 보자.

지금까지 코딩 작업이 제대로 동작한다면 public/system/uploads/images/ 디렉토리에 해당 이미지가 존재하게 되고 summernote 에디터에는 해당 이미지가 삽입되어 보이게 된다.


아래의 그림을 이미지를 드래그 하여, 에디터에 넣어보았다. 

아래와 같이 이미지가 등록되게 된다. 
이 이미지를 개발자 도구를 통하여 링크를 확인해보았다.  





이를 확인해보면 아래와 같이 서버에 잘 올라가 있는 것을 확인 해 볼 수 있습니다. 
이미지 용량은 76.21 K 로 별로 크지 않네요. 







개발자도구에서 링크를 확인해보면 /system/uploads/images/  ~~~  로컬 폴더에 생성되게 됩니다. 

밑의 스크린샷 이미지는 클립보드에서 복사 붙여넣기 한 이미지입니다. 



클립보드에서 붙여넣기 한 이미지도 잘 들어갔네요 !! 

이 이미지는 용량이 2.6M 나 되네요. 

스크린샷을 기존에 많이 올렸는데, 그게 오버헤드의 주 원인이었던 것 같습니다. 





그리고 스크린샷 이미지를 몇개 넣었지만 느려지는 것은 잘 못 느끼겠습니다. 

간만에 성공했군요 !! 
기분이 좋습니다. 
속도가 매우 빨라졌습니다 !! 


- 출처 - 
https://github.com/kimsQ/rb/issues/60
https://withrails.com/2015/06/06/bootstrap%EC%9A%A9-wysiwyg-%EC%9B%B9%EC%97%90%EB%94%94%ED%84%B0-summernote-%EC%82%AC%EC%9A%A9%EC%8B%9C-%EC%84%9C%EB%B2%84%EB%A1%9C-%EB%A1%9C%EC%BB%AC-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%85%EB%A1%9C/
http://www.tutorialbook.co.kr/entry/CoffeeScript-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0