Final (32)
프로젝트 막바지에는 기능 구현에 쫓겨 블로그 정리를 제대로 하지 못했다. 그래서 이 글은 당시 GitHub 커밋 내역과, 프로젝트 기간에 직접 적어 둔 업무 내역 목록을 AI(Claude Code)에게 보여주고 그걸 바탕으로 내용을 다시 정리했다. 코드는 실제 커밋에 있던 것을 가져왔다.
프로필 수정 페이지에 남아 있던 문제 두 가지를 고쳤다. 이 코드는 팀원(moremirim)이 7월 2일에 올려준 “공지사항의 FB연결, 프로필 수정관련 예외처리” 커밋에 같이 들어 있다.
프로필 수정 예외처리
남아 있던 문제는 이랬다.
- 닉네임은 그대로 두고 프로필 이미지만 바꾸려고 하면 저장이 안 됐다
- 지금 내가 쓰고 있는 닉네임으로 중복확인을 하면 “이미 닉네임이 존재합니다.” 가 떴다
2번은 당연한 결과였다. 전체 유저 목록에는 나 자신도 들어 있으니, 내 닉네임과 비교하면 항상 중복으로 나온다. 그리고 1번은 2번 때문에 생겼다. 저장하려면 중복확인을 통과해야 하는데, 닉네임을 그대로 두면 2번 때문에 통과를 할 수가 없었다.
내 닉네임은 중복에서 빼기
중복을 볼 때 닉네임이 같으면서 uid 가 나와 다른 사람만 중복으로 보도록 조건을 바꿨다. 빈 닉네임도 여기서 막는다.
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
@objc func validateName() {
let manageManager = ManageManager()
viewModel = ManageViewModel(manageManager: manageManager)
guard let nickName = userNameTextField.text, !nickName.isEmpty else {
isValidate = false
validateLabel.textColor = .red
validateLabel.text = "닉네임을 입력해주세요."
return
}
guard let uid = Auth.auth().currentUser?.uid else { return }
self.viewModel.getUsers { [weak self] in
if let userArray = self?.viewModel.userArray, !userArray.contains(where: { $0.nickName == nickName && $0.uid != uid }) {
self?.isValidate = true
self?.validateLabel.textColor = .blue
self?.validateLabel.text = "입력하신 닉네임은 사용 가능합니다."
} else {
self?.isValidate = false
self?.validateLabel.textColor = .red
self?.validateLabel.text = "이미 닉네임이 존재합니다."
}
}
}
이제 닉네임을 바꾸지 않아도 중복확인을 통과할 수 있어서, 이미지만 바꿔서 저장하는 것도 된다.
다만 구현 당시 컨디션이 좋지 않아서, 이미지를 바꿀 때도 중복확인 버튼을 한 번 누르고 저장하는 방식으로 마무리했다. 안내 문구에도 그걸 적어 두었다.
1
label.text = "닉네임 변경 전 중복확인 검사를 해주세요.\n프로필 이미지 변경시에도 중복확인 검사를 해주세요."
이미지를 받은 다음에 저장하기
26일 글에서 남겨 둔 문제도 여기서 같이 고쳤다. 이미지를 바꾸지 않았으면 기존 이미지를 Kingfisher 로 받아서 같이 저장하는데, 받기가 끝나기 전에 updateProfile 이 먼저 불리고 있었다.
그래서 저장 흐름을 함수 세 개로 나누고, 이미지를 받은 뒤에 다음 단계로 넘어가게 했다.
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
@objc func saveChanges() {
guard let newUserName = userNameTextField.text, !newUserName.isEmpty else {
showMessage(title: "닉네임을 입력해주세요", message: "닉네임을 입력해주세요.")
return
}
guard isValidate else {
showMessage(title: "중복확인을 해주세요", message: "닉네임 중복확인을 먼저 해주세요.")
return
}
ProgressHUD.animate()
guard let uid = Auth.auth().currentUser?.uid else { return }
if profileImage == nil {
KingfisherManager.shared.retrieveImage(with: URL(string: gotProfileImage!)!) { [weak self] result in
switch result {
case .success(let image):
self?.validateAndUpdateProfile(uid: uid, userName: newUserName, selectedImage: image.image)
case .failure(let error):
ProgressHUD.dismiss()
self?.showMessage(title: "에러 발생", message: "\(error)가 발생했습니다")
}
}
} else {
validateAndUpdateProfile(uid: uid, userName: newUserName, selectedImage: profileImage!)
}
}
saveChanges: 빈 닉네임과 중복확인 여부를 먼저 거른다. 새 이미지가 없으면 기존 이미지를 받고, 받기가 끝난 completion 안에서 다음 단계를 부른다validateAndUpdateProfile: 저장 직전에 한 번 더 중복을 확인한다. 중복확인을 누른 뒤 저장하기 전에 다른 사람이 같은 닉네임을 가져갔을 수도 있기 때문이다updateProfile: 실제로 저장하고 완료 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
28
29
30
31
32
33
34
func validateAndUpdateProfile(uid: String, userName: String, selectedImage: UIImage) {
let manageManager = ManageManager()
viewModel = ManageViewModel(manageManager: manageManager)
viewModel.getUsers { [weak self] in
guard let self = self else { return }
if let userArray = self.viewModel?.userArray {
if userArray.contains(where: { $0.nickName == userName && $0.uid != uid }) {
ProgressHUD.dismiss()
self.showMessage(title: "닉네임 중복", message: "이미 존재하는 닉네임입니다.")
} else {
self.updateProfile(uid: uid, userName: userName, selectedImage: selectedImage)
}
} else {
ProgressHUD.dismiss()
self.showMessage(title: "에러 발생", message: "사용자 목록을 불러오는 데 실패했습니다.")
}
}
}
func updateProfile(uid: String, userName: String, selectedImage: UIImage) {
userManager.updateProfile(uid: uid, nickName: userName, profile: selectedImage) { [weak self] result in
switch result {
case .success(()):
ProgressHUD.dismiss()
self?.showMessage(title: "수정 완료", message: "프로필 정보가 수정 되었습니다.") {
self?.navigationController?.popViewController(animated: true)
}
case .failure(let error):
ProgressHUD.dismiss()
self?.showMessage(title: "에러 발생", message: "(error.localizedDescription)가 발생했습니다.")
}
}
}
마지막 에러 메시지는 \(error.localizedDescription) 에서 \ 가 빠져서, 에러 내용 대신 글자가 그대로 나온다. 지금 다시 보니 보이는 실수다.
같이 고친 것
닉네임을 고치면 isValidate 를 되돌리면서, 안내 문구도 처음 상태로 돌려놓았다. 확인을 통과한 뒤에 닉네임을 고쳤는데 “사용 가능합니다” 가 그대로 남아 있으면 헷갈리기 때문이다.
1
2
3
4
5
6
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
isValidate = false
validateLabel.textColor = ThemeColor.mainBlack
validateLabel.text = "닉네임 변경 전 중복확인 검사를 해주세요."
return true
}
저장 버튼은 직접 만든 UIButton 대신 NavigationBar 의 기본 버튼(UIBarButtonItem)으로 바꿨다.
1
2
3
let saveBarButton = UIBarButtonItem(title: "저장", style: .done, target: self, action: #selector(saveChanges))
saveBarButton.tintColor = ThemeColor.mainOrange
navigationItem.rightBarButtonItem = saveBarButton
기존 프로필 이미지를 띄울 때 gotProfileImage! 로 강제 언래핑하던 것도 if let 으로 바꿨다.