Photo Layout Editor

Tool & Service Extra

Photo Layout Editor

photo-layout-editor-000.png

photo-layout-editor-001.jpg

사진 레이아웃을 편집하는 도구를 브라우저에서 구동되는 프로그램을 만들게 되었다.

이것을 만들게 된 계기는 Instagram blog에서 사진이 다양한 패턴으로 아름답게 배치되어 있는 모습에서 감명을 받았는데 사진 레이아웃을 편집하고 글 본문에 삽입할 수 있다면 좋겠다는 생각에 미쳐 이렇게 만들게 되었다.

이것이 만들어질거라고는 생각도 못했다. 무엇보다 블럭을 이동하는건 둘째치고 블럭을 이동한 자리에 기존 블럭은 다른 위치에 밀리는 알고리즘을 구현해야하는데 알고리즘 자체를 구현하는건 지금 나로써는 불가능하고, 이런 기능이 구현된 적당한 스크립트 플러그인을 찾아보느라 작업을 시작하지도 않았다.

Plan

작업을 시작하자고 결심하고 시간이 좀 흘러 블럭 배치를 편집할 수 있는 jQuery 플러그인을 발견하게 되었다. gridster.js이라는 것인데 이정도만한 스크립트 플러그인은 더이상 없어서 이걸 발견하고나서 바로 작업에 돌입하게 되었다.

기본적으로 어떤 기능을 넣을건지는 대충 머릿속에 들어있었다.

블럭 속성을 편집할 수 있는 속성폼과, 레이아웃을 편집하는 컨테이너, 이미지를 업로드하고 업로드한 이미지를 모아두는 영역, 선택한 이미지를 크로핑하여 사이즈를 바꾸거나 이미지 위치를 변형할 수 있는 기능들을 화면에 집어넣으려고 했다.
그래서 다음 그림과 같이 먼저 와이어프레임을 그려봤다.

photo-layout-editor-002.jpg

와이어 프레임을 이렇게 그렸다고 디자인이 똑같이 만들어지지는 않았다. 실제로 사용해보면 불편한 UI로 구성되곤 하면 조금씩 디자인을 고칠 생각이었다.

이 과정을 진행하면서 스크립트를 어떻게 작성할것인지에 대해서 고민하기 시작했다.
이 작업에서 대부분의 비중을 차지하는 부분은 javascript인데 단순히 jQuery만으로 작성하면 구조적으로 만들기는 정말로 힘들고 DOM 업데이트에 들어가는 비용이 많이 들어가는걸 잘 알고있어서 좀더 편한 방식을 생각하고 있었다.
마침 react라는 라이브러리를 사용하여 이런저런것들을 만들기 시작하는 때라서 연습해볼까 하는 생각으로 react를 사용하여 작업을 하기로 결심했다.

photo-layout-editor-004.jpg

우선 디자인과 기술적인 부분을 고민하고 정리하여 Trello 서비스를 이용하여 동작 과정이나 만들 컴포넌트, 기능명세서, 해야할일들을 기록해두었다.
디자인 작업 캡쳐화면이나 와이어프레임 캡쳐화면, 참고한 사이트나 관련 소스가 있는 사이트 url들을 추가로 기록해두었다.

무엇보다 내가 해야할일이나 작업해야할 부분들을 기록해두면 잊지않고 할 수 있어서 Trello는 대단히 고마워하는 서비스다.

Design

어떤것들을 구성 할지에 대해서 결정하고나서 디자인 작업을 시작하게 되었다.
처음에는 Photoshop으로 작업을 시작했다. 그저 버릇처럼 디자인작업을 시작하기만 하면 포토샵부터 켜버린다. 포토샵으로 어느정도 작업을 하다가 Sketch 3라는 디자인 프로그램을 알게 되어서 프로그램을 바꿔서 새로 작업하기 시작했다.

photo-layout-editor-003.jpg

와이어 프레임을 그릴때는 쉽게 블럭을 편집하는 법에 대해서 구체적인 계획이 없었는데 실제로 디자인을 해보니 툴바를 만들자는 생각에 미치게 되었다.
그래서 블럭을 편집하는 영역위에 기능을 실행하는 툴바 버튼들을 배치했다.

오른쪽에 이미지를 업로드하고 썸네일 이미지들이 나오는 패널을 넣었다.
이 패널은 닫았다가 열리는 이벤트가 있고, 이미지 위에 그것을 컨트롤하는 버튼들을 배치했다.
본 화면은 이렇게 세가지 형태의 영역을 두고, 팝업으로 선택한 이미지를 크로핑하는 기능을 만들기 위하여 디자인을 했다.

다시 만들긴 했지만 Sketch 3 라는 프로그램에 많이 도움받은 기분이 든다.

Development Environment

디자인 작업을 끝내고나서 개발을 위한 세팅에 많은 노력과 시간을 들였다.
scss와 react같은것들을 그대로 사용할 수 없기 때문에 빌드작업을 통하여 사용할 수 있는 소스로 변환을 해줘야한다. 편하게 빌드할 수 있는 환경을 만들어 두면 빠르고, 개발에 집중할 수 있어진다.

photo-layout-editor-005.png

scss to css로 빌드는 gulp-sass 모듈을 사용하여 쉽게 빌드 스크립트를 작성했다.

하지만 javascript쪽은 대단히 복잡했다. node.js가 등장하고나서 javascript에 대한 많은 개념들이 생겨났는데 이것들이 웹브라우저에서 동작하지 않는것들이어서 gulp, browserify 모듈을 이용하여 빌드를 하려하는데 세팅하는 난이도가 쉽지 않았다.
여차여차 javascript 빌드환경을 만들고나서 개발에 들어갔다. 어느정도 개발하고 난 후에 browserify 모듈을 이용한 빌드환경을 만드는게 너무 힘들기도하고 작동이 썩 좋지는 않았다는것을 깨달았다.

photo-layout-editor-006.jpg

그리하여 당시에 인기가 많은 webpack이라는 모듈 번들러 라는걸 이용하여 빌드환경을 바꿨다.
안그래도 개발하고 있던 소스코드를 확 엎어버리는 시기도 있었고해서 나름대로 시행착로를 겪고있는때에 javascript 빌드환경을 webpack 베이스로 확정지었다. webpack 모듈번들러는 확실히 다른 모듈에 비해서 설정하기가 심플하고 편리했다.

최종적으로 gulp를 빌드실행을 담당하고 css는 gulp-sass, javascript는 webpack-stream 모듈을 사용했고, react와 ea2015 코드를 빌드하는 모듈 프리셋은 babel에서의 babel-preset-es2015, babel-preset-react를 사용했다.

Development

해매면서 개발환경을 구축하고 바로 퍼블리싱과 개발에 들어갔다.
먼저 기초적인 형태를 html 마크업을 하고, css를 작성했다. 아무런 이벤트를 고려하지않고 순수하게 디자인대로 퍼블리싱 작업을 마쳤다.

대략적인 퍼블리싱 작업을 마치고나서 javascript작업에 돌입하면서 react를 손대기 시작했다.

photo-layout-editor-007.png

react가 컴포넌트에서 dom이 들어가기 때문에 퍼블리싱이 사실 개발이나 마찬가지다.
각종 이벤트에 의해 변환되는 화면도 css로 처리하는것이 훨씬 효율적이어서(css3 transform을 높은 퍼포먼스를 가진 애니메이션을 구현할 수 있다.) 스크립트 개발을 하면서 css작성도 같이 한 편이었다.

처음 작업할때에는 최고의 부모 컴포넌트를 한개로 구성을 했다.
그 속에서 각각에 기능에 맞는 컴포넌트들을 넣어놓고 그 하위 컴포넌트 제작을 이어나갔다.

단순한 형태여도 만들다보니 대단히 많은 컴포넌트가 만들어지게 되었는데 이것들을 서로 통신하는법에 대해 많은 어려움을 느끼게 되었다.
flux를 사용해볼까 싶었지만 아직 개념이 이해가 안가는 상태고, 많이 진척된 상태라서 적용하기가 무리가 있었다.

일단 큰 영역을 나누어 가장 큰 부모 컴포넌트를 여러개로 나누고, 부모 컴포넌트 객체들을 한 객체에 담아 관리하는 구조로 바꾸어서 서로 멀리있는 컴포넌트를 통신할 수 있도록 개선했다.

사이드바라는 이름의 컴포넌트는 사진을 업로드하고 업로드한 사진을 담아두는 역할을 하는데 로컬에 사진을 올리거나 서버 프로그램을 호출하여 사진을 서버에 올릴 수 있는 형태로 스크립트를 작성했다.

컨테이너 영역은 툴바 이벤트가 들어가고, 블럭을 편집할 수 있는 gridster jQuery 플러그인이 들어간다.
가장 큰 문제는 gridsterreact 컴포넌트가 아니라서 컨트롤하는일이 여간 쉽지가 않았다.

cropper 컴포넌트들도 그럭저럭 만들어냈다.

result 컴포넌트가 이 작업을 할때의 가장 하이라이트였던 것 같다.
모든 블럭과 이미지들의 데이터를 받아 처리하여 JSON으로 뽑아오거나 이미지 데이터로 뽑아오는 역할을 하는 컴포넌트다.
특히 이미지 데이터로 변환할때 순간적으로 canvas 태그를 만들고 거기에다 그리고 base64 형식의 이미지 데이터로 변환하여 사용하도록 만들었다.

이 작업을 하면서 drag&drop 이벤트를 직접 만들어보는 좋은 경험을 해보게 되었다. 태블릿 디바이스에서 사용 가능하도록 하기 위하여 탭 이벤트도 손보고 하다보니 작업양이 많아지고, 그만큼 작업시간도 길어지게 되었다.

기본적인 기능에 대한 작업이 끝나고나서보니 컴포넌트나 메서드들을 접근할 수 있는 방법들이 제각각이어서 api라는 객체를 만들고, 메서드를 접근하면 쉽게 기능을 사용할 수 있도록 만들어 보았다. 여기에서 문서작업을 할 때 많이 편해졌다.

End

외부 개발자가 이 프로그램을 활용하거나 기능을 수정할 수 있도록 많은 고민을 했는데 이게 최선인지는 모르겠다.
무엇보다 API객체를 만들어둔 덕분에 다른사람이 컨트롤을 할 수 있도록 문서를 만드는데 많은 도움이 되었다.

이 프로그램이 혼자서 진행하는 오픈소스 프로젝트라서 일정이 없다보니 시간이 한도끝도없이 걸리게 되어서 기간이 몇달이나 걸렸다.
실 작업시간은 훨씬 짧지만 작업을 안하는 날도 많았고, 손대면 몇줄 적고 끝낸적도 있기도 하고, 프로젝트를 엎어버린때도 있다보니 기간이 길어질 수 밖에 없었다.

아무리 진행 시간이 길어지더라도 이렇게 완성하고나니 보람이 생겼다.

이걸 이용하여 다른사람들이 멋진 컨텐츠를 만들었으면 하는 바램도 생긴다.