[iOS SwiftUI] onAppear 활용 API 연동

hyoooooooooopark·2024년 1월 3일
0

iOS

목록 보기
2/3

상황

새로 API를 연동하며 내가 기존에 해봤던 방식과는 다른 방식으로 흐름을 제어해보고 싶었다.

아이디어

아이디어는
1. API 요청을 보내는 뷰에서 isOnRquestAPI 라는 내가 API를 보냈는지 아닌지를 관리하는 변수를 하나 두고
2. API 요청을 보낼때 isOnRequestAPI를 변경해준다.
3. isOnRquestAPI로 API 결과 처리 부분과 기존 View 부분으로 나눈다.
4. API를 대기, 성공, 실패로 나누어 처리한다.

ViewModel에는 isLoading을 두어 API를 받아 오는 동안 true로 관리하였고,
isLoading이 true인동안 대기라고 정의했다.

아이디어를 코드로 표현하자면

if isOnRequestAPI {
	// API 결과 처리
	if someViewModel.isLoading {
    	// 대기상태
		ProgressView()
	} else if let result = someViewModel.response?.someElement {
    	// 성공
    } else {
    	// 실패
    }
    
} else {
	// API 요청을 보내기 전의 원래 View
	Button(action: {
		someViewModel.postSomething() // ViewModel에서 API호출	
		isOnRequestAPI = ture
	}, label: {
	    Text("API 요청 보내기")
	})
}

이렇게인데

주석으로 표시된 성공과 실패 부분에서
성공시 변수를 활용해 다른 View로 넘어가는 로직을 넣으려고 했다.

로그인 View로 예를 들면, 아래와 같이 로그인 여부를 나타내는 변수를 변경하고자 했다.

// 성공
isLogin = ture
isOnRequestAPI = false

문제점

하지만 아래처럼 View 내부이기 때문에 로직이 아닌 View를 넣어야 하는 문제가 발생한다.

해결 과정

생각이 난 해결책으로는
성공시 보여줄 View를 만들고, onAppear을 활용해서 성공 View가 Appearing 될 때 로직을 추가하는 방법이었다.

// 성공
SomeAPISuccessView()
	.onAppear() {
    	isLogin = ture
		isOnRequestAPI = false
    }

이렇게 만들어서 실행해보면 잘 되는 것처럼 보이지만 다른 문제가 발생한다.

1. 성공시 뷰와 실패시 뷰 둘 다 onAppear을 사용했을때 if로 제어했던 로직이 예기치 않게 동작하는 현상

if someViewModel.isLoading {
    // 대기상태
	ProgressView()
} else if let result = someViewModel.response?.someElement {
    // 성공
    A View
    	.onAppear() {
			// A Logic        
        }
} else {
    // 실패
    B View
    	.onAppear() {
			// B Logic
        }
}

이런 코드를 실행하고 성공적으로 API 데이터를 받아오면
당연히 A Logic이 실행된다고 예상했지만
실제로는 B Logic 후 A Logic이 실행되었다.

예상한 원인은
기존의 ViewModel에서는
API 호출 -> 응답 -> ViewModel의 isLoading 변경 -> response 변경 의 순서로 작성했는데,
isLoading이 변경될때 View에서 상태 변경을 감지하고 바로 새로 화면을 구성해주었을 것이다.
그런데 isLoading 변경된 순간에는 response에 값이 저장되있지 않았기 때문에
그 순간에는 실패인 B Logic이 실행된 것이라고 생각했다.

API 호출 -> 응답-> ViewModel의 -> response 변경 -> isLoading 변경 로 변경하였고, 원하는 동작을 얻을 수 있었다.

2. onAppear 되자마자 다른 View를 보여주는 로직이 실행되어서 성공시 View를 확인 할 수 없다는 점

말 그대로 성공하면 다른 View로 바로 화면이 바뀌어서 애써 작성한 성공시 View가 보이지 않는 문제가 있었다.

해결방안으로는 일정 시간이 지난 뒤 로직을 실행하는 방법이 있었다. (다른 앱들에서 경험한 것을 활용)

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
	isLogin = ture
	isOnRequestAPI = false
}

이런 방법을 사용해서 해결을 시도했다.

아쉬운점

하지만 여전히 마음에 걸리는 것들이 있었다.

  1. "이런 성공시 View를 보는 시간을 강제하면 UX를 해치는게 아닌가?" 라는 생각
    성공시 View에 바로 로직을 실행할 수 있게 하는 버튼을 추가하면 개선 가능

  2. 결국 한 번 더 클릭을 하던가 시간이 지나야 원하는 View로 간다는 점
    해당 시간만큼 미리 다음 뷰에 필요한 데이터를 요청해놓으면 오히려 UX에 좋은 영향을 줄 수 있다고 생각

결론

이 외에도 onReceive 활용 등 다양한 생각과 해결 방법, 발생하는 문제점들에 대해 고민을 했지만
UX 측면과 코드의 가독성 부분에서 생각했을때 기존에 내가 사용한 방법보다 훨씬 개선됐다고 생각한다.


!!주의!! 본 게시글은 학습을 기록하고, 경험을 공유하는 목적으로 작성되었습니다.
내가 만난 문제와 선택지들, 내가 선택한 해결법을 포스팅하였기 때문에
틀린 부분과 정답이 아닌 것들이 포함되어 있을 수 있습니다.

profile
슈뢰딩거의 개발 : 정답일 수도 아닐 수도 있습니다.

0개의 댓글