Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- button configuration
- swift custom ui
- uikit toast
- rxdatasources
- SWIFT
- swift bottomsheet
- reactorkit
- custombottomsheet
- traits
- swift 백준
- Tuist
- claen architecture
- swift navigationcontroller
- coordinator
- BFS
- identifiable
- 타임라인 포맷팅
- swift concurrency
- domain data
- RxSwift
- paragraph style
- custom navigation bar
- task cancel
- UIKit
- DP
- swift 점선
- custom ui
- task cancellation
- 버튼 피드백
- swift dashed line
Archives
- Today
- Total
김경록의 앱 개발 여정
[Swift] 코디네이터 패턴과 JWT 기반 오토로그인 본문
STEP 1
토큰 관리 객체에 대한 아이디어
- 키체인을 따로 별도 관리해주는 객체를 정의
- 해당 객체는 CRUD를 포함하고 싱글톤 객체로서 외부에서 편하게 접근 가능하도록 설정
- isLoggedIn:Bool 을 계산속성으로 정의, 해당 속성은 getToken을 통해 값을 업데이트
- public var isLoggedIn: Bool { get { // 실질적 통신에 사용되는 엑세스 토큰만을 확인 return getToken(type: .access) != nil } }
오토로그인에 대한 아이디어
- 키체인 혹은 유저 디폴트에 JWT 토큰을 받아 저장
- 로그인이 필요한 작업의 경우 해당 토큰을 꺼내서 헤더에 포함(Alamofire RequestInterceptor 사용)
- 서버로부터 토큰이 만료되었다는 안내를 받으면 기존 저장중이던 토큰을 삭제하여 업데이트
func retry(_ request: Request, for session: Session, dueTo error: any Error, completion: @escaping (RetryResult) -> Void) { ... let tokenManager = TokenKeyChainManager.shared tokenManager.deleteToken(type: .access) tokenManager.deleteToken(type: .refresh) ... }
STEP 2
사용한 코디네이터 프로토콜
public protocol Coordinator: AnyObject {
var parentCoordinator: Coordinator? { get set }
var childCoordinators: [Coordinator] { get set }
var navigationController: UINavigationController { get set }
func start()
func didFinish()
}
앱의 전반에서 로그인을 요구하는 경우
- SceneDelegate에서 (혹은 AppDelegate) 에서 토큰에 대한 유효성을 체크, 코디네이터를 통해 분기처리를 해주면 됨
일부 회원제인 경우
이번 포스팅의 주된 목적이자 겪었던 메인 트러블 슈팅 과정
로그인이 필요한 경우를 나누는 경우는 크게 두가지가 있다고 판단.
- 화면 전체가 회원이 아니면 접근이 불가능한 경우(ex: 마이페이지 접근)
- 화면엔 접근이 가능하지만, 일부 기능만을 이용할 수 없는 경우(ex: 댓글 작성)
모든 경우에 일일히
if 엑세스토큰 유효하지않음 {
coordinator?.pushToLoginView
} else {
coordinator?.pushToMyInfoView
}
따위의 반복 작업으로 처리 가능한 부분임
하지만, 위와 같은 반복 작업시에 많은 단점 존재
- 단순히 반복 작업만으로도 충분히 피곤하고, 유지보수성을 낮춤
- 개선된 사용자 경험을 위해 Alert등으로 안내해줘야하는데,
위에서 언급한 두가지 경우에서 Alert을 호출하는 위치가 일관적이지 못함(coordinator일수도, VC일수도, VM일수도.. ) - Alert코드 또한 반복되어야만 함
- 부모 자식 코디네이터의 관리가 어려워짐
개선 아이디어
- 로그인이 필요한 '동작' 이 포함된 모든 뷰가 가지게 될 (채택하게 될) 인증 전용 코디네이터를 선언
- protocol AuthenticationCoordinator: Coordinator { func checkLoginBeforeAction(onLoggedIn: @escaping () -> Void) func pushToLoginView() func presentLoginRequiredAlert() }
- 프로토콜의 기본구현을 통해 반복 작업을 최소화
func checkLoginBeforeAction(onLoggedIn: @escaping () -> Void) {
let isLoggedIn = TokenKeyChainManager.shared.isLoggedIn
if !isLoggedIn {
presentLoginRequiredAlert()
} else {
onLoggedIn()
}
}
로그인 요청 알럿과 로그인뷰로 이동하는 메서드는 생략(알럿에서 이동하기 누르면 로그인 뷰 push)
클로저를 통해 로그인이 된 경우에만 사용처에서 원하는 동작을 설정하도록 작성
사용처 예시 코드
// TestViewController.swift
private func pushToOnlyUserView() {
coordinator?.checkLoginBeforeAction(onLoggedIn: { [weak self] in
self?.coordinator?.pushToOnlyUserView()
})
}
// TestCoordinator.swift
func pushToOnlyUserView() {
//코디네이터 부모 자식 설정 코드 독립적으로 설정 가능
}
기대할 수 있는 이점
- 로그인 유도 Alert과 이동 코드 중복 감소
- 기존 매번 변하던 로그인 여부 확인 위치를 일괄적으로 유저 액션에 적용하여 작성가능
- 부모 자식 코디네이터의 설정을 직관적이게 설정 가능
'Trouble Shooting' 카테고리의 다른 글
[Swift] 여러 상황에 대응하는 레이아웃 만들기(with SnapKit, update Layout) (0) | 2025.03.08 |
---|---|
[Swift] Launch Screen에 Asset.xcassets 이미지가 적용되지 않는다면 (0) | 2025.02.01 |
[Swift UIKit] 비회원은 못보는 TableView Section, 어떻게 할까? (0) | 2025.01.24 |
[Swift UIKit] 공백이 포함된 커스텀 뷰 구현기 (0) | 2025.01.10 |
[Swift UIKit]present의 주체 (modal을 표시하는건 누구의 역할일까?) (0) | 2025.01.08 |