Skip to content

Refaotor/profile#65

Merged
Roy-wonji merged 8 commits intomainfrom
refaotor/profile
Dec 16, 2025
Merged

Refaotor/profile#65
Roy-wonji merged 8 commits intomainfrom
refaotor/profile

Conversation

@Roy-wonji
Copy link
Contributor

🔗 관련 이슈

  • 관련 이슈: splash 화면에서 main 화면 진입시 로그인이 풀리는 이슈 해결

✨ 작업 내용

  • 🎨 ImageCacheService 구현으로 프로필 이미지 캐싱 최적화
  • 🔧 Keychain 접근 레벨 개선으로 로그인 상태 안정성 향상
  • 📱 앱 버전 1.0.4 빌드 24로 업데이트 및 프로필에 버전 표시 추가
  • 🧹 로그아웃 로직 정리 및 불필요한 코드 제거

📝 참고 사항

  • ImageCacheService는 NSCache 기반으로 50MB 제한, actor로 thread-safe 구현
  • Keychain 접근 레벨을 kSecAttrAccessibleAfterFirstUnlockkSecAttrAccessibleWhenUnlockedThisDeviceOnly로 변경하여 토큰 안정성 개선

Motivation 🥳 (코드를 추가/변경하게 된 이유)

  • 빌드 시마다 로그인이 풀리는 문제 해결 필요
  • 프로필 이미지 로딩 성능 최적화 요구
  • 앱 버전 정보 사용자에게 제공 필요

Key Changes 🔥 (주요 구현/변경 사항)

1. ImageCacheService 구현

public actor ImageCacheService {
    private let cache = NSCache<NSString, UIImage>()
    private var inFlightTasks: [URL: Task<UIImage?, Never>] = [:]

    // 50MB 캐시 제한, 중복 다운로드 방지
    public func image(for url: URL) async -> UIImage?
}

2. Keychain 보안 개선

// 변경 전
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock

// 변경 후  
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly

3. EditProfileImage AsyncImage → ImageCacheService 적용

- 기존 AsyncImage 대신 커스텀 캐싱 로직 구현
- 로딩 상태 관리 개선 및 성능 최적화

4. 버전 정보 표시

- 프로필 화면에 v 1.0.4 형태로 앱 버전 표시 추가
- Environment.swift에서 중앙집중식 버전 관리

To Reviewers 🙏 (리뷰어에게 전달하고 싶은 말)

- ImageCacheService의 actor 사용법과 메모리 관리 부분 리뷰 부탁드립니다
- Keychain 접근 레벨 변경이 실제 기기에서 올바르게 동작하는지 확인 필요합니다
- 프로필 스켈레톤 뷰에서 일부 요소를 주석 처리한 이유 확인 부탁드립니다

Reference 🔗

- https://developer.apple.com/documentation/security/keychain_services
- https://developer.apple.com/documentation/foundation/nscache

Close Issues 🔒 (닫을 Issue)
- 로그인 상태 유지 관련 이슈 해결

Roy-wonji and others added 4 commits December 16, 2025 16:01
- 로그아웃 성공 시 AppStorage의 sessionId, socialType, userId 정리
- 기존에는 Keychain만 정리되고 AppStorage는 남아있던 문제 해결
- 회원탈퇴와 동일한 수준의 세션 정리 적용
- 로그인 풀리는 현상 방지

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
Copy link
Contributor

@minneee minneee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다~

Comment on lines +228 to +259
extension TransparentImageCaching {
/// 투명한 이미지 캐싱을 수동으로 활성화합니다.
/// 일반적으로는 ImageCacheService 사용 시 자동으로 활성화됩니다.
public static func activate() {
registrationLock.lock()
defer { registrationLock.unlock() }

guard !isRegistered else { return }
URLProtocol.registerClass(TransparentImageCaching.self)
isRegistered = true
}

/// 투명한 이미지 캐싱을 비활성화합니다.
public static func deactivate() {
registrationLock.lock()
defer { registrationLock.unlock() }

guard isRegistered else { return }
URLProtocol.unregisterClass(TransparentImageCaching.self)
isRegistered = false
}

/// 캐시를 완전히 지웁니다.
public static func clearCache() async {
await cacheManager.clearCache()
}

/// 현재 처리 중인 요청 수를 반환합니다. (디버깅용)
public static func processingRequestCount() async -> Int {
await cacheManager.processingRequestsCount()
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actor와 nslock은 같이 쓰는건 권장사항이 아닌데 같이 써야하는 이유가 있었나요 ?

@Roy-wonji Roy-wonji merged commit bc8deb2 into main Dec 16, 2025
@Roy-wonji Roy-wonji deleted the refaotor/profile branch December 16, 2025 23:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants