Layout

Eli·2021년 2월 7일
3

iOS

목록 보기
3/11
post-custom-banner

오토 레이아웃(Auto Layout), 넌 누구냐!

AutoLayout

View에 주어진 제약조건에 따라 뷰를 다루는 것으로

앱 내부(컨텐츠의 양 등) 또는 외부 (가로세로 전환/화면 크기 등)에 따라 동적으로 반응 할 수 있는 UI 구현 가능.

아래와 같이 AutoLayout을 사용하면 화면 크기에 따르지만 비율에 대한 제약조건 등을 통해 대응 할 수 있다.

Frame Layout

사실 정통적인 방식은 화면을 Frame 방식으로 작업을 하는 방식이었다.

이 방식은 빠르고 가장 정확하게 대응 할 수 있지만 화면의 변화에 따라 매번 새롭게 계산해 프레임을 업데이트를 해주어야 하며, 각기 다른 스크린 사이즈의 디바이스들을 모두 대응해야만 한다.

왼쪽 아래는 프레임 방식을 실제 사이즈를 실측해 화면을 구성하는 예시.

위의 오른쪽은 뷰와 뷰 사이의 넓이 관계들을 정의합니다.
이 관계들을 정의 하는 것을 제약 사항으로 볼 수 있습니다.

오토 레이아웃은 이 제약조건을 통해 뷰의 크기와 위치를 정의하게 됩니다.

Interface Builder

많은 iOS 개발자들이 인터페이스 빌더로 작업을 하게된다.
굉장히 편하게 UI 작업을 할 수 있으며, 빠른 작업 속도를 보장한다.

아래의 사진은 iOS의 Interface Builder를 통해 AutoLayout을 정의하는 예시.

사각형의 뷰에 제약조건 사항들을 정리해주는 내용이다.

left/right는 superview와 16의 마진을 가지며 제약사항을 따른다..
top은 superview와 20의 마진을 가지며 제약사항을 따른다.
Height는 Aspect Ratio에 따라 현재 화면에 보이는 넓이:높이 비율을 가지는 제약사항을 따른다.
위와 같이 마우스로 몇번이면 쉽게 화면을 그릴 수 있다는 엄청난 장점이 있다.

그러나...
크나큰 단점이 몇가지 있는데
1. 위와 같은 ViewController가 한 Storyboard에 10개가 넘고 뷰가 복잡해지는 순간 xcode의 감당할 수 없는 버그/깨짐/버벅임을 경험 할 수 있다.
이후 유지보수에는 엄청난 시간과 비용이 들거란 이야기...

2.또한 code로는 절대 UI 요소를 파악할 수 없다.
안드로이드의 경우 xml을 보면 그나마 UI 구성요소를 판단할 수 있지만, xcode는 그와달리 code를 보고 절대 레이아웃을 판단할 수 없다.

Merge에 대한 Conflict와 코드리뷰도 거의 불가능한 Interface Builder의 엄청난 단점이다.

나의 경우에도 위와 같은 문제들을 겪은 후에 Interface Builder는 간단하며, 수정사항이 없을 것으로 보이는 화면에만 적용하게 되었다.

그럼 이제 코드로는 어떻게 AutoLayout을 적용하는지 알아보자.

In Programmatically

사실 코드로 작업을 하게되면 위의 문제점은 해결할 수 있지만 iOS에서 제공하는 Autolayout을 코드로 구현하게 되면 그렇게 깔끔하지 않은? 코드들이 나온다

한번 보자.

let myView = UIView()

override func viewDidLoad() {
		super.viewDidLoad()
		
		self.myView.backgroundColor = .lightGray
		self.view.addSubView(myView)

		//요놈을 이야기하자면 코드로 생성하는 UI요소는 Default가 true로 들어가게 된다.
		//iOS에서 자동적으로 화면비율에 맞추어 AutoResizing해주는 Constraints가 들어가는데
		//그럼 우리가 코드로 Constraints를 줄 수 없게 되어 추가해주는 코드.
		//더 알고싶다면 아래 링크를 보자
		myView.translatesAutoresizingMaskIntoConstraints = false

		myView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 20).isActive = true
		myView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 16).isActive = true
		myView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: 16).isActive = true
		myView.heightAnchor.constraint(equalTo: self.myView.widthAnchor, multiplier: 2.0/3.0).isActive = true
}

iOS ) translatesAutoresizingMaskIntoConstraints

위의 Interface Builder에서 그리는 것과 동일한 사각형을 구현하는데 들어가는 코드이다.
보다시피 쉽지 않다.
.isActive는 왜 꼭 넣어주어야 하며, 왜 이렇게 긴지
이를 개선한 라이브러리가 있다.

SnapKit

SnapKit/SnapKit

SnapKit을 이용해 위와 동일한 사각형을 그려보자

import SnapKit

myView.snp.makeConstraints { (make) in 
		make.top.equalToSuperview().inset(20)
		make.left.right.equalToSuperview().inset(16)
		make.equaltTo(self.myView.snp.height).multipledBy(2/3)
}

//심지어 아래도 자동으로 해준다.
//translatesAutoresizingMaskIntoConstraints = false

AutoLayout의 지옥을 한번 경험한 자들이 찾는 라이브러리이며, 나도 최근 1년전 부터의 프로젝트를 파고 작업을 한다면 SnapKit을 이용하여 개발하곤 한다.

Safe Area

아이폰 X (탈모 노치폰)이 태어나면서 함께 태어난 기능인데

스테이터스 바의 노치 영역과 하단의 스와이핑 영역들이 발생을 하면서 이 부분을 제외한 안전한 영역에 대한 가이드라인을 제공하기 시작한 것이다.

위와 같은 Safe area라는 가상의 영역을 만들고 Constraint를 Safe area에 설정할 수 있게 해주는 일종의 가이드라인이다.

SnapKit은 아래와 같이 Safe area를 따를 수 있다

box.snp.makeConstraints { (make) -> Void in
    make.left.equalTo(self.view)
    make.right.equalTo(self.view)
    make.top.equalTo(self.view.safeAreaLayoutGuide.snp.top)
    make.bottom.equalTo(self.view.safeAreaLayoutGuide.snp.bottom)

		//간단하게는 뭐 이렇게?
		make.edges.equalTo(self.view.safeAreaLayoutGuide)
}

위와 같이 간단하게 iOS의 AutoLayout을 다루어 봤다.

처음 접할 땐 Constraint라는 개념을 좀 이해하기 어려웠었는데 연차가 늘어나면서 점점 이해도가 높아지며 쉽게 능숙하게 다룰 수 있게 되었다.

뭐 애플에서 몇년 내엔 Swift UI로 옮길 것 같은데 그건 또 조만간 한번 스터디를 한다면 그곳에 별도로 정리를 하게 될 것 같다.

profile
애플을 좋아한다. 그래서 iOS 개발을 한다. @Kurly
post-custom-banner

1개의 댓글

comment-user-thumbnail
2021년 2월 7일

잘 읽었습니다~

답글 달기