Skip to content

알라딘 API와 Vanilla UIKit으로 구현한 책 검색 프로젝트

Notifications You must be signed in to change notification settings

wontaeyoung/Vanilladin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

프로젝트

스크린샷

image

한 줄 소개

알라딘 책 정보 조회 앱


서비스 기능

  • 텍스트 기반 검색 기능
  • 책 상세정보 조회 기능
  • 최근검색어 기능

프로젝트 환경

개발 인원
iOS 1인

개발 기간
2023.08 ~ 2023.09 (6주)


개발 환경

iOS 최소 버전
14.0+

Xcode
15.0.1


작동 화면

검색 화면 List <-> Grid 전환 스크롤 페이지네이션

상세화면 에러 사용자 피드백 최근 검색어

구현 고려사항

  • 바닐라 프로그래밍으로 ****라이브러리를 사용하지 않고 개발
  • 커스텀 DI Container를 구현해서 의존성 관리참조 인스턴스 재사용
  • 데이터 변경 사항을 MVPDelegate 패턴으로 UI에 반영
  • 책 리스트 조회에 오프셋 기반 페이지네이션 적용

아키텍처

image


기술 활용

이미지 캐싱 적용

  • NSCache를 이용하여 이미지 캐싱을 구현하고, 이미지 요청 시점에 캐시 적용 분기 추가

  • Scene 라이프사이클에 메모리 경고 옵저버를 연결해서 리소스 사용 및 회수

이미지 캐시 매니저 소스코드
final class ImageCacheManager {
    // MARK: - Property
    static let shared: ImageCacheManager = .init()
    private let cache: NSCache<NSString, UIImage>
    private let memoryWarningNotification: NSNotification.Name
    
    // MARK: - Initializer
    private init() {
        self.cache = .init()
        self.memoryWarningNotification = UIApplication.didReceiveMemoryWarningNotification
        
        addMemoryObserver()
    }
    
    // MARK: - Method
    func getObject(for key: String) -> UIImage? {
        let cacheKey: NSString = .init(string: key)
        let cachedImage: UIImage? = cache.object(forKey: cacheKey)
        
        return cachedImage
    }
    
    func setObject(
        _ object: UIImage,
        for key: String
    ) {
        let cacheKey: NSString = .init(string: key)
        cache.setObject(object, forKey: cacheKey)
    }
    
    func removeObject(for key: String) {
        let cacheKey: NSString = .init(string: key)
        cache.removeObject(forKey: cacheKey)
    }
    
    @objc func removeAllObjects() {
        cache.removeAllObjects()
    }
    
    func addMemoryObserver() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(removeAllObjects),
            name: memoryWarningNotification,
            object: nil)
    }
    
    func removeMemoryObserver() {
        NotificationCenter.default.removeObserver(
            self,
            name: memoryWarningNotification,
            object: nil)
    }
}

다중 이미지 요청 병렬처리 적용

  • 책 리스트 조회 과정에서 10개의 이미지 순차 요청 문제 발생

  • TaskGroup을 사용한 병렬 처리를 적용하여 응답 시간 약 3.6배(테스트 기준) 개선

  • 병렬 처리 결과를 요청 인덱스 기준으로 재정렬하여, 검색의 정렬 기준인 Accuracy 보장




의존성 컨테이너 고유 인스턴스 식별

  • DependencyContainer 는 레지스트리를 사용하여 의존성 관리 인스턴스 요청 시, 이미 등록된 의존성을 체크해서 재사용

  • 인스턴스 등록 여부를 식별하기 위해, ObjectIdentifier 를 레지스트리 Key로 채택

  • ObjectIdentifierType 자체가 정의된 메타데이터를 기반으로 생성되기 때문에, 인스턴스의 레지스트리 등록 여부 판단 가능


트러블슈팅

HitTest 영역 미인식 문제


  • 삭제 버튼의 탭 인터랙션 미반응 문제 발생
  • 예상 가능한 원인인 Interaction Enabled, View Hierarchy를 검토했으나 이슈 확인 불가

원인 확인

삭제 버튼의 View 계층

  • contentView
    • paddingView
      • deleteButton

override func setConstraint() {
	...
        
	paddingView.setPaddingAutoLayout(to: contentView, padding: 20)
        
	...
}
  • paddingView은 contentView를 기준으로 20의 inner padding 적용



image
  • 위 사진의 파란색 선이 paddingView 영역으로, 상하 20 padding이 적용되어 선에 가까운 높이로 드로잉

  • iOS의 터치 이벤트 처리 시스템에 따라서 paddingView의 hitTest 에서 터치 이벤트 영역이 존재하지 않아, 하위 뷰인 삭제버튼으로 터치 가능한 뷰로 인식하지 않음

    • 시각적으로 뷰가 보이는 것과, 터치 이벤트 영역은 별개로 작동
  • paddingView의 상하 padding 조절로 이슈 해결



image



About

알라딘 API와 Vanilla UIKit으로 구현한 책 검색 프로젝트

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages