마이갤러리 개발 삽질기 – 2) AJAX는 축구팀이 아니다

사실 이번 미니프로젝트를 기획하며 가장 주안점을 둔 사항 중 하나는 "JS와 친해지기" 그 중에서도 "AJAX 기법과 친해지기" 였다.

AJAX는 "Asynchronous JavaScript and XML" 의 약자로 비동기적인 웹 애플리케이션 제작을 위한 웹 개발 기법이라고 한다. 우리나라 개발 커뮤니티에선 "에이작스" 라고 읽는 것이 보편적인 것 같고 아주 가끔 "아작스" 랄지 "아약스" 라고 읽는 분 있다.

기술 이름이 참 거창하다..... 참고로 내가 옛날부터 좋아하고 잘 아는 Ajax는 아래 사진과 같다. 

마! 암스테르담 등킨 드나스 무 밨나!

죄송하다.

AJAX를 만든 분이 해당 축구팀과의 매칭을 노리고 이름을 지은 것 같진 않지만...AJAX라는 명칭은 내가 생각하는 신박한 IT기술 네이밍 중 하나이다. 

사용 분야는 방대하다. 아마 우리가 요즘 살면서 하루라도 AJAX 기술을 경험하지 않고 살기는 정말 어려울 것이다. 네이버 야구 생중계창에서 자동으로 스코어 바뀌는 것, 그것이 바로 에이작스다. 페북 댓글 단다고 새로고침 되지 않는 것, 그것이 바로 에이작스를 통한 웹 앱 구현이다. 

백엔드 개발을 하며 AJAX를 위한 API개발을 하지 않는 경우는 거의 없다. 더구나 지금 내가 기획한 것처럼 CRUD기능이 있고 회원가입 등 폼에서 중복 방지 로직을 구현하려면 AJAX의 적용은 선택이 아닌 필수가 된다.

 

AJAX 실행의 흐름

간단하다. 웹페이지 상의 특정 이벤트(문자열의 입력, 버튼의 클릭, 화면 아래 끝까지 스크롤을 내리기 등)를 받았을 때 미리 정의해놓은 스크립트가 실행되며 XMLHttpRequest를 서버로 전송하고, 그 요청에 대한 response를 받아와 다시 스크립트 상에 정의된 바에 따라 웹페이지를 통해 사용자에게 노출시키는 것이다.

옛날부터 사용되었던 XMLHttpRequest, 즉 XHR이라는 명칭이 즐겨 사용되고 있지만 최근 AJAX 구현에서 request와 response는 JSON(JavaScript Object Notation)을 사용하는 것이 일반적이다. 이는 JSON의 포맷 자체가 몹시 가벼우면서도 인간도 이해하기 쉬운 직관성을 갖고 있기 때문이고, 그냥 다른 사람들이 많이 써서 그렇기도 하고, 무엇보다 jackson 등의 의존성을 통해 POJO에서 JSON으로의 변환이 무척 빠르고 쉽기 때문이기도 하다.

그래서 AJAX를 구현하고 실행시키기 위해서는...

  • Script가 필요하다. 외부에 정의된 .js 파일이든 웹페이지 내의 스크립트 영역이든 스킙트가 정의되어 있어야 한다.
  • 백엔드 로직이 필요하다. 이 로직은 적당한 JSON 응답을 돌려줄 수 있어야 한다.
  • 통신을 시작시킬 이벤트를 구상해야 한다. 버튼을 클릭하게 할 것인가? 폼을 채워넣게 할 것인가? 심지어 일정 주기로 계속 AJAX 요청을 날리게 짤 수도 있을 것이다(이 기법을 "에이작스 폴링" 이라고 하는데 1단계에선 다루지 않는다).

<마이갤러리> 에서의 적용.

마이갤러리 프로젝트에선 다음의 분야들에서 AJAX 통신을 적용했거나, 적용할 예정이다. 

  • 회원가입 시, 아이디 중복의 체크. 아이디를 입력받음과 동시에 서버에 XHR을 날려 중복 여부를 실시간으로 체크한다.
  • 카테고리 생성 시 카테고리명 중복의 체크. 개념은 상동.
  • 방문자 초대링크 생성. 버튼을 누르면 짠 하고 새 링크가 뜨는 개념.
  • 추후 구현할 메시지 수발신 로직 구현 시에, 받을 회원 이름을 자동완성시켜주는 로직(구현예정).
  • 일정 주기로 서버에 접속해 새 메시지가 있는지 여부를 체크(구현예정).

 

아이디를 입력하다가....
중복이 발생돼 경고창을 보여줬다.

시행착오 끝에 이제 AJAX에 대해 조금이나마 이해하게 된 바, 그 눈물나는 삽질기를 여러분과 차근차근 공유해 보고자 한다. 

회원가입 폼

회원가입 폼에서 AJAX의 역할은 단 하나 - 중복된 아이디로 회원가입이 이뤄지는 것을 프론트단에서 막아내는 것이다.  우리가 흔히 누르는 [중복 확인] 버튼을 구현하는 개념이라고 생각하면 쉬울 듯하다.

버튼을 누르는 방법도 충분히 괜찮지만, 그냥 입력하기만 해도 자동으로 판정이 떨어지는게 더 힙하다(...)고 생각해서 사용자가 한 칸 한 칸 아이디를 채울 때마다 에이작스 통신이 일어나도록 기획하였다.

그런데 칸이 비어있거나 아이디가 너무 짧은데도 에이작스 통신이 일어나는 것은 낭비라고 생각했다. 칸이 비어있다면 아직 입력하지 않은 것으로 간주해 어떠한 동작도 하지 않고, 아이디가 다섯 글자 이하라면 좀 더 입력하라는 메시지를 프론트단에서 노출하고 서버로는 어떠한 통신도 이뤄지지 않게 설계하였다.

비밀번호에 대한 중복체크는 (당연히) 구현하지 않았고 다만 6글자 이상을 암호로 사용하도록 설계했다. 아이디가 중복되지 않으면서 비밀번호가 6글자 이상인 경우 회원가입 버튼을 활성화하도록 구현하였다.

아래는 회원가입 폼을 위한 자바스크립트 코드다:

 join.js


간단한 코드인데 쓸데없이 엔터만 많이 쳐 놔서 길어보이는 거다;;

원리는 정말 간단하다. 아래에서도 설명하겠지만 아이디 입력 폼에서 텍스트 입력 이벤트가 일어날 때마다 checkId()를 실행시킬 것이다.

아래는 글자가 한땀한땀 입력될 때마다 상기한 스크립트가 실행되게끔 설계한 HTML 폼이다.

JOIN.HTML


checkId()는 서버와의 AJAX 통신을 수행한다. 데이터는  HTTP POST로 던질 것이고, 서버는 중복 여부를 unique라는 boolean 오브젝트에 담아 돌려줄 것이다.

만약 입력한 아이디가unique하다면(중복이 일어나지 않아 서버가 unique = true를 반환했다면) 전역 변수로 선언한 idCheck에 true가 입력될 것이고, 아이디 중복 경고창은 jQuery hide 메소드를 통해 사라질 것이다. 마지막에는 setJoinButtonActive()가 실행되어 아이디와 비밀번호 모두 조건을 충족한다면 회원가입 버튼을 활성화시킨다.

말로 하니 어렵다;;

백엔드 로직도 한 번 살펴보자.

APICONTROLLER.JAVA

DUPLICATEDINFOCHECKER.JAVA


본래 AJAX를 위한 비즈니스 로직 구현에 있어서, 받은 오브젝트를 그대로 되돌려주는 것이 best practice라고 알고 있다. 즉, 지금 우리의 상황을 보면 회원가입을 통해 Admin 객체를 만들어내고 있기 때문에 에이작스 response로도 Admin 객체를 똑같이 되돌려주는 것이 가장 좋은 구현이란 얘기다.

그러나 지금의 케이스에 똑같이 적용하기에는 무리가 있다. 우선 우리는 회원가입 과정 중 하나인 "아이디 중복 체크" 를 만들고 있기 때문에 논리적으로도 아직 Admin 객체가 만들어지지 않은 상태다.

또한 회원가입 폼에 구현된 AJAX의 응답으로 Admin 객체를 반환한다면, 그 안에 담겨있는 암호를 비롯한 각종 회원 정보가 불필요하게 한번 더 전송되는 취약점을 갖게 된다.

따라서 나는 AJAX response를 위한 별도의 클래스를 구현하는 것이 맞다고 판단했고 그 결과가 DuplicatedInfoChecker 다. 이름이 맘에 들지 않는다. 이런 경우에 사용하는 컨벤션이 있는지 알고 싶다. 

ApiController에는 @RestController 어노테이션을 붙여놓았다. 이를 통해 리턴값이 POJO가 아닌 JSON으로 반환될 수 있게 구현할 수 있다. POJO에서 JSON으로의 변환은 com.fasterxml.jackson에서 담당하게 된다.

회원가입 창에서의 AJAX 구현 삽질은 이것으로 마무리됐고, 다음 포스팅에서 초대링크 생성 과정에서의 AJAX 적용 삽질기를 공유해보고 싶다.

public static void main (String args[]){
System.out.println("hello, wordpress!");
}