brunch

You can make anything
by writing

C.S.Lewis

by 유나 Mar 30. 2017

4.2 인스타그램 만들기
- 레이아웃(Layout) 1

지난 시간에 정리했던 변수반복문을 이용해서 이제 인스타그램의 레이아웃을 만들어보자. 뭐든지 이미지로 처리하면 더 쉽고 빠르지만 그간 배운 내용들의 개념 이해를 더욱 공고히 하고 트레이닝하는 것을 중점으로 해보겠다.


우선 완성작을 다시 한번 감상하며 어떻게 만들지 구상해보자.



1. 어떻게 만들지 구상하면서 사전 준비하기

완성작 gif를 보면 UI는 크게 타임라인(메인), 상세, 촬영 이렇게 3가지로 나뉜다. 그리고 타임라인에 필요한 요소로는 Header, Tab bar, 프로필 이미지, 유저 아이디, 포스팅 이미지, 코멘트, 각종 버튼들이 있다.


1-1. top과 bottom 디자인 psd (또는 sketch)

Component로 간단하게 만들었던 medium처럼 이번에도 top(Header)과 bottom(Tab bar) UI는 psd로 선작업 후 import 해서 사용한다. 물론 다 framer에서 만들어도 상관없지만 디자인 작업물을 import 하면 길어지는 코드를 줄일 수 있다. 효율을 위해서 불필요한 작업은 최소화하는 게 좋다. 중간에 포스팅 영역은 for문을 활용해야 하므로 그에 필요한 것들은 따로 준비한다. 

import할 psd의 구성

top 영역은 타임라인에서는 카메라와 메시지 버튼이, 유저명을 클릭해서 넘어갔을 때는 back버튼과 더보기 메뉴가 나타나므로 버튼 4개를 준비한다. (준비한 버튼 전체를 보여주기 위해 다른 위치에 두었을 뿐, 실제 버튼은 동일한 위치에 있다.)

나중에 flow component에서 header를 지정해줘야 하므로 Head라는 이름의 그룹으로 status bar와 로고, 버튼 등을 감싸주었다.

하단 메뉴바는 인스타그램 UI 형태를 갖추기 위한 요소이기 때문에 따로 버튼을 분리하지 않고 통 이미지로 준비했다. (Tab bar처럼 클릭 또는 변화 요소가 없는 경우는 그냥 통 이미지로 처리하여 코드와 레이어를 줄이는데 어차피 import 할 거니까 따로 만들어도 상관은 없다.)


1-2. 포스팅 영역과 상세에 필요한 이미지 준비



포스팅 헤더 (yellow영역)

디테일하게 하려면 프로필 이미지, id, 위치정보, 버튼까지 다 레이아웃을 분할해야 하지만 해당 프로토타입에서는 레이어를 다 분할해야 할 만큼의 액션이 있는 것이 아니므로 통 이미지로 준비해도 된다. 타임라인에서 몇 개의 포스팅을 나열할 것인지 생각해서 그 수에 맞춰 프로필 이미지를 준비하면 된다.


이런식의 이미지를 원하는 수만큼 준비한다.



포스팅 이미지 (magenta 영역)

프레이머에서는 unsplash에서 제공하는 이미지를 랜덤으로 불러와 사용할 수 있는 코드가 있다. 이를 활용할 예정이기에 여기서는 따로 이미지를 준비하지 않았지만 원하는 이미지를 불러오길 원한다면 이미지를 준비해두어야 한다. (이때 타임라인에 보일 이미지와 프로필 상세에서 보일 이미지의 수를 고려하여 준비해야 한다.)


포스팅버튼과 코멘트 이미지 예시

포스팅 코멘트 & 버튼 (cyan영역)

포스팅 코멘트는 텍스트 처리할 수도 있지만 그럴 경우 for문을 활용하기 때문에 data 처리를 해야 하는 부분이 있어서 이미지로 처리했고 버튼에 별다른 모션이나 이벤트가 들어가지 않으므로 코멘트와 버튼을 통 이미지로 준비했다. 프로필 이미지 수만큼 준비한다. (만약 좋아요 버튼 등에 이벤트를 넣을 생각이라면 이 역시도 다 별도로 준비해야 한다.)





상세 프로필 영역 이미지 예시




상세 프로필 영역 (Green 영역)

상세 프로필도 포스팅 코멘트와 마찬가지의 문제가 있기 때문에 이번에는 이미지로 대체한다. Header 아래부터 그리드 이미지 영역 위까지를 잘라서 준비했다. 개수는 마찬가지로 프로필 이미지와 수를 맞춰준다.







예제 파일은 여기서.

https://www.dropbox.com/s/ybo7iekewd38jw0/instagram_files.zip?dl=0






2. PSD(또는 sketch) import

Component로 간단한 프로토타입 만들기에서 했던 것과 마찬가지로 psd를 연 상태에서 framer의 import 버튼을 눌러 디자인 파일을 프레이머에 가져온 후 아래의 코드를 삽입한다. 아래의 코드에 대한 설명 역시 해당 편에 있으므로 여기서는 생략한다.


psd = Framer.Importer.load("imported/ui_medium@1x")


new BackgroundLayer #흰 배경을 삽입해주었다. 이건 생략해도 상관없다.


Utils.globalLayers(psd) #여기서 바로 위 코드의 제일 앞에 사용된 이름을 그대로 넣으면 된다.

Framer.Extras.Hints.disable()




3. 타임라인(메인) 만들기



지난번 component를 활용하여 간단한 프로토타입 만들기에서는 상세를 먼저 만들고 메인을 만들었지만 이번에는 작업이 복잡하니 헷갈리지 않도록 메인 만들고 상세를 만들어볼 예정이다. 우선 왼쪽의 타임라인(메인)을 먼저 만들어보자.


3-1. 불필요한 레이어 숨기기

UI 디자인 파일을 import 하면 모든 레이어가 활성화된 상태가 된다. 상단의 back버튼이나 더보기 버튼은 상세로 이동했을 때 표시되어야 하기 때문에 근데 첫 화면에서는 visible을 이용해 숨긴다.


btnBack.visible = false

btnHMore.visible = false



visible과 opacity : 왜 'opacity = 0'을 사용하지 않고 'visible = false'를 사용해야 할까?

visible과 opacity는 모두 시각적인 속성이다. visible의 사전적 의미는 '보이는', '가시적인'으로 true, false의 boolyean값을 가진다. 반면 opacity는 '불투명함'이라는 뜻을 가졌으며 숫자 값을 이용해 '불투명함'의 정도를 제어한다.

'visible = true'와 'opacity = 1' / 'visible = false'와 'opacity = 0'은 시각적으로 같은 효과를 준 것처럼 보이지만 사실은 전혀 다르다. 특히 'visible = false'와 'opacity = 0'에서 큰 차이점을 느낄 수 있는데, opacity는 투명도를 조절하여 실제로 존재하고 있지만 없는 것처럼 보이게 하는 반면 visible은 객체를 보여주거나 숨기는 속성을 가지고 있다.

visible과 opaciry

위 그림처럼 두 개의 객체가 같은 위치에 있을 때 visible을 사용하면 layerB에 대한 이벤트가 있을 때 클릭이나 어떠한 액션이 가능하다. 하지만 opacity는 단순히 투명하게 만들어 없는 것처럼 만드는 것일 뿐, 실제로는 그대로 존재하고 있기 때문에 layerC에 어떤 이벤트를 주어도 layer A가 덮고 있어서 액션을 취할 수 없는 오류가 생길 수 있다.


왼쪽 : visible = false, 오른쪽 : opacity = 0

프레이머에서도 preview에서는 동일한 형태로 보이지만 레이어 부분을 보면 visible = false를 사용했을 때 해당 레이어가 비활성화 처리되고 opacity = 0은 그대로 활성화되어 있는 것을 확인할 수 있다.



3-2. for문을 활용하여 포스팅 리스트 만들기

이번에도 역시 snippets를 활용해서 변형을 해보자. Snippets > Components > Scroll List를 불러온다.

이미 설정되어 있는 변수에 대해 알아보자.


#Variables

rows = 16 #for문을 활용해 만들 레이어의 개수

gutter = 10 #레이어와 레이어 사이의 여백

rowHeight = 200 # 레이어의 높잇값


코드만 봐서 이 변수가 어디서 활용되는지 파악하기 어렵다면 변수의 값을 변경해서 바뀌는 부분을 살펴보자. 그러면 조금 더 쉽게 변수에 대해 파악할 수 있고 이러한 트레이닝이 반복되면 단순한 구조에서는 코드만으로 파악할 수 있다.


3-2-1. 구조 파악하기

우리가 반복적으로 만들어야 할 타임라인의 디자인 구조를 다시 보면 위의 그림과 같이 profile + photo + button & comment가 한 덩어리가 되어 계속 반복된다. 그러면 당연히 for문에도 profile, photo, button & comment 3개의 레이어를 생성해줘야 한다는 얘기.


다시 코드로 돌아가서... 기존의 cell 레이어의 속성을 변형하여 profile로 사용하고 2개의 레이어를 추가하여 각 각 photo와 button & comment를 만들어보자.



3-2-2. 새로 변수 선언하기

우선 변수 중에서 row를 제외하고 나머지는 필요 없으니 지운다. 그리고 필요한 변수들을 새롭게 선언할 텐데 무엇을 변수로 만들지 리스트업을 먼저 해보자. (기존에 선언된 변수를 활용해도 되지만 헷갈리지 않도록 이름을 바꾸다 보면 새로 선언하는 것과 다를 것이 없다.) 

위의 구조를 실눈을 뜨고 집중해서 보면 몇 가지 필요한 사이즈들이 보일지 모르겠는데... 레이어들의 가로 세로 값을 변수로 지정해주어야 한다. 사실 여기서는 이것만 변수로 선언해주면 된다.


가로사이즈는 당연히 디바이스의 가로 값만큼 사용할 거니까 profile, photo, button&comment 모두 동일한 값을 지닌다. (아이폰을 기준으로 만들었기 때문에 750이라고 절댓값을 사용해도 되고 Screen.size라는 상대 값을 지정해줘도 된다.) 그리고 각 3개의 레이어의 높이 값을 따로 변수로 선언해준다.


#Variables

rows = 8 #8개의 포스팅을 만들 예정이므로 16에서 8로 변경했다.

profHeight = 102 #profile 레이어의 높잇값

photoSize = Screen.width #사진 사이즈

commentHeight = 382 #button&comment 레이어의 높잇값


3개의 레이어에 대한 가로 세로 값을 변수로 선언해주면 총 6개의 변수여야 되는데 3개만 새로 선언해서 이상하다 싶을지도 모르겠다. 하지만 가로 값을 어차피 Screen.width 아니면 750으로 사진의 사이즈와 동일하게 사용된다. 그래서 photoSize 변수를 같이 사용할 거라 생략했다. 또한 이번 예제에서 사진은 정방형(정사각형)의 형태를 활용할 예정이므로 photoHeight가 아닌 photoSize로 명명했다.



3-2-3. for문으로 profile 레이어 만들기


# Loop to create row layers

for index in [0...rows]

        profList = new Layer #기존 cell 레이어의 이름을 알아보기 쉽도록 profList라고 바꿨다.

                width:  photoSize #위에 말한 것과 같이 photoSize를 같이 사용한다.

                height: profHeight #미리 선언해둔 profile 레이어 높이값에 대한 변수의 이름을 쓴다.

                y: index * (profHeight + photoSize + commentHeight) #y값을 통해서 반복되는 레이어가 겹치지 않도록 설정해주어야 한다. 처음 생기는 profile 레이어가 다음에 생길 때는 profile + photo + button &comment 레이어 다음에 위치해야 한다. 3-2-1. 구조 파악하기 그림을 참조하면 이해가 더 쉽다. 그래서 profile레이어 높이 + photo 레이어 높이 + button&comment 레이어 높이를 합친 값에 index 즉, 순차적으로 0, 1, 2.. 을 곱하면 자동으로 그림과 같은 위치에 위치하게 된다.

                parent: scroll.content #스크롤이 되어야 하므로 scroll component의 content에 귀속시킨다.

                image: "images/profList_"+index+".png"


image 부분에 대한 부가설명을 더한다.

예제 zip 파일을 다운로드하여 열어보면 images 폴더에 여러 이미지가 들어있다. 자세히 보면 이름이 모두 규칙적으로 정해진 것을 볼 수 있다.

모든 이미지 파일은 동일한 이름+0~7까지의 숫자로 되어있다.

이는 for문을 활용하여 반복되는 레이어를 생성할 때 각 각 다른 이미지가 들어가도록 하기 위함이다. for문은 대괄호[] 안의 숫자 범주를 벗어날 때까지 1씩 증가한다. 그러므로 불러올 이미지의 경로를 "images/profList_"+index+".png"라고 해주면 for문이 반복되면서 index에 0~7까지의 숫자로 치환된다. 즉, index가 0일 때는 "images/profList_"+index+".png"는 "images/profList_0.png"가 되고 for문에 의해 반복되면 이전 값에 +1이 되니까 index는 1되고 다음 레이어에는 "images/profList_1.png"의 이미지가 들어가게 된다. index는 변수이고 나머지는 문자열이기 때문에 index 앞뒤로는 따옴표로 감싸는 것이다.


4.1 인스타그램 만들기 - 반복문(for문)에서 설명했던 위 그림과 같은 원리다.



3-2-4. for문으로 photo와 comment 레이어 만들기

위에 만들어놓은 profList 아래에 같은 방법으로 photo와 comment레이어를 추가한다.


# Loop to create row layers

for index in [0...rows]

        profList = new Layer

                width:  photoSize

                height: profHeight

                y: index * (profHeight + photoSize + commentHeight)

                parent: scroll.content

                image: "images/profList_"+index+".png"


        postPhoto = new Layer

                size: photoSize

                image: Utils.randomImage() #Utils.randomImage()를 사용하면 위에서 말한 것처럼 unsplash의 이미지가 랜덤으로 적용된다. 이걸 사용해도 되고 원하는 이미지가 있다면 profile, comment 이미지를 준비한 것과 마찬가지로 규칙적인 이름으로 8장을 준비해서 불러오면 된다.

                y: index * (profHeight + photoSize + commentHeight) + profHeight #photo는 profile 아래에 위치해야 한다. 그래서 profile레이어의 높이값에 해당하는 변수를 한번 더 더해줬다.

                parent: scroll.content


        comment = new Layer

                width: photoSize

                height: commentHeight

                y: index * (profHeight + photoSize + commentHeight) + profHeight + photoSize # postPhoto의 y값을 설정해준 것과 마찬가지 원리다. photo레이어 아래에 위치해야 하므로 그 위에 있는 profile과 photo레이어의 높이값에 해당하는 변수를 추가로 더했다.

                image: "images/comment_"+index+".png"

                parent: scroll.content


여기까지 하면 아래와 같은 형태로 완성이 된다. 스크롤을 해서 아랫부분까지 어긋남이 없는지 확인을 한 번씩 해보자.


3-3. flow component를 활용하여 완성하기

그런데 제일 먼저 import 했던 상단과 하단 UI가 보이지 않는다. 이 부분은 flow component를 활용하여 해결하면 된다. 이제는 익숙한 Sinppets > Components > Flow를 불러온다.


# Create layers

        layerA = new Layer

                size: Screen.size 

                backgroundColor: "#00AAFF"

        

        layerB = new Layer

                size: Screen.size 

                backgroundColor: "#FFCC33"


# Set up FlowComponent

flow = new FlowComponent 

flow.showNext(layerA)


# Switch on click

layerA.onClick ->

        flow.showNext(layerB)


layerB.onClick ->

        flow.showPrevious()


불필요한 layerA와 B를 지우고 위 과정에서 만들었던 레이어들을 대치하고 밑에 깔려있는 Head와 TabBar를 각 각 flow의 head와 footer로 지정하여 보이도록 한다. header와 footer로 지정해주기만 하면 for문으로 만들어둔 body에 해당하는 콘텐츠가 알아서 header의 아래로 위치 조정이 되기 때문에 위치를 따로 조정하지 않아도 된다.


# Set up FlowComponent

flow = new FlowComponent 

flow.showNext(scroll) #layerA 대신 미리 만들어놓은 타임라인 레이어 전체를 감싸고 있는 scroll component의 이름으로 교체한다.

        

flow.header = Head 

flow.footer = TabBar


# 아래의 코드는 후에 상세까지 레이어를 만든 후 필요한 부분이기 때문에 삭제하지 않고 'cmd+/'를 눌러 주석처리해서 기능이 작동하지 않도록 한다.

# Switch on click

# layerA.onClick ->

#         flow.showNext(layerB)

# layerB.onClick ->

#         flow.showPrevious()



4. 타임라인(메인) 완성


이제 여기에 상세화면을 만들고 타임라인의 프로필 이미지를 각 각 클릭하면 해당 상세화면이 나오도록 만들면 완성이다. 그러기 위해서는 배열(Array)에 대해 알아야 한다. 이 부분은 다음 편에서 계속 이어서 하도록 하겠다.



instagram: https://www.instagram.com/fish0422/

facebook : https://www.facebook.com/fish0422

blog : http://blog.naver.com/fish0422






매거진의 이전글 4.1 인스타그램 만들기 - 반복문(for문)
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari