이번에 팀스파르타에서 진행하는 한 달 인턴 1차에 합격하여 과제를 받았다. 회원가입, 로그인, 로그아웃 기능을 구현하는 어떻게 보면 간단한 과제였는데 서버 사용 없이 내부 저장소를 사용하여 구현을 진행하였다.
그런 의미로 이번 포스트에서는 서버 연동 없이 내부 저장소 만으로 이메일과 닉네임을 관리하기 위한 시스템을 구현하는 방법에 대해 알아보자. 이 포스팅은 UserDefaults와 Core Data를 활용하여 사용자 정보를 저장하고 업데이트하는 과정을 포함한다.
UserDefaults를 통한 현재 이메일 설정 및 삭제
현재 이메일 저장
사용자가 로그인할 때 현재 이메일을 UserDefaults에 저장하여 쉽게 접근할 수 있도록 했다. 아래 코드는 현재 이메일을 저장하는 방법이다.
// UserDefaults에 현재 이메일 저장
UserDefaults.standard.set(currentEmail, forKey: "currentEmail")
현재 이메일 삭제
사용자가 로그아웃하거나 계정 탈퇴 시 UserDefaults에서 현재 이메일을 삭제하는 방법이다.
// UserDefaults에서 현재 이메일 삭제
UserDefaults.standard.removeObject(forKey: "currentEmail")
Core Data를 통한 사용자 데이터 필터링 및 업데이트
currentEmail을 사용하여 Core Data에서 특정 사용자의 정보를 정확하게 가져오고 업데이트하는 방법을 구현한다.
사용자 데이터를 가져와 화면에 노출하는 함수
아래의 함수는 currentEmail을 사용하여 Core Data에서 사용자 데이터를 필터링하고, 해당 데이터를 출력한다.
private func displayUserInfo() {
guard let currentEmail = UserDefaults.standard.string(forKey: "currentEmail") else {
print("현재 이메일이 설정되지 않았음")
return
}
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest: NSFetchRequest<User> = User.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "email == %@", currentEmail)
do {
let users = try context.fetch(fetchRequest)
if let user = users.first {
print("Auth | user: Email: \\(user.email ?? "N/A"), Nickname: \\(user.nickname ?? "없음"), isLoggedIn: \\(user.isLoggedIn)")
mainView.updateWelcomeLabel(withText: user.nickname?.isEmpty == false ? "\\(user.nickname ?? user.email ?? "정보 없음") 님 환영합니다!" : "\\(user.email ?? "정보 없음")님 환영합니다!")
} else {
mainView.updateWelcomeLabel(withText: "사용자 정보가 없음")
}
} catch {
print("정보 오류: \\(error)")
mainView.updateWelcomeLabel(withText: "데이터를 가져오는 중 오류 발생")
}
}
닉네임 업데이트 함수
사용자가 닉네임을 변경할 수 있도록 하는 함수이다. currentEmail을 통해 해당 사용자의 데이터를 가져오고, 닉네임을 업데이트한다.
private func updateUsername(_ newUsername: String) {
guard let currentEmail = UserDefaults.standard.string(forKey: "currentEmail") else {
print("현재 이메일이 설정되지 않았음")
return
}
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest: NSFetchRequest<User> = User.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "email == %@", currentEmail)
do {
let users = try context.fetch(fetchRequest)
if let user = users.first {
user.nickname = newUsername // 사용자 이름 업데이트
try context.save() // 변경 사항 저장
AlertManager.shared.showSignInAlert(on: self, message: "닉네임 수정이 완료되었습니다.") {
self.displayUserInfo() // 화면 업데이트
}
}
} catch {
print("닉네임 업데이트 오류: \\(error)")
}
}
로그인 함수 구현
사용자가 이메일과 비밀번호로 로그인하거나 회원가입할 수 있도록 하는 함수이다.
@objc private func signInButtonTapped() {
guard let email = emailTextField.text, !email.isEmpty,
let password = passwordTextField.text, !password.isEmpty else {
AlertManager.shared.showAlert(on: self, title: "오류", message: "사용자 이름과 비밀번호를 입력해 주세요.")
return
}
let hashedPassword = password.sha256()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest: NSFetchRequest<User> = User.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "email == %@", email)
do {
let users = try context.fetch(fetchRequest)
if users.isEmpty {
// 사용자 이름이 존재하지 않으면 회원가입 진행
let newUser = User(context: context)
newUser.email = email
newUser.password = hashedPassword
newUser.isLoggedIn = true // 로그인 상태 업데이트
try context.save() // 변경 사항 저장
KeychainService.savePassword(service: "MyApp", account: email, password: hashedPassword)
// 회원가입 성공 후 알럿 표시 및 MainViewController로 이동
AlertManager.shared.showSignInAlert(on: self, message: "회원가입을 축하드립니다.") {
self.navigateToMainViewController()
}
} else {
// 사용자 이름이 존재하면 로그인 진행
let user = users.first!
if user.password == hashedPassword {
user.isLoggedIn = true
try context.save()
// 로그인 성공 후 알럿 표시 및 MainViewController로 이동
AlertManager.shared.showSignInAlert(on: self, message: "로그인이 완료되었습니다.") {
self.navigateToMainViewController()
}
} else {
// 비밀번호가 일치하지 않는 경우
AlertManager.shared.showAlert(on: self, title: "오류", message: "이메일 또는 비밀번호가 일치하지 않습니다.")
}
}
} catch {
print("오류: \\(error)")
}
}
결론
이렇게 구성된 시스템은 currentEmail을 통해 Core Data에서 사용자의 정보를 정확하게 가져오고, 닉네임 및 로그인 상태를 업데이트할 수 있다. UserDefaults를 활용하여 현재 로그인된 이메일을 손쉽게 관리하고, Core Data를 통해 사용자 정보를 안전하게 저장하고 업데이트할 수 있다.