티스토리 뷰

처음에 느껴진 jQuery와 Angular의 차이



jQuery(이하 jq)는 솔직히 보자면 프레임워크가 아니다. 기존에 존재하는 Javascript를 좀 더 편한 사용을할 수 있게 만들어 주는 라이브러리 같은 개념이었다. 그렇기 때문에 View를 구성하고 소위 자료를 저장하는 Model을 관리하지는 않는다. 그에 반면 Angular(이하 ng)프레임워크라고 할 수 있다.


자바 진영의 Best 프레임워크인 스프링과 비슷한 느낌을 주며, 개발 시 강력한 가이드모듈 인젝션을 제공해 주기 때문이다. 그런데 문제라고 할 수 있는 것이 jq에 숙달된 상태에서 ng는 많은 자유를 뺏는 기분이었다. jq에서는 DOM부터 Javascript까지 자유 자재로 접근하고 쓸 수 있었지만, ng는 정해진 틀이 있고, 그 틀 안에서 구현하기를 강조하기 때문이다.



물론 이러한 틀에 숙달되면 문제가 없지만...



ng에서 가장 강점 중 하나는 Model부터 View까지 직통 연결이라는 점이고, Two-way Binding을 지원하는 것이었다.

이점을 각각 풀어 보도록 하겠다.



M에서 V까지 직통 연결



서버와 클라이언트가 통신하는 환경에서 API를 통해 JSON 타입의 자료를 서버로부터 받는 환경으로 개발하고 있었다. 이때 JOSN으로 받은 데이터(이하 Model)을 View까지 표현하기 위해서는 jq의 경우 View를 접근하고, 이를 풀어서 적절하게 가공하며, 동적으로 HTML을 생성해서, 해당 위치에 대치하거나 추가하는 방법을 사용하였다.



하지만, ng는 HTML과 병행된 Template 페이지에 사용할 모델을 적시 적소에 넣어만 주면 된다. 물론 그것들을 가공하는 것은 ng의 특유한 지시어의 도움이 조금 필요하지만, jq때와 비교하면 손쉽게 View 구성이 가능해 진다. Template 페이지 경우 자바로 개발 시 JSTL과 비슷한 느낌이 나긴 하지만, 그것보다는 HTML 문서 지향적이고 간단한 지시어로만 사용가능하기 때문에 ng쪽이 뭔가 발전되고 성숙한 느낌이 든다.



물론 Server-side가 아닌 Client 내에서 템플릿 페이지가 렌더링 되기 때문에 그것에서 오는 차이가 있다. 잠깐 집고 넘어가자면 JSTL을 쓰는 JSP는 템플릿 페이지에 모든 모델 정보들을 넣어서 HTML로 만든 이후에 클라이언트로 보내는 것이고, ng는 일단 모델 받고 템플릿 페이지 받아서 Client의 웹 브라우져에서 렌더링하는 것이다. 이에따라 각기 장점은 존재하는데, 요즘 서버 성능만큼 사용자가 가지고 있는 PC 성능도 높기 때문에 웹 브라우져에서 렌더링 하는 것이 많은 시간을 소모하지 않기에 개발 트렌드는 이쪽(Client에서 렌더링)으로 흘러가고 있다.



ng에서 Model과 View관계를 간단히 설명하기위해 아래 코드를 확인하자. (공식 홈에 가면 잘 나와있다.)

<!doctype html>
<html ng-app>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
  </head>
  <body>
    <div>
      <label>Name:</label>
      <input type="text" ng-model="yourName" placeholder="Enter a name here">
      <hr>
      <h1>Hello {{yourName}}!</h1>
    </div>
  </body>
</html>

HTML 페이지에 단순히, ng만 CDN으로 선언한것이다. 물론 ng에 직접 들어가면 Controller 연결 없이 이렇게 쓰는 경우는 거의 없지만, ng가 어떤 녀석인지 이해하기에는 좋은 예제임에 틀림없다.


{{}} 기호 안에 들어가는 것은 개발자들이 익히 알고 있는 변수다. 물론 변수라고 치부하기에는 모델이라는 거창한 말이 있지만, 일단 변수다. 값을 넣고 빼는 그 저장소이다. 그런데, 웹 코딩에서는 이러한 변수 선언은 Javascript에서 하는 것으로 알 고 있지만, ng에서는 위와 같은 방식으로 사용하면 html 내에서 바로 선언 및 사용 가능하다.



html 태그를 살펴보면 ng-app이라는 attribute가 있는 것을 알 수 있다. 이게 중요한 건데, 이 페이지에 ng를 적용하겠다라는 의미인 것이고, 이 아래에 위치해야 ng의 능력을 사용해 볼 수 있다.

input 태그에 attribute 중 ng-model이 있는데, 이건 이 input 태그의 value 값을 여기에 적힌 변수에 넣겠다라는 것이다.

여기서 재미있는 것이, 따로 이벤트가 없어도 저 변수에 값이 들어간다는 점이고, h1 태그 안의 {{}}의 기호 안에 그 변수가 그대로 적혀있는데, 변수의 값을 가져와 출력한다는 것이다.


즉, 다른 이벤트 처리 없이 바로 실시간 반영되어 동적으로 input에 입력한 값이 h1출력된다는 점이다.


변수에 대해 한가지 집고 넘어가자면 웹 개발 하면서 언제나 써왔던 그것인 json object 형태로도 사용 가능하다. 물론 복잡하게 쓰려면 Controller 에서 이를 관리 해야 한다.


관련한 좋은 예제들은 검색 및 ng 홈페이지에 가면 충분히 습득 할 수 있기 때문에 그곳을 확인하시길 바란다.



프로젝트에 들어가서 처음 한일 - Masonry Style 적용


웹 서비스를 만들 때 가장 공을 쏟는 곳 중 하나가 메인 페이지이다. 구성하려는 서비스의 특성 상 많은 아이템들을 화면에 보여줘야 했다. 그래서 첫 시도는 ng-material에서 제공해 주는 gird를 기반으로 1:1 사이즈의 격자에 아이템을 배치하여 출력했었다. 하지만, 밋밋한 느낌이 들었고 재미없다는 느낌 또한 들었다.


이를 뭔가 멋지게 바꿔보고 싶었는데, 그때 논의 된 것이 '핀터레스트' 였다. 핀터레스트와 같은 UI 구조를 워터폴 혹은 마손리 스타일이라고 하는데, 이 스타일을 차용하여 그대로 개발하려는 서비스에 적용하기로 했다.


그리고 지옥은 시작되었다.



핀터레스트의 UI는 많은 개발자들의 손을 거치고 다듬고 만들어진 그것일 것이다. 하지만, 서비스 개발간 웹 개발은 나혼자였다. 그렇기에 제일 먼저 이러한 마손리 스타일을 라이브러리의 힘을 빌어와 구성하기로 하였고, 선정을 위해 이것 저것 검색하기 시작했다.

이때, 나는 앵귤러와 일반 JS 간의 호환이 잘 될것이라 믿고 있었고, 처음부터 내가 사용해 보왔거나, 인지도 있는 녀석을 대상으로 검색하였었다. 처음 선정된 것은 shuffle.js 였다. 동적으로 출력되는 것부터 에니메이션, 아이템 검색 까지 이것 저것 맘에 드는 녀석이었지만, 막상 화면에 적용해 보니 크나큰 문제가 봉착하게 되었다.



바로 ng-material에 파생된 필연적인 문제인데.... 바로 속도 문제였다. 정확히 속도 보다는 Sync 문제이고, ng-material이 화면을 구성하고 이게 마무리되는 시점을 모른다라는 것이 최악의 상황인 것이다. 도대체 Shuffle은 언제 시작하고 적용해야 할 지 몰라, 꼼수로써 0.5초 뒤에 적용하기 위해 setTiimeout 함수를 차용하기 이르렀다. 


하지만, 세부적인 조정, 무한 스크롤 등의 추가로 뭔가를 해보려 했지만, 호환성 실패(일반 Javascript 상황에서는 되지만, ng위에서는 안되는...), 기능의 제약 등으로 적용 실패를 하였고, 그 다음 도입을 시도한 것이 jquery-masonry였다.



jquery-masonry를 처음 본 순간 내 운명이라고 생각할 정도로 많은 세부적인 기능과 다른 라이브러리 연동으로 확장성 있게 사용할 수 있는 것이 너무나 매력적으로 보였고, 실제 서비스에 적용을 해본 결과 손쉽게 UI를 구현할 수 있었다. 물론 이것 또한 ng 전용은 아니기에 호환성을 맞추는 작업이 힘들었지만, 그것을 성공해 놓고 화면 출력된 결과물을 보니 뿌듯하였다.



하지만.... 지금까지도 팀원끼리 회자되는 '마손리의 저주'가 이때부터 시작되고 있었으니....



바로 스크롤 이벤트의 처리를 할 수 없다라는 것이다. 이것이 jquery-masonry의 문제인 것인지 ng 문제인 것인지, 아니면 다른 라이브러리의 문제인 것인지 알 수 없는게 더 큰 문제였다. 무한 스크롤과 Image-Lazy-Load는 이러한 스크롤 이벤트가 핵심인데 이벤트 처리가 어디에선가 off를 한건지 막혀 버린 것이었다. 또한, 버리고 사용할 만한 혹은 대체할 만한 라이브러리도 선정할 시간도 없었다.


그래서 많은 장고 끝에 0.1초에 한번씩 타이머 이벤트를 발생시키고, 첫 페이지의 가장 하단에 비어있는 div를 절대 좌표계로 top 요소를 통해 출력하게 하고, 그 위치를 가져오고 계속하는 방식으로 어떻게든 만들어 내었다. 이 과정에서 setTimeout과 setInterval과 대응되는 존재인 $timeout, $interval 로 사용해야 ng 호환성을 높이면서 이벤트 처리에 사용할 수 있다는 것이다.


이미지를 느리게 출력하는 것은 서버에서 가장 가벼운 흐린 이미지를 먼저 출력하고, 차후 스크롤 위치에 따라 큰사이즈 이미지를 출력하게 해주는 라이브러를 사용하였지만, 마손리의 저주로 파생된 스크롤 이벤트의 먹통으로 서버쪽에서 이미지를 여러 사이즈로 몇 부를 만들고 이 중 적당하고 가벼운 것을 사용하여 바로 출력하는 것을 차용하였다.


3화에서 계속...

댓글
댓글쓰기 폼