Better Ajax with Rails
웹개발을 하다보면 전체 페이지를 다시 로딩하지 않고 부분적으로 내용을 업데이트 해야할 일이 많이 생깁니다. Front-end 의 MVC framework를 쓰는 경우가 아니라면 보통 이런 상황에서 Jqeury 의 Ajax 기능을 생각하게 되는데요, 이번 글에서는 이 기능을 좀 더 세련된 rails 방식으로 구현하는 법을 소개해드릴까 합니다.
예를 들어서 페이지 내에 한 부분에서 키워드를 사용해서 리스트를 검색한 후에 검색결과를 비동기 방식으로 부분적으로만 업데이트 하는 기능이 있다고 생각해 봅시다.
이런 경우에 다음과 같이 jquery의 ajax fuction을 사용해서 구현한 경우를 쉽게 접할 수 있습니다.
ajax 로 받아온 데이터를 미리 정해놓은 HTML element 안에 차곡차곡 쌓아 rendering 하게 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
$.ajax({ type: "POST", url : 'some_request_url', data : 'some_keyword', contentType : "application/x-www-form-urlencoded; charset=UTF-8", timeout: 5000, success: function (data) { var $title = $('<h1>').text(data.results[0].title); var $description = $('<p>').text(data.results[0].description); $('#search_result') .append($title) .append($description) }, error : function(data){ $("#search_error").show(); } });
간단하게 html을 업데이트 하는 경우에는 jquery 방식이 간편하고 사용하기 편할 수 있는데요, 다음 예제와 같이 업데이트 하는 부분의 html 코드가 조금 복잡해 지기 시작하면 이부분을 string으로 조합해서 append 하는 일이 결코 단순한 작업은 아닐 수 있습니다. 여기에 class, style 등의 attribute 값들이 붙기 시작하면 코드의 가독성도 떨어지고 디버깅도 따라서 힘들어 지게 됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$.ajax({ type: "POST", url : 'some_request_url', data : 'some_keyword', contentType : "application/x-www-form-urlencoded; charset=UTF-8", timeout: 5000, success: function (data) { var image = "<img height='14' width='14' style='display:inline-block; float: right;' src='some_image.png'/>"; var keyword = "<div class='keyword_text' style='display:table-cell'>" + data.results[0].keyword + "</div>"+image; $('#search_result').append("<li class='row postlink' id='row"+idx+"' " + "onclick='javascript:keyword_clicked("+idx+", \""+name+"\",\""+data.results[0].id+"\")'>"+keyword+"</li>"); }, error : function(data){ $("#search_error").show(); } });
이 비동기 기능을 rails 방식으로 다음과 같이 풀어볼까 합니다.
1) routes.rb
Rails 를 이용해서 비동기 부분을 구현하려고 하면 몇개의 파일에 간단한 수정사항이 필요한데요, 우선 routes 파일에
다음과 같은 요청이 오면 html template을 보내는 대신 js template를 return 할 것이라고 명시해 줍니다.
1
post 'search/search_by_keyword' => 'search#search_by_keyword', defaults: { format: 'js' }
2) controller
그렇게 되면 실제 controller에서는 할일이 특별하게 취해야 할 행동은 없습니다.
app/contollers/search_controller.rb
1 2 3 4
def search_by_keyword return [] unless params[:search_query] @results = List.get_by_keyword(params[:search_query]) end
3) view
routes 쪽에 명시된 내용으로 naming convention을 추측해보면
views/search라는 directory에 search_by_keyword 라고하는 파일을 연상하게 될텐데요, 이때 중요한건 우리가 js 로 받을 것이라고 명시했기 때문에 js.erb라는 파일을 생성해야 합니다.
search_by_keyword.js.erb 는 다음과 같이 간단합니다. 필요한 부분을 활성화 시키는 등 기본적인 jquery(javascript) 기능들을 여기에 정리하고, #searched_list 라고 하는 HTML element에 넘어온 데이터를 가지고 실제로 보여줘야 하는 리스트를 생성하면 됩니다. 실제로 #searched_list 라고 하는 element는 searched_list 라고 하는 partial에 담겨 있습니다.
1 2
$("#searched_list").html("<%= escape_javascript (render 'searched_list') %>"); $('#searched_list_area').show();
그럼 실제로 js.erb쪽에 명시된 partial에 들어가서 기존에 html template 작업하듯이 하심 됨니다. 이때 넘어간 데이터는 controller에서 넘어온 @results 입니다.
/view/search/_searched_list.html.erb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
<%= @results.each do |result| %> <li> <a href="/result/<%=result[:id]%>" class="some_link"> <span class="some_span"> <img src="<%= result[:image] %>" class="thumb_nail" alt="<%= result[:title]%>"> </span> <div class="class1"> <div class="class2"> <div class="class3"> <strong class="class4"><%= result[:title] %></strong> <span class="class5">"<%= result[:description]%>"</span> </div> </div> </div> </a> </li> <% end %>
4) action
앗 여기서 중요한 것 하나. ajax 로 부른다는 건 일반적으로 front end 쪽에서 user가 므슨 엑션을 취했다는 뜻일텐데요,
여기서는 검색버튼을 눌렀을때에 저런 일련의 엑션들이 생성이 되는 형태입니다.
검색 input field 하고 연관있는 form을 submit 했을때 일어나게 되어 있습니다.
views/search/_search_input_box.html.erb
1
<%= form_tag('/search/search_by_keyword', id: :search_form, method: 'post', remote: true) do %>
여기서 중요한건 remote:true —> 이 부분인데요, 이 remote 라고 하는 attribute 값이 ajax call을 사용하겠다는 뜻이 됩니다.
submit 버튼을 누르고 chrome dev tool에서 network flow를 보면요, 아래와 같이 ajax 콜이 생성된것을 볼수 있습니다.
이상으로 간단하게 rails를 사용하여 ajax 기능구현 방법을 소개 해 드렸는데요, 위와 같은 rails 방법으로 좀 더 명시적인 흐름을 알 수 있게 구현한다면 가독성도 높일 수 있을 뿐 아니라 기본적인 rails의 "convention over configuration" 이라는 기본 사상을 고수하면서 유지보수/디버깅에도 효율적인 방법이 될것이라고 생각합니다.
Popit은 페이스북 댓글만 사용하고 있습니다. 페이스북 로그인 후 글을 보시면 댓글이 나타납니다.