1. Why AJAX?
Ettopia에서 AJAX를 사용하기로 결정한 이유는 '새로고침을 사용하지 않는 기능'을 구현하기 위해서였다. 대표적으로는 코멘트 기능과 like 기능이 있었는데, 이러한 기능들은 새로고침이 있을 경우 사용자에게 굉장한 불편함을 초래할 수 있다. 따라서 새로운 URL로 routing하던 기존의 방식은 '사용자의 편의성 증대'를 목표로 삼고 있는 Ettopia에 적합하지 않았기 때문에, 비동기 방식으로 데이터를 업로드하고 불러오는 AJAX가 필요했다.
2. About AJAX
먼저 AJAX란 서버와 통신하기 위해 XMLHttpRequest 객체를 사용하는 것으로, 페이지를 리로딩하지 않고도 일부 페이지의 데이터를 업데이트할 수 있는 '비동기 방식'을 가진 자바스크립트와 XML이다. 따라서 AJAX를 사용하여 웹페이지를 개발하면 즉각적으로 데이터베이스에 정보를 연결하고 실시간으로 업데이트가 필요한 부분을 개발할 수 있다. 전체 페이지를 새로고침하지 않고 필요한 부분의 정보만 받아오기 때문에 그만큼의 리소스 낭비를 최소화할 수 있는 장점을 가지고 있다. 그러나 HTTP 클라이언트의 기능 및 지원하는 Charest에서 한정되어 있으며 연속으로 데이터를 요청할 경우 서버 부하가 증가할 수 있다. 따라서 AJAX를 웹페이지 개발에 사용하기 위해 특징을 잘 파악하고 사용할 필요가 있다.
📌참고: '비동기 방식'이란?
비동기 방식이란 웹페이지를 새로고침하지 않고 계속해서 데이터베이스에서 데이터를 불러오는 방식을 가리킨다. 동기화 방식과 비동기화 방식의 차이는 다음 그림과 같다.

3. AJAX와 시행착오
Ettopia의 리뷰 Like 기능을 AJAX를 통해 구현하기 위해서는 jQuery에 대해 알 필요가 있었다. jQuery는 웹사이트에서 자바 스크립트를 쉽게 활용하기 위해 도와주는 자바스크립트 라이브러리로, AJAX와 관련된 다양한 메소드를 제공한다. AJAX가 객체를 얻은 후 url을 통해 받은 응답 결과에 따른 함수를 실행하는 구조로 되어 있는데, 자칫하면 코드가 길어질 수 있는 이러한 구조를 개발자가 쉽게 사용할 수 있도록 도와주는 것이 바로 jQuery이다.
jQuery를 통해 AJAX를 사용하기 위해서는 가장 먼저 사용할 메소드가 어떤 기능을 수행하는 지 알아야 할 필요가 있었다.
$.ajax({
type : 'post',
url: '{{url_for("add")}}',
data : JSON.stringify(review_dic),
dataType : 'JSON',
contentType: "application/json",
success : function(data) { //data는 내가 flask에서 return 받은 데이터 이름
console.log(data['elementId'])
$("#" + data['elementId']).text(data['like_num']);
},
error : function() {
alert('서버 통신에 실패하였습니다.');
}
})
다음과 같은 방식으로 AJAX를 사용하였는데, 이때 사용된 $.ajax()가 가장 보편적으로 사용되는 메소드로 모든 jQuery AJAX 메소드 중에서도 통합적인 메소드이다. 해당 메소드의 내부 형식은 다음과 같다.
- type : 데이터를 전송하는 방법
- url : 클라이언트가 HTTP 요청을 보내는 서버 주소
- data : 데이터의 형식. JSON.stringify()를 통해 문자열로 변환.
- dataType : 서버에서 받을 데이터의 타입
- contentType : 보내는 데이터의 타입. 주로 "application/json"이 쓰인다.
- success/error : AJAX의 요청이 성공/실패했을 때 실행되는 callback 함수
이처럼 한 메소드를 사용하는데도 알아야 할 내부 형식이 많으며 AJAX를 사용하기 위해 jQuery에 대한 기본 지식을 가지고 있어야 하기 때문에 다소 어려움이 있다. 특히 Ettopia의 Like 기능을 구현하기 위해 $.ajax() 메소드를 사용할 때 url에 어떠한 것을 입력해야 할 지 많은 고민과 수정이 이루어졌다. Ettopia는 Goormide에서 Flask를 사용하여 개발했기 때문에, Flask에서 사용가능한 url_for 함수를 사용하여 python 파일에 만들어둔 add 함수와 연결시켜 리뷰에 대한 Like 수가 증가할 수 있도록 하였다.
4. Flask, Firebase, and AJAX
Ettopia의 Like 기능을 구현하기 위해 작성한 코드 중 특정 이미지를 틀릭하면 Like 수가 증가하는 코드를 통해 어떠한 방식으로 코드를 구현하였는지 알아보면 다음과 같다.
- application.py
@application.route('/add', methods=['POST'])
def add():
data = request.get_json()
print(f"add 함수 실행 결과: {data['reviewKey']}")
like_num = DB.update_review_like(data['reviewKey'])
return jsonify({ 'result' : "success", 'elementId' : data['elementId'], 'like_num' : like_num})
해당 코드는 AJAX를 사용하여 구현한 부분 중 $.ajax() 메소드 내 형식 중 url 과 연결되는 Python 코드로, add라는 함수가 'POST'를 통해 데이터베이스에서 해당하는 리뷰의 key 값을 받아 update_review_like 를 통해 like_num 을 업데이트하고 jQuery에게 'elementId' 와 변경된 'like_num'을 반환하고 있다.
- database.py
#각 리뷰의 like 수 업데이트 하는 함수
def reset_review_like(self, store_key):
reviews = self.db.child("review").get()
if reviews.each() is not None:
for review in reviews.each():
value = review.val()
if review.key() == store_key:
old_review_like = value['like_num']
update_review_like = old_review_like + 1
keyValue = review.key()
self.db.child("review").child(keyValue).update({"like_num": update_review_like})
print()
return update_review_like
return False
else:
return False
해당 코드는 특정 가게의 고유 key 값을 받아 내부에 있는 모든 리뷰를 가져온 후 웹페이지에서 눌린 리뷰가 무엇인지 key 값을 통해 찾아내 일치하는 리뷰가 존재할 경우 + 1을 해주어 업데이트를 하는 함수이다. 이 함수는 application.py 내부의 add 함수와 연결되어 있어 add를 통해 reviewKey를 받아 함수를 실행하여 update_review_like를 반환한다.
- firebase

다음 사진은 firebase 라는 데이터베이스에 정보들이 어떻게 저장되어 있는지 보여준다. review 라는 부모 노드 아래 각 리뷰에 따른 key 값이 존재하며 각 key 값 당 사용자가 입력한 정보와 구현한 like_num 이 있는 것을 확인할 수 있다. AJAX을 통해 구현하였기 때문에 like_num의 값은 사용자들이 실시간으로 클릭할 때마다 바뀌게 된다.
5. 총평
지금까지 AJAX의 개념과 특징에 대해 알아본 후 Ettopia의 Like 기능 구현 과정을 통해 어떠한 시행착오와 개발 과정을 거쳐갔는지 함께 살펴보았다. 해당 개발을 진행하며 AJAX 라는 새로운 기술을 익혀 활용하는 과정에서도 어려움이 있었으나 이번 개발을 진행하며 가장 어려웠던 부분 중 하나는 진행하는 개발에 맞는 올바른 정보를 찾아내는 것이었다. AJAX의 필요성을 느껴 관련 정보를 알아보며 하나씩 배우고, 코드에 직접 적용해보며 사용법을 익혀나갔기 때문에 다소 시간이 소요되었다. 그러나 끝까지 찾아보며 적용한 결과 성공적인 Like 기능을 구현할 수 있었다. 처음에 시작하기에 다소 어려운 부분들도 있으나 AJAX를 자유롭게 활용할 수 있게 된다면 이를 사용하여 Like 기능 뿐만 아니라 다방면에서 활용가능할 것이라 생각한다.