포스트

Final (27)

게스트 모드 Alert 수정

1
2
3
4
5
6
showMessage(title: "로그인이 필요한 기능입니다.", message: "사용 할 수 없습니다.") {
    let scene = UIApplication.shared.connectedScenes.first
    if let sd: SceneDelegate = (scene?.delegate as? SceneDelegate) {
        sd.switchToGreetingViewController()
    }
}

이렇게 메세지를 띄워 로그인 페이지로 가게끔 수정했다.

ChatVC, MapViewController, DetailedReviewViewController, StoreViewController에 적용

cancel 추가

무조건 로그인 페이지로 이동하게 강요하는것 같아 취소버튼도 가능하게 바꿈

showMessage에서 showMessageWithCancel로 변경

1
showMessageWithCancel(title: "로그인이 필요한 기능입니다.", message: "확인을 클릭하시면 로그인 페이지로 이동합니다.") 

커뮤니티 페이지 닉네임 중복처리

주요 변경 사항

  • Combine을 이용한 닉네임 중복 확인 로직 추가
  • ManageViewModelManageManager를 통해 사용자 목록을 조회
  • checkNickname() 내에서 닉네임이 비어 있을 경우, 중복 검사를 거쳐 updateUserName() 호출
  • viewWillAppear 시점에서 checkNickname() 실행되도록 이동
  • cancellablesviewModel 프로퍼티 추가

코드 변경 요약

닉네임 중복 검사 로직 추가

1
2
3
4
5
6
7
8
9
10
11
12
private func validateNickname(nickName: String, completion: @escaping ((Bool) -> Void)) {
    let manageManager = ManageManager()
    self.viewModel = ManageViewModel(manageManager: manageManager)

    self.viewModel?.getUsers {
        if self.viewModel?.userArray.contains(where: { $0.nickName == nickName }) == false {
            completion(true)
        } else {
            completion(false)
        }
    }
}

showNameAlert 수정 (중복 처리 포함)

1
2
3
4
5
6
7
8
9
10
self?.validateNickname(nickName: newName) { result in
    switch result {
    case true:
        self?.updateUserName(uid: uid, newName: newName)
    case false:
        self?.showMessage(title: "중복 확인", message: "현재 닉네임은 이미 존재합니다.") {
            self?.showNameAlert(uid: uid)
        }
    }
}

viewWillAppear 내 checkNickname 호출 위치 변경

  • 기존에는 viewDidLoad에서만 호출
  • viewWillAppear 내로 이동하여 뷰가 다시 나타날 때마다 검사하도록 개선

변경 이유

  • 사용자 최초 접속 시 닉네임이 비어 있거나 중복될 가능성을 차단하기 위함
  • 채팅 채널 접속 전 사용자 정보의 신뢰성을 보장
  • Combine과 MVVM 구조를 활용해 뷰컨트롤러의 책임을 분산시킴

ManageViewModel 함수 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func getUsers() {
        manageManager.fetchUsers { [weak self] error, dataSnapshot in
            self?.userArray.removeAll()
            if let error = error {
                self?.managePublisher.send(completion: .failure(error))
            }
            guard let dictionary = dataSnapshot?.value as? [String: [String: Any]] else { return }
            
            for (uid, userDict) in dictionary {
                let email = userDict[db_email] as? String ?? ""
                let nickName = userDict[db_nickName] as? String ?? ""
                let profileImageUrl = userDict[db_profileImageUrl] as? String ?? ""
                let isBlockInt = userDict[db_isBlock] as? Int ?? 0
                let isBlock = isBlockInt != 0
                
                let model = UserModel(uid: uid, email: email, isBlock: isBlock, nickName: nickName, profileImageUrl: profileImageUrl)
                self?.userArray.append(model)
            }
            self?.managePublisher.send(())
        }
    }
  • 정리
    • fetchUsers() 메서드를 통해 Firebase에서 사용자 데이터를 가져옴
    • UserModel로 파싱하여 배열에 저장
    • 완료 후 managePublisher를 통해 성공 여부 알림 (Void, .failure(error) 형태)
  • 목적
    • 닉네임 중복 검사 등 사용자 정보를 참조해야 하는 ViewModel 로직에서 사용
    • 주로 ChannelVC에서 닉네임 입력 시 중복 확인 용도로 활용

예외처리

주요 목적

닉네임이 비어있거나 중복된 상태로 채팅 채널에 입장하는 문제를 해결하기 위해,
닉네임 유효성 검사 후에만 채널 입장을 허용하도록 로직을 개선함.
특히 Alert 반복 처리와 isValidate 플래그를 도입해 예외 상황도 제어함.


viewWillAppear에서 닉네임 유효성 검사 실행

화면이 나타날 때마다 닉네임 유효성 검사를 수행하여 이후 채널 입장 조건을 준비함.

1
2
3
4
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    checkNickname()
}

checkNickname - 닉네임 존재 여부에 따라 Alert 분기 처리

Firebase Realtime Database에서 현재 유저의 닉네임을 가져와 검사하며,
비어있을 경우 Alert을 통해 사용자에게 닉네임 입력을 유도함.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private func checkNickname() {
    if let user = currentUser {
        userManager.fetchUserData(uid: user.uid) { [self] error, snapshot in
            guard let dictionary = snapshot?.value as? [String: Any] else { return }
            currentName = (dictionary[db_nickName] as? String) ?? "Unknown"
            if currentName == ""  {
                showNameAlert(uid: user.uid)
                isValidate = false
            } else {
                isValidate = true
            }
        }
    }
}

showNameAlert - 닉네임 입력 및 중복 확인 Alert 반복 구조

사용자가 입력한 닉네임이 이미 존재하는 경우, Alert을 다시 띄워 유효한 닉네임을 받을 때까지 반복함.

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
private func showNameAlert(uid: String) {
    let alertController = UIAlertController(...)
    alertController.addTextField { textField in
        textField.placeholder = "Name"
    }

    let confirmAction = UIAlertAction(title: "OK", style: .default) { [weak self] _ in
        if let textField = alertController.textFields?.first,
           let newName = textField.text, !newName.isEmpty {
            self?.validateNickname(nickName: newName) { result in
                if result {
                    self?.updateUserName(uid: uid, newName: newName)
                    self?.isValidate = true
                } else {
                    self?.isValidate = false
                    self?.showMessage(title: "중복 확인", message: "현재 닉네임은 이미 존재합니다.") {
                        self?.showNameAlert(uid: uid)
                    }
                }
            }
        }
    }

    alertController.addAction(confirmAction)
    ...
    present(alertController, animated: true)
}

didSelectRowAt에서 isValidate 검사 추가

유효한 닉네임이 설정되지 않은 경우, 채널에 입장하지 않고 Alert을 다시 표시함.
채널 입장은 오직 isValidate == true일 때만 허용.

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
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let channel = channels[indexPath.row]
    var viewController: ChatVC?

    isLocation = (currentAddress == channel.name)

    if let user = currentUser {
        if isValidate {
            viewController = ChatVC(user: user, channel: channel)
            viewController?.isLocation = isLocation
        } else {
            guard let uid = Auth.auth().currentUser?.uid else { return }
            showNameAlert(uid: uid)
            return
        }
    } else if let customUser = customUser {
        viewController = ChatVC(customUser: customUser, channel: channel)
    }

    if let viewController = viewController {
        navigationController?.pushViewController(viewController, animated: true)
    }

    tableView.deselectRow(at: indexPath, animated: true)
}

결론

  • 채널 입장 전에 닉네임 유효성을 반드시 검증하게 만들어 UX 개선
  • 중복 닉네임 Alert 반복 처리로 사용자 실수 대응
  • isValidate 플래그 도입으로 ViewController 흐름 제어 명확화
  • 전체적으로 커뮤니티 기능의 안정성과 일관성을 높이는 리팩토링이라 할 수 있음
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.