[iOS] clipShape와 contentShape의 차이점 (Feat. SignInWithAppleButton)

유인호·2024년 9월 8일
1

iOS

목록 보기
63/64

0. 서론

스유에서 뷰를 자를때 clipShape를 자주 사용했었다. 사실 그거밖에 몰랐었다. 그러다가 문제가 생겼는데, SignInWithAppleButton, 이녀석 때문에 골머리를 앓았다.

애플 로그인은 상당히 까다롭다. Sign in with Apple | Apple Developer Decumentation을 확인해보면 뭔가 주저리주저리 말이 많다는걸 알 수 있다.

우리 회사 디자인은 동그란 애플 로그인 버튼을 사용하기에, 헛된 디자인 공수를 줄이기 위해 해당 사이트에서 가능한 디자인인지 확인하고 개발을 진행했었다.

근데 뭐 여기까진 다들 아는 사실이겠지만, SwiftUI에서 애플 로그인을 쉽게 만들 수 있도록 애플이 버튼을 하나 만들어놓았는데, 바로 SignInWithAppleButton이다.

1. SignInWithAppleButton이 뭔데

import SwiftUI
import AuthenticationServices

struct ContentView: View {
	var body: some View {
		SignInWithAppleButton { request in
			request.requestedScopes = [.fullName, .email]
		} onCompletion: { result in
			// Apple Login 처리 (필자는 파이어베이스로 진행했었음)
		}
	}
}

이렇게 하면 바로 애플로그인을 구현할 수 있도록 초 간단하게 만들어놓은 버튼이다. 실제로 Class에 상속받아서 사용하는게 원래 정석인데, 너무 귀찮기도 하고 내가 만든 Apple Login Service Class는 이미 다른 클래스를 상속받고 있기에 Apple Login을 위해 내가 만들어놓은 구조를 전부 해집어야하는 문제가 발생했었다.

게다가 FirebaseAuthCombine을 사용하고 다른 타 로그인도 있어서 ASAuthorization을 받아오는 스트림을 모든 로그인에 동일한 Funtion을 사용해 획일화 되게 관리하고 있었는데, 클래스에 상속받아서 사용하는 애플로그인은 도저히 이 구조가 불가능했다.

즉, 나는 SignInWithAppleButton이 버튼을 커스텀 해내지 못한다면 모든 코드를 싹 갈아 엎어야 하는 문제가 생긴거다.

이미 다 다른 로그인에 스트림을 핸들링하는 Funtion도 다 만들었는데... 나는 자신이 없었다.

2. 커스텀 못할 자신이 없었다.

뭐 SignInWithAppleButton도 View니까 대충 frame 넣으면 되겠지 ㅋㅋ

라고 생각하면 오산임

아까 보여줬던 이 코드

import SwiftUI
import AuthenticationServices

struct ContentView: View {
	var body: some View {
		SignInWithAppleButton { request in
			request.requestedScopes = [.fullName, .email]
		} onCompletion: { result in
			// Apple Login 처리 (필자는 파이어베이스로 진행했었음)
		}
	}
}

이 코드의 결과물은 다음과 같다.

오~ Shape처럼 작동하는구나? 그럼 대충 .frame으로 조져주면 커스텀 되겠네 ㅋㅋ

라고 생각했다면 하수

????

그렇다. SignInWithAppleButton은 .frame으로 조지던 말던 애플에서 최소한 애플 로고와 저 문구가 나오게, 만들어놓은거다.

2. clipShape를 이용해서 강제로 모양을 바꿔보자

라고 생각했으면 중수

결과물부터 보면

잘 되는걸 확인해 볼 수 있다.

호들갑이란 호들갑을 다 떨더니 뭐야? 라고 할 순 있겠지만 단순히 여기서 끝났다면 글을 쓰지 않았을것, background를 먹여보자.

clipShape을 해서 Circle로 변경해주었음에도 불구하고 배경이 아까 그대로 남아있는거같다.

실제로 빨간색부분을 누르면 터치도 된다.

이렇게 사용해도 문제는 없겠지만 Hstack으로 다음과 같은 코드를 작성했을때

이런 문제가 발생한다. 그럼 내가 구글 로그인 버튼을 눌렀는데 애플 로그인 창이 나올수도 있는것이다.

3. clipShape의 원리부터 알아보자.

Apple Login은 잠시 재껴두고 그냥 버튼을 하나 만들어보자.

이 버튼의 눈에 보이는 크기와 실제로 누를 수 있는 실제의 크기는 어떻게 될까?

예상하듯 이렇다.

물론 위치를 label안에 넣어도 동일하다.

아까 AppleLogin하고 상당히 비슷하다는걸 눈치챌 수 있을것이다. AppleLogin버튼의 내부가 대충 이런식으로 만들어놨기에, 우리가 아무리 clipShape로 조져도 실제 크기를 조절할 수 없는것이다.

clipShape의 특징은 사용자 눈에 보이는것만 잘라낸다. 즉, 실제 크기와 상이할 수 있다는것. 문제가 생길수도 있을것이다.

그렇다면 무엇을 써야하는가?

4. contentShape

을 생각했다면 고수

대게 clipShape랑 같이 사용된다. 보기에 달라진게없어보일수도 있지만, 빨간색 부분을 아무리 눌러도 터치 이벤트가 발생하지 않는다.

contentShape(_:eoFill:) | Apple Developer Document를 보면 다음과 같이 나와있다는걸 알 수 있다.

Defines the content shape for hit testing.

testing이라는 말에 속지 말고, 그냥 터치 범위를 정의해주는 모디파이어라는걸 알 수 있다.

여기까지 있던걸 잘 짬뽕시키면 다음과 같은결과를 얻을 수 있다.

의도되지 않은 범위를 제한하고, 의도가 가득차게 사용자에게 구글 로그인인 척 애플로그인을 시킬 수 있을 것이다. 실제로 작동한다.


애플 입장에선

일수도

profile
🍎Apple Developer Academy @ POSTECH 2nd, 🌱SeSAC iOS 4th

0개의 댓글