Published on

Rails remote를 사용해 비동기로 서버 응답 요청하기

Authors
img1
  • 목차

문제

웹서비스의 기능을 개발하다 보면 비동기로 서버의 응답을 받아서 처리해야 할 때가 있습니다. 가장 쉽게 좋아요 기능의 예를 들 수 있습니다. 화면의 새로고침 없이 좋아요를 표시하고 서버에 그것을 반영하는 기능을 개발하려고 합니다.

개발환경

  • Ruby 2.6.3
  • Rails 6.0.0.rc1
  • haml + sass

해결

  1. 비동기라는 단어를 듣지 마자 생각나는 것은 ajax 라는 단어일 것입니다.
  2. 하지만 이번엔 rails의 remote 기능을 사용해 비동기 좋아요 기능을 개발해 보려고 합니다.

likes/_buttons.html.haml

.buttons
  - if current_user.present? and letter.likes.pluck(:user_id).include?(current_user.id)
    = link_to image_tag("buttons/liked@3x.png", class: "btn-like"), likes_path(letter: letter), remote: true , method: :post , class: "btn", id: 'js-like-touch-' + letter.id.to_s, "data-turbolinks": "false"
  - else
    = link_to image_tag("buttons/fill-36@3x.png", class: "btn-like"), likes_path(letter: letter), remote: true , method: :post , class: "btn", id: 'js-like-touch-' + letter.id.to_s, "data-turbolinks": "false"

좋아요 버튼을 보여주는 partial 입니다. haml 문법으로 쓰여 있음에 유의해 주세요. (erb를 사용하시는 분은 converter를 사용하셔도 좋습니다) 여기서 중요한 것은 remote: true라는 부분입니다. 링크에 remote를 설정해 주면 페이지를 이동하지 않고 요청에 따른 응답을 처리하게 됩니다. 나중에 응답을 처리하기 위해 id를 동적으로 생성해 줍니다.

routes.rb

Rails.application.routes.draw do
  post '/likes', to: 'likes#create'
end

route에 post 요청에 대한 controller를 연결합니다.

controllers/likes_controller.rb

  def create
    unless current_user.present?
      redirect_to user_session_path
      return
    end
    liked = Like.find_by(user_id: current_user.id, letter_id: params[:letter])
    @letter = Letter.find_by(id: params[:letter])
    if liked.present?
      liked.destroy
      return
    end

    like = Like.new
    like.user_id = current_user.id
    like.letter_id = params[:letter]
    like.save
end

create 요청에 대한 응답을 작성합니다. .js에 대한 응답을 따로 지정하지 않으면 controller가 create에 해당하는 파일을 자동으로 찾습니다. 특정 응답에만 작동하게 하고 싶으면 |format| 에 따라서 응답을 설정하실 수 있습니다.

create.js.erb

$('#js-like-touch-<%= @letter.id %>').replaceWith("<%= j render partial: 'likes/button', locals: {letter: @letter} %>");

create 액션에 해당하는 js파일입니다. 내가 좋아요를 누르면 이 js 파일이 실행됩니다. .erb 형식을 보면 알 수 있듯이 레일즈 템플릿 또한 사용할 수 있습니다. 저는 미리 link의 id를 letter.id로 미리 지정해 두었습니다. 내가 받은 입력에 해당하는 id를 선택해 replace 해줍니다. partial에서 if 문으로 letter 모델의 좋아요 여부에 따라 이미지를 다르게 출력하게 작성해 놓았으므로 다시 렌더링하라고만 해주면 됩니다.

결론

RubyOnRails(이하 rails)와 Rails Templete를 사용해서 하는 개발은 요즘 유행하는 Backend / Frontend의 구분이 명확하지 않기 때문에 처음에는 좀 어려웠습니다. 더군다나 ajax를 사용하지 않고 rails의 기능에 의존하는 것은 너무 의존하는 게 아닌가 싶기도 합니다. 하지만 보시다시피 아주 명쾌하고 강력합니다! 따로 ajax 설정을 해주지 않아도 됩니다. 만약 서버에서 push하고 싶으면 rails action cable 기능을 사용하면 됩니다. 쉽고 빠른 Rails의 세계로 오세요!

더 자세한 내용은 Rails에서 javascript 사용하기 문서를 참조해 주시기 바랍니다.

(광고) 나를 위해 쓰는 편지 헤아림 서비스를 많이 사랑해 주세요!