버즈아트 SEO 관련 작업 정리

 

버즈아트(https://bbuzzart.com) 웹서비스의 검색엔진 최적화 (SEO) 작업 진행 과정을 정리 해봤습니다. 내부 기록과 비슷한 작업을 하는 분들을 위해 두서없이 정리 했습니다.

  • 컨텐츠 서비스를 하고 있는 입장에서 SEO(search engine optimization – 검색엔진 최적화) 엄청나게 중요한 기능이지만 클라이언트를 SPA 만들고 있던 타력 때문에 리뉴얼때도 어쩔 없이 SPA(React) 진행 밖에 없었음

 

  • SPA Applications은 기능을 구현하고 서비스를 만들기에 용이 하지만 Client에서 서비스를 구동 시킨다는 근본적인 한계 때문에 검색엔진 최적화에는 치명적인 문제를 안고 있었음.

 

  • 그래서 만든 대안이 프록시 서버가장 시급한 일이 페이스북 Open Graph에 대한 대응이었기 때문에 페이스북 검색봇이 서비스에 접근하면 User Agent를 확인하고 별도의 프록시 서버로 리다이렉션하여 Open Graph 메타 데이터를 전송하는것으로 기능 구현함

 

  • 구글봇 역시 프록시에서 처리 하였지만 프록시 서버에서 전달하는 데이터가 실제 서비스의 코어 데이터만 전달 하다보니 검색엔진이 크롤러가 온전한 컨텐츠를 모두 가지고 가지 못하는 문제가 생기고 각 컨텐츠 페이지의 링크 구조가 온전하게 검색엔진에 전송되지 않아서 검색 키워드에 대한 검색 결과가 완전하지 나나타지 않는 현상이 발생 하고 있었음

 

  • 서버 랜더링이 위의 문제들에 대한 완전한 해결방안임을 알고는 있었지만 레거시 코드와 기능 구현 문제로 SSR전환을 쉽게 결정하지 못하는 상태로 상당한 시간이 지나감

 

  • React의 경우 Next라는 프레임워크로 서버사이드 랜더링 기능이 지원 되고 있지만 기존에 사용중이던 클라이언트 Navigation 시스템과 User Management 시스템의 상당한 변경 이슈로 결정을 망설이게됨

 

  • 하지만 꼭 해야 하는 일이라서 Next – React 기반의 프로토타이핑 개발을 진행해서 기존 코드와의 변경점을 확인하고 실제 개발에 착수.

 

  • 동시에 구글 서치엔진 SEO 기능에 대한 서베이 및 개발 진행
    • 구글 검색엔진 최적화에 관련한 자료는 대부분 https://developers.google.com/search/docs/guides/ 에서 찾을 있음
    • https://www.google.com/webmasters/tools/home 에서 구글 SEO 관련 셋팅을 진행함
    • 각 컨텐츠에 맞는 구조화 데이터에 대한 메타 데이터 및 LD+Json 스크립트를 지원하면 더 품부한 검색 결과 및 검색결과에서 더 좋은 표시 결과를 얻을 수 있음
    • LD+Json 버즈아트의 경우 컨텐츠를 http://schema.org/VisualArtwork 구조와 같이 생성하도록 구성, 다른 컨텐츠 구조는 적절한 스키마를 찾아서 데이터를 삽입하는 과정을 거침
    • SiteMap은 가능 하면 모든 링크를 크롤링 후 생성해서 업로드 해주는 것이 원하는 경색 결과를 얻을 수 있음
    • 상용 서비스를 이용할 수도 있고 크롤러를 만들 수도 있음
    • 우리는 https://github.com/lgraubner/sitemap-generator 이용하여 Node.js 기반으로 만들어 사용함
    • 컨텐츠는 매일 생성되므로 가능한 자주 SiteMap을 생성하여 업데이트 해주는 것이 SEO에 최적화에 좋은것으로 판단
    • 메타 데이터의 생성은 Next – Head Tag 이용하여 서버 랜더링 상황에서 Setting

 

  • 결론

    • SEO는 참을성이 필요한 작업으로 생각됨
    • 검색엔진의 요청사항을 파악하고 꾸준한 업데이트와 최적화의 과정을 거쳐야 최적화 가능
    • 작업 완료 이후에도 검색봇이 크롤링 해서 인덱싱 하는 과정에 상당한 시간이 소요되므로 개발완료 이후 1~2달에 걸쳐 꾸준히 검색결과의 변화를 확인하고 조금씩 옵티마이즈하는 과정을 거쳐서 최적화 해야함

리액트 네이티브(React Native) 프로젝트에서 생각해야할 것들

 

버즈아트 서비스가 버전 4로 업그레이드 되었습니다. 버즈아트는 신진 작가들을 위한 아트 큐레이션 & 소셜 서비스 입니다.  전세계의 신진 작가들이 작품을 소개하고 소통할 수 있는 서비스 공간을 만들고 있습니다.

이미 3년째 서비스를 운영하고 있고 새로 업데이트된 이번 버전이 네번째 메이저 업그레이드입니다이번 버전은 프론트앤드 기술 스택을 페이스북의 React React Native(이하 RN) 통일(?) 했습니다. 기존의 기술스택(Angular & Native)을 버리고 완전 새로운 기술 스택(React Native & React)을 도입해서 앱과 웹 프론트 개발을 완료 했습니다.  아래 몇가지 이야기로 왜 기술을 바꿨는지 어떤점이 좋은점이고 위험한지 정리해봤습니다.

기술 스택 변경의 이유

버즈아트는 아직 작은 회사 입니다.  많은 기술 인력을 채용할 여력이 없고 운영할 능력도 부족합니다. 하지만 한 팀이 되어야 하고 동일한 어조로 서로 소통 할 수 있어야 한다고 생각 했습니다. React와 RN은 동일한 자바스크립트 기술 기반위에 있어서 적은 개발팀 내부에서 여러가지 언어와 기술 스택이 분리되어 있어서 언어들이 달라서 발생할 수 있는 분리 장벽이 없습니다. 그리고 누군가 어려운 일이 생기면 서로 도움을 주고 받을 수 있는 팀 구조를 만들 수 있다고 생각 했습니다. 이게 작은팀에서는 꽤 중요한 요소 입니다.

크로스플랫폼에 대한 개인적인 환상

제 개인적으로 크로스플랫폼이라는 말에 아주 오~래 된 환상이 있었습니다. 한번 만들면 여기 저기서 돌릴 수 있어 라는 말은 석기시대 때부터 있었던 사기(?) 같은 이야기 였고 자바가 어느정도 그문제를 해결하는가 싶더니 최근엔 LLVM을 통해서 많은 언어들이 이젠 진짜 가능한것 처럼 이야기 하고 있습니다. 리액트와 RN 역시 그 대열에 서 있긴 하지만 역간 다른 스텐스를 취합니다.

페이스북 개발팀은 니가 잘하면 한 70% 정도의 코드는 공유 할 수 있을거야~ 라고 말하더군요. 이정도면 대박 아닌가 하는 생각도 선택의 이유였습니다. 결국은 개인적인 환상을 성취하기 위해 회사를 위험에 빠트리게 됩니다.

선택의 불안감

하지만 불안감이 존재 했습니다. 개인적으로는 꽤 오랫동안 아이폰으로 네이티브 개발을 해왔기 때문에 RN이 네이티브의 성능을 따라갈 수 있을지 의문스러웠습니다. 그리고 RN은 글을 쓰고 있는 현재도 버전 0.45에 머물고 있고 국내에서 성공 사례로 알려진 케이스도 별로 없었습니다.

게다가 RN으로 시작 했다가 네이티브로 돌아간 이야기(https://brunch.co.kr/@jamess/5) 와 같은 블로그가 불안감을 더 높이기도 했습니다.

 

파일럿 프로젝트

그래서 파일럿 프로젝트를 먼저 하기로 했습니다. 성능을 한번 보면 되겠지 싶었습니다. 그리고 새로 만난 팀원들의 합도 한번 맞춰 보구요.

일주일 정도의 작업끝에 메인 피드 하나를 만들어서 각종폰에서 테스트 했습니다. 아이폰은 매우 훌륭한 성능이 나왔고 안드로이드는 뭔가 찜짐하긴 했지만 커스터마이즈를 좀 하고 캐싱을 좀 하면 나아 지겠지 하는 생각으로 이정도면 시작 할만하다고 평가 했습니다.

하지만 그게 아니었다는게 나중에 밝혀 집니다.

 

RN 개발의 기술적인 포인트들

결론적으로 파일럿 프로젝트를 포함해서 아이폰, 안드로이드, 웹프론트를 4명의 인원으로 약 3개월(100)만에 개발완료하고  성공적(?)으로 서비스를 오픈 했습니다.

그 과정에서 겪은 몇가지 기술적 혹은 개발 운영 측면에서 본 문제점 및 해결 방안을 아래와 같이 정리 해보겠습니다.

CSS

RN의 개발과정은 웹프론의 개발 과정과 동일한 순서와 방법으로 진행 하는 것이 좋습니다웹프론트를 개발해 보신분은 아시겠지만 UI 디자인이 나오면 CSS를 이용해 화면을 먼저 만들게 됩니다. 그리고 HTML이 나오면 거기에 데이터를 입히는 과정을 진행 하죠.

기존 네이티브앱 개발은 한명의 개발자가 화면구성과 데이터 연결을 동시에 작업하는 것이 일반적이었지만 RN의 특성상 CSS를 이용한 화면 구성이 이루어 지므로 CSS를 잘 다루는 웹 퍼블리셔가 필수적인 요소입니다.

다행히 저희팀에는 CSS를 아주 잘 다루는 개발자가 있었습니다.  이것이 중요한 또 한가지 이유는 일반적으로 Hot-Loading을 이용한 시뮬레이터 기반에서 개발을 하게 되는데 이게 주로 아이폰 시뮬레이터 기반에서 개발을 시작하기 때문에 나중에 안드로이드에 올려보면 화면이 깨지거나 오동작을 하는 경우가 꽤 빈번하게 발생합니다. 이유는 아직 RN이 베타라서 그럴 수도 있고 CSS를 깔끔하게 정리 하지 못한 탓일 수도 있습니다만 제 생각으로는 RN으로 만든앱들에서 UI관련된 오류 문제는 거의 CSS를 잘못 만든 탓이 아닌가 싶습니다.

 

리스트 컨트롤

앱개발에서 가장 많이 쓰는 컨트롤은 리스트 컨트롤입니다. 아이폰과 안드로이드 각각 다른 이름의 리스트 컨트롤이 있지만 앱화면의 거의 대부분은 이 리스트 컨트롤 기반으로이루어진다고 해도 과언이 아닙니다. RN에도 ListView라는 리스트 컨트롤이 있습니다.

저희팀이 앱을 거의 다만들고 여러가지 폰에서 테스트를 시작하면서 고난에 빠지게 된 이유가 이 ListView 때문이었습니다. 아이폰은 매우 깔끔하게 잘 돌아갔습니다. 물론 아이폰도 리스트를 계속해서 로딩 하다보면 메모리 부족 현상이 나타나면서 앱이 크래시 되는 문제가 더러 있었습니다만 가장 심하게 나타난 것은 역시 안드로이드 구중에서도 하위 기종에서 문제가 많았습니다.

10페이지를 넘기지 못하고 앱이 죽어 버리는 경우가 다반사 였습니다. 꽤 심각 했습니다. 문제의 해결방법을 찾던중 RN 3월 이후 버전에 FlatList 라는 컨트롤이 있다는걸 발견 했습니다몇일이 걸리긴 했지만 ListView FlatList 변경 했습니다.

링크(https://facebook.github.io/react-native/blog/2017/03/13/better-list-views.html) 살펴 보시면 있겠지만 FlatList 메모리 사용과 성능 문제에서 기존 ListView 가지고 있던 문제들을 대부분 해결 했고 저희팀도 결과로 확인 할수 있었습니다.

안드로이드 하위 기종에서도 크래시없이 거의 모든 페이지를 보여주는 결과를 보여 줬습니다.

 

브리지 라이브러리

RN은 기본적으로 웹뷰가 아닌 네이티브 방식으로 실행됩니다. JS를 통해 만든 코드를 앱 내부에 임포트된 네이티브 코드를 실행 시키면서 기존의 웹뷰 빙식의 하이브리드 앱보다 더 빠르게 실행 시킬 수 있도록 만든 플랫폼입니다.  이것은 기존에 만든 네이티브 스테틱 라이브러리를 사용할 수도 있다는 이야기 이기도 합니다. RN에서 지원해 주지 않는 기능들은 네이티브로 만들어서 연결 할 수도 있다는 이야기 입니다. 그것을 위해 존재하는 연결방법이 브리지 라이브러리 입니다.

https://js.coach/react-native 에는 이미 만들어서 사용가능하게 구성된 상당이 많은 라이브러리들이 있고 그 라이브러리들은 아이폰과 안드로이드를 동시에 지원 하도록 구성된 것들이 많습니다.

하드웨어 연결 혹은 카메라, 비디오, 기타 다양한 기능을 가진 브리지 라이브러리들이 있고 만약 없다면 스스로 만들 수도 있습니다.

 

자바스크립트

웹프론트팀을 운영하고 있는 회사라면 JS 기술 혹은 환경에 대해 익숙 할 수도 있지만 네이티브앱만 만들어 왔다면 JS로 앱을 만드는 일에는 꽤 많은 허들이 존재 할것 같습니다.

ES6, Webpack 기타등등.. 너무 많은 디펜던시에 얽혀 있어서 요즘은 JS헬이라는 말도 있을 정도입니다만 Create-React-Native-App 같은 cli도구를 이용하면 기본적인 환경 구성은 쉽게 수도 있습니다. (https://github.com/react-community/create-react-native-app)

그렇지만 JS를 이용한 개발은 어쩔 수 없는 공부시간이 필요한것 같습니다. 최근에는 TypeScript를 많이들 사용해서 JS Type 오류들을 해결해 나가면서 구조화 시키는 기술들을 많이 사용하고 있는것으로 확인하고 있습니다. 저희도 다음 업그레이드에서는 TypeScript를 도입해 보려고 준비하고 있습니다.

 

결론

RN은 매우 매력적입니다.

개인적으로 가장 매력적인것은 더이상 아이폰앱을 만드는 AutoLayout을 사용하지 않아도 된다는 부분이었습니다. 사실 애플이 AutoLayout을 도입한건 매우 큰 실책이라고 여전히 생각하고 있습니다. Flex Layout얼마나 좋은데요.

아이폰과 안드로이드를 한개의 코드 베이스로 개발하고 동일한 기술스택으로 웹까지 개발 할 수 있다는 것은 예산이 적은 스타트업에겐 매우 좋은 소식이 아닐 수 없습니다하지만 기존의 개발 습성과 기술 전환에 들어가는 리스크와 비용을 생각하면 쉽게 올라 탈 수 있는 말은 아닌것 같습니다.

또 하지만 리스크에 도전하고 그 성취감에 쩌는 개발자야 말로 진정한 이시대의 진정한 개발자가 아니겠습니까? 한번 해보세요. 재미 있습니다.

그래서 성능은 어떠냐구요? 저희 앱 한번 깔아 보세요. 보시면 압니다.

박병일(billy@bbuzzart.com)

 

아이폰 다운로드

https://itunes.apple.com/us/app/bbuzzart-new-art-in-your-hand/id868618986

안드로이드 다운로드
https://play.google.com/store/apps/details?id=net.bbuzzart.android

개발자 채용 홈워크 과제

버즈아트는 신진 작가를 위한 아트 소셜 서비스 입니다. 그리고 인터넷 기술 기반의 테크컴퍼니입니다. 기술로 더 나은 인간의 삶을 만들수 있을 것이라고 꿈꾸는 기업입니다.

인터넷 테크기업의 어려움은  항상 좋은 사람을 구하는 일인것 같습니다. 많은 회사들이 다양한 방법으로 개발자들을 충원 하고 있지만 정말 이 방법이 옳은것 인가에 대해서는 항상 고민이 많습니다. 기초적인 알고리듬에 대한 질문 부터 개발 언의의 기술적 내용을 묻는 질문들을 면접에서 묻고 평가 하려고 하지만 이런 순발력을 요구 하는 답변을 잘하는 것이 기술자를 평가하는 모든 잣대가 되는것에 조금은 의문을 가지고 있습니다.

그래서 조금 더 편안한 환경에서 자신의 기술적 성취를 평가 받을 수 있는 방법을 생각하다가 홈워크를 하는 것으로 평가하면 어떨까 하는 생각을 했습니다. 각 플렛폼 별로 간단한 과제를 개발자 자신이 자유로운 방식으로 결과물을 만들고 GitHub.com을 통하여 제출하는 방식으로 기술적 평가를 해보려고 합니다.

그리고 제출한 지원자의 노고를 생각해서 소정의 개발 비용을 면접시에 드리려고 합니다.

대략의 순서는 아래와 같습니다.

  1. 프로필(이력서)을 이메일로 제출 하시고 아래의 API 데이터를 각 플렛폼(웹, 아이폰, 안드로이드) 별로 데이터를 가지고 와서 자유 형식으로 화면에 보여주는 코드를 작성 하시면 됩니다.
  2. 오픈소스 라이브러리를 사용할 수 있습니다만 모든 코드를 오픈소스에서 베껴서 제출하는 것은 안됩니다. REST 통신 혹은 이미지 캐시 등의 기술적 난이도가 높은 부분에서 일상적으로 사용하는 오픈소스를 사용할 수 있습니다.
  3. 완료된 소스는 제출자 개인의 아이디로 만든 Github.com 에 Public 모드로 업로드 하고 채용 담당자에게 완료 이메일과 함께 링크를 보내 주시면 됩니다.
  4. 채용 담당자는 소스 평가 후 면접일정을 알려드리고 면접시에 소정의 개발 비용을 드립니다.

API

본 과제는 마무리 되어 API 주소를 삭제 하였습니다.

위의 API링크는 아래 이미지와 같이 현재 버즈아트 홈페이지에 있는 Curators’s Pick의 다섯개 이미지를 가지고 오는 API와 동일한 테스트 API링크 입니다. JSON형태의 리턴 구조를 가지고 있고 data key 내부에 배열의 형태로 5개의 데이터가 수록되어 있습니다.

개발자의 역량에 따라 다양한 형태의 뷰구조를 만들 수 있는 데이터를 API 내부에 수록되어 있습니다. 데이터 구조를 파악하시고 원하는 형태로 뷰어 구조를 만들어 제출 하시면 됩니다.

bbuzzart-new-art-in-your-hand-2017-01-31-11-06-18

채용정보

  1. 아이폰 부문 – https://www.rocketpunch.com/jobs/23263
  2. 안드로이드 부문 – https://www.rocketpunch.com/jobs/23264
  3. 웹 프론트 부분 – https://www.rocketpunch.com/jobs/23265

AWS ELB를 활용한 사례 – 버즈아트

버즈아트(http://bbuzzart.com)는 신진 작가들을 위한 버티컬 아트 소셜 서비스 입니다.버즈아트 서비스 비즈니스에 대한 자세한 이야기는 최근 아웃스탠딩의 기사(http://outstanding.kr/buzzart2017021)를 읽으시면 더 많은 정보를 얻을 수 있을것 같습니다.

이번글에서는 버즈아트에서 AWS를 어떻게 활용하여 서비스에 이용하고 있는지에 대해서 한번 써보겠습니다. 많은 기업에서 이미 AWS를 활용하여 서비스를 하고 있고 많은 분들이 기술적인 경험을 가지고 있겠지만 실무에서 활용한 작은 경험이 글을 읽는 블로그 독자들에게 도움이 되기를 바랍니다.

As is

제가 합류한 시점에 버즈아트는 이미 AWS를 이용해서 서비스를 하고 있었습니다. 글로벌 타겟으로 하고 있는 서비스이기 때문에 해외 리전에 서버를 두고 운영을 하고 있었습니다. 그 시점에서의 간단한 서버 구성은 아래 그림처럼 직렬화된 구조 였습니다. 서비스 초기에 인프라에 대한 안정성 혹은 효율성을 염두에 두기가 쉽지 않은 부분이 여실히 드러나는 구조 였습니다.

tech_blog_2-2017-01-25-14-28-48

서버는 그림 처럼 직렬화 되어 있고 어느 한 부분에서 문제가 발생하면 서버스 전체가 중지 될 수 있는 위험성을 안고 있었습니다. 이런 시스템의 문제는 인프라에서 발생하는 문제 보다 서비스 개발 운영중에 나타날 수 있는 소프트웨어의 작은 버그 하나로도 서비스 전체가 중지 될 수 있는 취약한 문제점을 안고 있었습니다. 운영 조직이 따로 없는 작은 스타트업에서는 개발자들이 늘 서버시의 운영상태에 촉각을 곤두세우고 있어야 하고 문제 발생시에 즉각 대응 하지 못하면 서비스가 중단되는 사태를 맞을 수 밖에 없는 치명적인 리스크를 안고 불안한 하루 하루를 보내야만 합니다.

To be

버즈아트에 합류하고 한달쯤 기존 인프라에 대한 스터디를 마치고 마음속으로는 이것이 답이 될 것이다 라는게 있었습니다. 그동안 여러 경로를 통해 공부해온 AWS ELB(Elastic Load Balancing)를 쓰면 최소한 인프라 측면에서 발생하는 몇가지 문제는 해결 할 수 있겠다라는 생각이 있었지만 이것이 옳다고 큰소리로 이야기할 자신이 없었습니다. 이유는 개인적으로 실제 서비스 경험이 없었기 때문입니다. 그래서 확신을 가지고 이렇게 하면 문제가 없습니다 라고 말하기가 좀 어려웠습니다.

AWS ELB의 장점이 여러가지가 있겠지만 제 개인적으로 생각하고 있는 장점은

  1. 갑자기 늘어 날 수 있는 사용자에 대한 대응이 가능 하다.
  2. 소프트웨어 및 하드웨어 버그로 나타날 수 있는 서비스 장애에 대한 대응이 가능하다.

정도의 두가지를 생각했습니다. 먼저 사용자 폭증에 대해서는 Load Balancer를 사용하는 가장 중요한 목적이므로 따로 언급할 필요도 없을것 같습니다. 하지만 두번째 소프트웨어 버그 및 하드웨어 장애로 인한 시스템 장애의 경우는 항상 나타날 수 있는 문제 이므로 바른 시간내에 적절한 대응을 하여야 하지만 대응을 하는 동안에도 서비스는 계속 되어야 하므로 서비스 중단 사태를 최소화 할 수 있는 대응 방안이 될 수 있다고 할 수 있습니다.

Test Project

앞서 말한대로 문제는 경험이 없어서 아무리 AWS가 안정적인 시스템이라고 하더라도 무언가 한번 만들어 보지 않고 실 서비스에 도입을 하는데는 약간의 꺼리낌이 있었습니다. 그래서 테스트 프로젝트를 하나 만들었습니다. 아래 그림과 같이 AWS에서 가장 비용이 적은 인스턴스 두개를 생성하고 각각에 Node.js를 이용해서 개발한 서비스를 만들고 앞단에 ELB를 이용해서 로드 발란서를 붙이고 인스턴스 뒷단에 RDS 기반의 MySQL 데이터 베이스를 설치해서 시스템을 구성 했습니다.

앞의글(https://tech.bbuzzart.com/2017/01/06/구글-vision-api를-이용한-예술작품-분석)에서도 뭔가 간단한 테스트에는 Node.js가 최고 라고 이야기 한바 있습니다만 Node.js를 이용해서 간단한 웹 서비스와 REST API를 통하여 RDS MySQL 데이터를 조회하는 시스템을 구성 했습니다. 그리고 jMeter를 이용해서 서버에 부하를 가하는 테스트를 수차례 실행 했습니다.

아주 간단한 서비스 시스템이라 버그의 가능성으로 인한 서비스 오류의 가능성이 적은탓에 일부러 서버 하나를 중단 시키거나 서비스를 수동으로 내리는 방법으로 테스트를 진행 했고 개인적으로 이 정도면 가능 하지 않을까 하는 확신과 함꼐 ELB 셋팅 방법을 숙지 했습니다. 제 생각엔 이게 중요한 문제 였던것 같습니다. 알고는 있지만 셋팅과정에서 나타날 수 있는 문제들을 미리 한번 시뮬레이션 해보는 것이 자신감을 높이는 좋은 방법이라고 생각 됩니다.

DNS & Running

한번 해보면 두번째는 쉽습니다. 실제 운영할 사이즈의 인스턴스를 n개 만들어 API서버와 웹서버를 각각의 인스턴스에 설치하고  RDS에 DB 인스턴스를 생성해서 기존 데이터를 리스토어 하고 실제 운영 테스트를 시작 했습니다. 그런데 기왕에 사용하기 시작한 AWS인데 아예 DNS까지 AWS것을 사용하는게 시스템 호환성 측면에서 더 좋은 것이 아닐까 하는 생각이 들었습니다. 이미 AWS에는 Route53이라고 하는 꽤 쓸만한 DNS시스템을 가지고 있기도 합니다.

그래서 기존에 국내 업체를 통하여 운영중이던 DNS 시스템을 AWS Route53으로 이전 하는 작업을 준비 했습니다. AWS ELB 기반으로 모든 서버 셋팅을 완료 하고 일정 기간 테스트를 거쳐서 테스트가 마무리 되는 시점에서 DNS를 국내업체에서 Route53으로 이전 했습니다.  DNS 이전 작업중에 서비스가 이전 서버와 AWS 서버로 중복 접속되는 부분이 일부 있었고 사용자 데이터의 일부가 양쪽 서버에 분산되는 격미한(?) 오류가 있었고 이런 데이터는 수작업(?)으로 이전 하는 작은 사고가 있었지만 크게 무리 없이 서버 이전 작업을 마무리 할 수 있었습니다.

tech_blog_2-2017-01-25-14-29-29

결론

아마존 AWS는 이미 많은 업체들이 사용하고 있는 대표적인 클라우드 시스템입니다. 안정성 면에서나 비용면에서 타의 추종을 불허 하지만 모든 기능을 제대로 알고 사용하고 있는 곳이 그렇게 많지 않은것 같습니다. 물론 제 의견입니다. 아닐 수도 있습니다(다들 이미 아시는데 저 혼자 생각일 수도 있습니다.) ^^;

ELB를 도입하고 나서 버즈아트는 API서버,  WEB서버의 업그레이드시에 서비스를 중단하지 않고 서버 개별 업그레이드를 진행할 수 있습니다.  소프트웨어는 언제나 오류를 발생 시킬 수 있고 하드웨어 또한 항상 문제 발생의 가능성이 있습니다. 하지만 가장 중요한건 서비스는 항상 정상적으로 가동 되어야 한다는 것일 것 같습니다.

글을 쓰고 보니 AWS 광고 하는것 같이 되어 버렸습니다만 전혀 그렇지 않습니다. 우리(버즈아트)가 어떻게 일을 하고 어떻게 하면 좀 더 편하게 시스템을 관리 할 수 있을까 하는 고민의 끝에 실행한 결과를 블로그 독자들과 나누고 싶은것이 이 글의 의도 입니다. 그리고 앞으로 계속 합류할 더 많은 개발자들을 위한 업무 히스토리를 남기는 일이기도 하구요.

사족

비용의 측면에서 보면 기존의 시스템과 ELB시스템은 그리 큰 차이가 나는 것은 아닌것 같습니다. 기존의 1개의 서버는 매우 큰 인스턴스를 사용 했고 이후에 인스턴스는 좀 더 작은 것들을 병렬로 연결 했기 때문에 비용이 비슷하고 DNS에서 약간의 비용이 더 발생하는 정도로 방어(?) 한것 같습니다. 더 큰 이득은 이전에도 큰 문제는 없었습니다만 불안감이 좀 줄었고 고민하지 않고 편안하게 밤잠을 잔다는 정도?

마지막으로

개발자를 충원하고 있습니다. 개발자가 일하기 좋은 문화를 만들어 보겠다는 생각은 많지만 혼자 되는 일은 아닌것 같습니다. 함께 만들어 가실분! 아래 링크를 참조 하세요

https://www.rocketpunch.com/companies/bbuzzart/jobs

박병일(billy@bbuzzart.com)

구글 Vision API를 이용한 예술작품 분석

버즈아트(http://bbuzzart.com)는 신진 작가들을 위한 아트 소셜 서비스 입니다. 2015년에 서비스를 시작해서 올해로 3년차에 접어 듭니다. 사이트를 보시면 아시겠지만 다양한 작품들이 올라 옵니다. 유화, 수채화, 그래픽 아트, 사진작품까지 다양한 컨텐츠가 매일 수십 혹은 수백점씩 업로드 되고 있습니다.

2017년 상반기 버즈아트 테크팀의 기술적 목표를 컨텐츠의 개인화로 잡고 있습니다. 누가 어떤 작품을 좋아하고 작품을 좋아하는 경향이 어떤지를 분석해서 좀 더 개인화된 피드를 제공하는데 기술적 목표를 가지고 진행하려고 계획중입니다. 그런데 어떤 기준으로 이미지를 분류 해야 할지 무척 난감 하더군요.

개인적으로는 최근 머신러닝 붐도 있고 해서 이미지분석과 관련된 스터디를 작년부터 하고 있었습니다만 수학적 기반이 부족해서 상당한 고통(?)을 받고 있던 상황이라 이걸 어떻게 해결해야 하나 하는 고민을 하고 있었습니다. 그래서 미술전공한 알바를 고용해서 작품 하나하나를 다 분류 해 볼까 하는 생각까지 했었습니다만 그것도 쉬운일은 아니었습니다.

미리 말하는 결론은 구글 Vision API를 이용해서 성공적으로 약4만여작의 작품을 카테고리별로 분류 완료 했습니다. 예술 작품을 머신러닝으로 분류 한다는것 자체가 어쩌면 말도 안돼는 이야기 일 수도 있지만 어쩌면 오히려 사람이 분류 하는것보다 더 객관적인 데이터를 줄 수도 있지 않을까 하는것이 제 생각이었습니다. 그래서 머신러닝을 API로 서비스 하는 업체들을 찾기 시작 했습니다.

필요기능

처음에 서베이 해 본  머신러닝 엔진은 구글 Vision API (https://cloud.google.com/vision) 와 아마존 Rekognition 입니다. 구글 Vision API는 아래의 그림1과 같이 페이지에 접속해서 이미지를 드래그 드롭하는것 만으로도 테스트가 가능합니다.

vision-api-image-content-analysis-google-cloud-platform-2017-01-06-14-03-56

[그림1 구글 Vision API]

위의 그림과 같이 이미지를 드롭하면 머신러닝 분석 결과를 몇가지 타입으로 분류해 줍니다.

  • Label – 이미지가 가지고 있는 내용 특성을 분류 합니다. 우측 결과처럼 그림의 애용에 따라 % 를 보여줍니다. 제가 가장 필요 했던것이 이것입니다. 예를 들면 이미지에 강아지가 있다면 Dog n%의 형태로 결과를 보여줍니다.
  • Text – 이미지에 문자가 있다면 OCR 결과를 보여줍니다.
  • Face – 이미지에 얼굴이 있다면 안면분석 결과도 보여줍니다.
  • Color – 이미지가 가자고 있는 컬러를 정량적으로 알려줍니다.
  • SafeSearch – 성인물, 폭력등의 요소가 있는지 찾아줍니다.

아마존 Rekonition(https://aws.amazon.com/ko/rekognition) 역시 구글과 비슷한 정도의 분석 결과를 만들어 주지만 테스트 결과 안타깝게도 Color분석 기능이 없어서 제 테스트 목록에서 빠졌습니다만 대략 두 업체 모두 비슷한 정도의 가격과 성능을 보여 주고 있었습니다.

amazon-rekognition-%eb%94%a5-%eb%9f%ac%eb%8b%9d-%ea%b8%b0%eb%b0%98-%ec%9d%b4%eb%af%b8%ec%a7%80-%eb%b6%84%ec%84%9d-2017-01-06-14-17-26

[그림 2 아마존 Rekoginition]

가격

각 분석엔진의 비용은 아래 링크를 참조하시면 됩니다. 결론적으로 저는 구글 API를 무료로 사용하게 되었는데 이유는 계정을 만들고 카드를 등록하니 300달러의 크레딧을 무료로 지급해 주더군요. 이미지 분석을 마치고도 꽤 많은 크래딧이 아직 남아 있습니다. ^_^

버즈아트 작품들을 카테고리별로 분류하기 위해서는  Label, Color 두가지 요소에 대한 분석이 필요했기 때문에 구글 Vision API를 이용하기로 결정 했습니다.

개발과 API

현재 버즈아트 서버는 Java/Spring 기반으로 구성되어 있지만 간단한 유틸리티 혹은 테스트 프로젝트는 거의 Node.js기반으로 진행하고 있기 때문에 이 프로젝트 역시 Node.js로 개발하기로 하고 JavaScript API를 검색하니 아래의 링크에서 찾을 수 있었습니다.

https://github.com/googlecloudplatform/google-cloud-node#google-cloud-vision-alpha

개발을 시작하기전에 Google Console(https://console.cloud.google.com)을 통하여 계정에 앱과 API Key를 먼저 생성하여 준비합니다.

설치는 아래와 같이 진행합니다.

$ npm install --save @google-cloud/vision

실제 구현한 코드는 대략 아래와 같습니다.

var vision = require('@google-cloud/vision')({
    projectId: 'bbuzzart-image-process',
    credentials: visionkey --> 구글에서 받은 키(생략 ^^;)
});

var options = {
    verbose: true,
    types:[
        'properties',
        'label'
    ]
};
function detectImage(work, callback){

    var img = work.thumbnailM;
    var workid = work.work;
    vision.detect(img, options, function (err, detections, apiResponse) {
        if (err) {
            if (err) console.log(err);
            callback();
        } else {
            var colors = detections.properties.colors;
            var labels = detections.labels;

            async.parallel([
                function(cb){
                    if (colors.length > 0){
                        addColors(workid, colors, function(err){
                            cb(err, workid);
                        });
                    } else {
                        cb('No Colors', workid);
                    }
                },
                function(cb){
                    if (labels.length > 0){
                        addLabels(workid, labels, function(err){
                            cb(err, workid);
                        });
                    } else {
                        cb('No Labels', workid);
                    }
                }
            ], function(err, result){
                callback();
            });
        }
    });

}

위 코드는 실제 동작한 코드의 일부입니다. vision.detect() 함수의 결과로 JSON을 구글로부터 받아서 파싱하고 데이터베이스에 저장하는 과정을 거쳐서 아래 화면의 결과를 얻을 수 있었습니다. 물론 화면에 뿌리는 별도의 코드가 있습니다. ^^

bbuzzart-contents-manager-2017-01-06-17-50-09

bbuzzart-contents-manager-2017-01-06-18-04-01

결론

작품 이미지를 분류하는 일은 피드 개인화의 가장 기초적인 작업입니다. 누가 어떤 작품을 많이 보는지 보는 사람이 좋아하는 작품이 어떤 경향을 가지는지 하는 일을 향후 더 많은 작업들을 거쳐야 하지만 이미지 컨텐츠를 서비스 하는 기업에서는 이미지에 대한 분류가 가장 기본적인 작업일것이라고 생각됩니다.

작년 알파고 사태(?) 이후로 머신러닝에 대한 관심이 개발자들 사이에서도 매우 높고 많은 책들과 자료들이 나오고 있지만 기술 난이도가 매우 높고 저와 같이 수학맹인 사람이 넘기에는 매우 높은 벽인것 같습니다. 하지만 해야하는 업무는 꼭 완수해야하는 개발자의 입장에서는 비용이 들더라도 효과적인 방법이 있다면 그걸 사용하는 것도 좋은 방법이 될것이라고 생각됩니다.

몬스터 하나를 제압 했으니 이젠 다음 스테이지로 넘어 갑니다. 또 블로깅 하겠습니다.

박병일(billy@bbuzzart.com)