Skip to content

Latest commit

 

History

History
618 lines (508 loc) · 31.3 KB

README.md

File metadata and controls

618 lines (508 loc) · 31.3 KB

🎥 박스오피스🍿

📖 목차

  1. 소개
  2. 팀원
  3. 타임라인 및 핵심경험
  4. 파일트리
  5. 실행 화면
  6. 트러블 슈팅
  7. 주요 학습 내용
  8. 팀 회고
  9. 참고 링크

1. 📢 소개

일일 박스오피스가 궁금하신가요? 혹은 영화 개별 상세 조회를 원하시나요? 저희에게 물어보세요!

✔️ 캘린더에서 원하시는 날짜를 선택해주세요 📅
✔️ 해당 날짜의 1️⃣~🔟위 박스오피스를 제공해드립니다!
✔️ 새로고침을 원하시면 리스트를 아래로 잡아 끌어주세요!
✔️ 영화 별 상세정보도 확인 가능하니 놓치지 마시고 확인해 보세요😆

핵심 개념 오픈 API / URLSession / JSON Decoding / CodingKeys / UNIT Test /
CollectionView / ModernCollectionView / UIActivityIndicatorView /
UIRefreshControl / NSMutableAttributedString /
API KEY 발급 및 노출 방지 / Image Fetch / NSCache /
Modal / UICalendarView / DateManager / Image Loading View


2. 👤 팀원

Serena 🐷 BMO 🤖

3. ⏱️ 타임라인 및 핵심경험

프로젝트 기간 : 2023-07-24 ~ 2023-08-18

타임라인

날짜 내용
2023.07.24 ◽️ 일별 박스 오피스 샘플 json dataset 추가
◽️ 일별 박스오피스 Model 추가
2023.07.25 ◽️ 일별 박스오피스 관련 테스트 추가 및 테스트 작성
◽️ 박스오피스 Model 추가
◽️ 전체 Model CodingKey 적용
2023.07.27 ◽️ 네트워크 관련 로직을 처리하는 NetworkManager 타입 추가
◽️ 영화진흥위원회로부터 일별 박스오피스 조회하는 로직 작성
2023.07.28 ◽️ 영화 상세정보 조회를 위한 DTO 생성 및 CodingKey 적용
◽️ 영화 상세정보 조회 메서드 추가
◽️ 매직리터럴 관리를 위한 NameSpace 추가
2023.07.31 ◽️ Result 타입을 활용하여 Model 바인딩 및 에러처리
2023.08.02 ◽️ 스토리보드 제거 및 코드베이스 UI 구현
◽️ 일벽 박스오피스 Cell 생성
◽️ 일별 박스오피스 CollectionView로 구현
2023.08.03 ◽️ CollectionViewDataSoruceDiffableDataSource로 변경
◽️ CollectionViewrefresh control 추가
2023.08.04 ◽️ 접근성 향상을 위해 adjustsFontSize 적용
◽️ 에러 발생시 Alert 출력
2023.08.06 ◽️ BoxOfficeService를 사용하는 곳은 모두 의존성 주입을 받아 사용하도록 변경
◽️ 공통 Alert 중복 메서드 분리
◽️ 영화 상세정보 ViewController 생성 및 구현
◽️ 다음 이미지 검색 관련 DTO 추가
2023.08.07 ◽️ NetworkManager 로직 변경 및 싱글톤 클래스로 변경
◽️ Dynamic Type 적용
2023.08.08 ◽️ Kakao Developer에 팀 앱 생성
◽️ KakaoAPIKeyplist에 등록
2023.08.09 ◽️ 이미지 로드 애니메이션 생성
◽️ 이미지 캐시 저장 로직 추가
2023.08.10 ◽️ 박스오피스 날짜 선택 ViewController 추가
◽️ BoxOfficeService의 날짜 로직을 DateManager 싱글톤 클래스로 분리

핵심경험

  • 영화진흥위위원회 오픈 API를 참고하여 '오늘의 일일 박스오피스 데이터'와 '영화 개별 상세 데이터' Model을 구현
  • Model을 활용하여 URLSession으로 JSON 파일을 Fetch
  • JSON 파일 Decode에 대한 Unit Test 작성
  • iOS 14.0 미만 버전을 위한 CollecionView / iOS 14.0 이상 버전을 위한 ModernCollecionView 구성
  • Kakao API Key를 활용하여 영화 포스터 fetch하기
  • fetch한 이미지 및 데이터를 StackViewScrollView에 넣기

4. 🌲 파일트리

파일트리

BoxOffice 
├── App
│   ├── AppDelegate.swift
│   └── SceneDelegate.swift
├── Base.lproj
│   └── LaunchScreen.storyboard
├── Error
│   ├── AlertManager.swift
│   ├── JSONDecoderError.swift
│   └── NetworkManagerError.swift
├── Extension
│   ├── Bundle+.swift
│   ├── JSONDecoder+.swift
│   ├── String+.swift
│   └── UIFont+.swift
├── Info.plist
├── KakaoAPIKey.plist
├── Model
│   ├── DTO
│   │   ├── BoxOffice
│   │   │   ├── BoxOffice.swift
│   │   │   ├── BoxOfficeResult.swift
│   │   │   └── DailyBoxOffice.swift
│   │   ├── DaumSearch
│   │   │   ├── DaumSearchMainText.swift
│   │   │   ├── DaumSearchMeta.swift
│   │   │   └── ImageDocument.swift
│   │   └── Movie
│   │       ├── Audit.swift
│   │       ├── Company.swift
│   │       ├── Genre.swift
│   │       ├── Movie.swift
│   │       ├── MovieInfo.swift
│   │       ├── MovieInfoResult.swift
│   │       ├── Nation.swift
│   │       ├── People.swift
│   │       └── ShowType.swift
│   └── Section.swift
├── NameSpace
│   ├── CustomDateFormatStyle.swift
│   ├── KakaoNameSpace.swift
│   ├── KobisNameSpace.swift
│   ├── MimeType.swift
│   └── MovieDetailNameSpace.swift
├── Protocol
│   ├── CalendarViewControllerDelegate.swift
│   └── DaumSearchDocumentable.swift
├── Service
│   └── BoxOfficeService.swift
├── Util
│   ├── DateManager.swift
│   ├── ImageCacheManager.swift
│   └── NetworkManager.swift
├── View
│   ├── BoxOfficeCell.swift
│   ├── Custom
│   │   ├── DetailLabel.swift
│   │   ├── LabelsStack.swift
│   │   └── TitleLabel.swift
│   └── MovieDetailView.swift
└── ViewController
    ├── BoxOfficeViewController.swift
    ├── CalendarViewController.swift
    └── MovieDetailViewController.swift

5. 📲 실행 화면

박스오피스 로딩 화면 박스오피스 리스트 새로고침
이미지 로딩 화면 캘린더로 날짜 선택하기

6. 🛎️ 트러블 슈팅

CodingKeys

🔥 문제점

  • 초반 코드 작성 시 decode 과정에서 알 수 없는 에러가 계속 발생하였습니다. decode 과정에서 어느 부분에서 잘못되었는지를 찾기 위해 코드를 처음부터 다시 작성하다보니, CodingKey를 잘못 작성하여 JSON decode가 되지 않았다는 것을 발견했습니다.

🧯 해결방법

  • CodingKey를 사용할 때 프로퍼티명을 swift에서 사용할 이름으로 지정하고, enum case의 값으로 기존의 JSON 키 값의 이름을 지정해야합니다. 하지만 이를 반대로 작성하였더니, 알 수 없는 에러가 발생하여 이를 디버깅하는데 많은 시간을 소요하였습니다.

    CodingKey 잘못 작성 예시

    struct BoxOfficeResult: Decodable {
        let boxofficeType: String
        ...
    
        enum CodingKeys: String, CodingKey {
            case boxofficeType = "boxOfficeType"
            ...
        }
    }

    CodingKey 올바른 예시

    struct BoxOfficeResult: Decodable {
        let boxOfficeType: String
        ...
    
        private enum CodingKeys: String, CodingKey {
            case boxOfficeType = "boxofficeType"
            ...
        }
    }

UnitTest에서 do-catch문 사용 시 XCTFail 활용

🔥 문제점

  • Unit Test에서 JSON 파일 Decode에 대한 테스트를 진행 시 do-catch문을 활용하였습니다. 이때 테스트가 실패했을 때 XCTTest 메서드를 retrun만 하게 되면 테스트가 Success처리 되는것을 확인했습니다.
  • 테스트가 꼭 Then과정까지 도달하지 않더라도 GivenWhen과정 또한 테스트에 적절하지 않은 값이 들어오거나, 값이 처리되는 과정에 대한 처리가 필요하다고 생각했습니다.

🧯 해결방법

  • XCTFail 메서드를 찾아 테스트 진행 중 적절하지 않은 부분에 삽입해 주었습니다. Apple Developer 공식문서에 따르면 XCTFail의 설명은 다음과 같습니다.

    This function generates a failure immediately and unconditionally. (이 함수는 즉시 무조건 실패를 생성합니다.)

    func test_box_office_sample_json_파일을_디코딩_할_수_있다() {
        // Given
        guard let result: BoxOffice = JSONDecoder.decode(fileName: "box_office_sample") else {
            XCTFail("파일명 'box_office_sample'로 JSON 디코딩 할 수 없습니다.")
            return
        }
    
        // When
    
        // Then
        XCTAssertNotNil(result)
    }

Result 타입을 활용하여 URLSession dataTask에서 발생한 에러 처리

🔥 문제점

  • ViewController에서 요청한 dataTask에서 작업 도중 에러가 발생하는 경우, 발생한 에러를 ViewController에서 전달받아 처리하고 싶었습니다. 하지만 dataTask 클로저 내부에서 밖으로 값을 리턴시킬수 없는것처럼, 에러도 밖으로 던질 수 없었습니다.

    Invalid conversion from throwing function of type '@sendable (Data?, URLResponse?, (any Error)?) throws -> Void' to non-throwing function type '@sendable (Data?, URLResponse?, (any Error)?) -> Void'

🧯 해결방법

  • Return 값이 없는 경우나 Error throws를 할 수 없는 상황에서 Result 타입을 활용하여 Error Handling을 할 수 있습니다. 특히 URLSessiondataTask처럼 Void 타입으로 기본 구현되어 있는 메소드안에서 발생한 Error를 외부로 전달하고 싶을 때 유용하게 사용 가능합니다.

    코드 예시

    1. Error 타입을 생성
    enum NetworkManagerError: Error {
        case notExistedUrl
        ...
    }
    1. Result Type을 파라미터로 받는 함수 정의 (Success: Generic, Failure: NetworkManagerError)
    struct NetworkManager {
    // completion Handler 파라미터로 Result Type을 파라미터로 받는 Void 클로저
    static func loadData<T: Decodable>(_ components: URLComponents?,_ dataType: T.Type,_ completion: @escaping (Result<T, NetworkManagerError>) -> Void) {
        ...
                // Void 타입으로 기본 구현되어 있는 메소드(dataTask)안에서 Error 발생
                do {
                    ...
                    // 성공한 경우
                    completion(.success(result))
                } catch let error as JSONDecoderError {
                    ...
                    // 실패한 경우
                    completion(.failure(NetworkManagerError.failureJsonDecode))
                } catch {
                    ...
                    completion(.failure(NetworkManagerError.unknown))
                }
            ...
    }
    
    1. Generic 타입으로 전달받은 Success 타입을 구체적 타입으로 다시 전달
    func loadDailyBoxOfficeData(_ completion: @escaping (Result<BoxOffice, NetworkManagerError>) -> Void) {
        ...
        NetworkManager.loadData(components, BoxOffice.self) { result in
            switch result {
            case .success(let data):
                completion(.success(data))
            case .failure(let error):
                completion(.failure(error)) 
            }
        }
    }
    1. ViewController에서 Success/ Failure 처리
    private func fetchBoxOffice(_ result: Result<BoxOffice, NetworkManagerError>) {
        switch result {
        case .success(let boxOffice):
            ...
        case .failure(let error):
            ...
        }
    }

NSMutableAttributedString를 활용하여 특정 문자 변경하기

🔥 문제점

  • 랭킹 변동 정보를 표시하기 위해 화살표 특수문자를 활용하였습니다. 이때 변동 정보에 맞추어 Label Text의 해당 특수문자의 색상만 바꾸고자 하였습니다. 예를 들어 랭킹이 높아진 경우 빨간색의 위로 향하는 화살표를, 랭킹이 낮아진 경우 파란색의 아래로 향하는 화살표를 표시하고자 했습니다.

🧯 해결방법

  • UILableString Text뿐만이 아니라 attributedText를 사용할 수 있습니다. String Text를 사용하게되면 글자에 foregroundColor를 줄 수 없기 때문에, attributeText를 사용하고자 하였습니다.
  • attributedText에는 NSMutableAttributedString 타입의 값을 대입할 수 있습니다. 하여 StringNSMutableAttributedString 타입으로 변환하여 사용했습니다.
  • addAttribute(_:value:range:) 메서드를 이용하여 해당하는 문자를 지정한 색상으로 변경했습니다.

API Key를 git에 노출시키지 않는 방법

🔥 문제점

  • 이미지 검색 API를 사용하기 위해 Kakao Developer에서 앱을 생성하여 REST API Key를 발급받았습니다. 발급받은 REST API Key를 이용해 이미지 검색 API를 이용하는데 성공했고, 해당 내용을 커밋하려고 했습니다.
  • 변경 내역을 확인하던 중 API Key가 포함된 코드가 커밋된다면 이후 별도 관리를 위해 해당 코드를 제거하더라도 깃 커밋 이력에 API Key가 그대로 노출 되는 상황이 발생하게 됩니다.

🧯 해결방법

  • 저희는 이러한 상황이 발생하지 않도록 하기 위해 KakaoAPIKey.plist 파일을 만들고 gitignore에 추가했습니다. 해당 파일은 깃을 통해 받을 수 없게 되었기 때문에 팀원에게 직접 파일 전달을 하는 방식으로 작업하게 됩니다.
  • plist내부의 데이터는 Bundle을 확장하여 읽기전용 프로퍼티를 통해 가져오도록 했습니다.
    extension Bundle {
        var kakaoApiKey: String {
            guard let file = self.path(forResource: "KakaoAPIKey", ofType: "plist") else { return "" }
            guard let resource = NSDictionary (contentsOfFile: file) else { return "" }
            guard let key = resource["Authorization"] as? String else {
                fatalError("KakaoAPIKey.plist에 Authorization를 설정해주세요.")
            }
    
            return key
        }
    }
    
    enum KakaoNameSpace {
        ...
        static let authorization = "Authorization"
        static let apiKey = Bundle.main.kakaoApiKey // Bundle에 등록된 Key를 NameSpace로 관리
    }
    
    // 이후 URLRequest에 header에 필요한 정보를 주입
    let headers = [
        KakaoNameSpace.authorization : KakaoNameSpace.apiKey
    ]

    Bundle은 실행 가능한 코드와 해당 코드의 자원을 포함하는 디렉토리입니다. Bundle은 여러가지가 있는데, 그 중 main은 앱이 실행되는 코드가 있는 Bundle 디렉토리에 접근할 수 있는 bundle입니다.


UIImageView의 Height를 동적으로 입력

🔥 문제점

  • 이미지 검색 API를 통해 어떤 사이즈의 이미지를 가지 와도 이미지의 widthcontentViewwidth와 맞추면 되었습니다. 하지만 UIImage.contentMode를 어떻게 조정해도 가로 혹은 세로 사이즈의 요구조건을 맞출 수 없었습니다.

🧯 해결방법

  • UIImageView.contentMode와 상관없이, 비율을 계산하여 세로 사이즈를 조정해주기로 했습니다. 다행히도 이미지 검색 시 가로, 세로 사이즈 정보가 함께 제공되었기 때문에 어렵지 않게 높이를 동적으로 입력할 수 있었습니다.
    private func setPosterImage(_ imageDocument: ImageDocument, _ image: UIImage) {
        // 비율 = UIImage 프레임 가로 ÷ 로드된 이미지 실제 가로 사이즈
        let ratio = self.movieDetailView.posterImage.frame.width / CGFloat(integerLiteral: imageDocument.width)
        // 높이 = 비율 × 로드된 이미지 실제 세로 사이즈
        let height = ratio * CGFloat(integerLiteral: imageDocument.height)
        self.movieDetailView.posterImage.heightAnchor.constraint(equalToConstant: height).isActive = true
        self.movieDetailView.posterImage.image = image
    }

UIFont Extension을 활용하여 Dynamic Bold Font 구현

🔥 문제점

  • 특정 문자의 두께를 변경하고자 할 때 어떤 방법을 사용할 지 고민하였습니다.
  • swift 기본 제공 메서드를 활용하는 방법이 있지만, 이는 Font사이즈가 고정 된다는 단점이 존재했습니다.
    .systemFont(ofSize: 17, weight: .bold)
  • LabelButtonDynamic Type에 대한 대응이 되어야한다고 생각했기 때문에, Font의 사이즈가 고정되지 않으면서 특정 Font의 두께를 조절할 수 있는 방법을 찾고자 하였습니다.

🧯 해결방법

  • UIFontextension하여 폰트를 Custom할 수 있다는 것을 알게되어 이를 활용하였습니다.
    extension UIFont {
        static func preferredFont(for style: TextStyle, weight: Weight) -> UIFont {
            let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: style)
            let font = UIFont.systemFont(ofSize: descriptor.pointSize, weight: weight)
            let metrics = UIFontMetrics(forTextStyle: style)
            return metrics.scaledFont(for: font)
        }
    }

Singleton 구조의 DateManager로 Date 관리 로직 분리

🔥 문제점

  • 이전 Step에서는 어제의 날짜 기준으로 모든 데이터를 로드하면 되었으나, 이번 Step부터는 다양한 날짜를 대응해야 했습니다. 여러 ViewController에서 지정 날짜를 공유해야 하는 상황에서 어떤 방식으로 대응할지 고민을 했습니다.
  • ViewController간 날짜 정보를 주고 받을 수 있지만, 날짜 정보를 가지고 있는 ViewController가 모두 메모리에서 해제되는 경우 날짜 정보가 초기화 되는 위험이 있었습니다.
  • 기존에 생성한 BoxOfficeService는 앱의 생명주기와 함께하는 구조체이기 때문에, 기존 날짜 관련 로직을 이곳에서 관리하였습니다. 하지만 날짜 관련 로직이 증가하면서 이전과 같이 BoxOfficeService에서 이를 모두 관리하는 것은 적절하지 않다고 생각했습니다.

🧯 해결방법

  • DateManager를 생성하여 날짜 관련 프로퍼티를 해당 클래스에서 처리하도록 했습니다.
    class DateManager {
        static private let dateFormatter = DateFormatter()
        static let yesterday: Date = .now - (24 * 60 * 60)
        static var selectedDate: Date = yesterday
        ...
    
        private init() {}
    }

UICalendarView 선택된 날짜

🔥 문제점

  • 날짜선택 화면의 달력에는 현재 선택된 날짜가 미리 선택되어 있어야 한다는 내용이 있었습니다. 해당 요구사항을 구현하기 위해 UICalendarView.Decoration를 이용했습니다.

    커스텀 데코레이션에 적용한 코드

    private func customDecoration() -> UIView {
        let view = UIView()
        view.backgroundColor = .red
        view.clipsToBounds = false
        view.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
        return view
    }
  • 결과는 날짜의 하단 일부 영역에만 커스텀을 할 수 있을 뿐, 날짜 자체가 선택된 효과를 줄 수 없었습니다.

🧯 해결방법

  • UICalendarSelectionSingleDate를 인스턴스화 하고(UICalendarSelectionSingleDateDelegate도 채택합니다.) 아래 코드를 적용하면, 원하는 효과가 적용되는 것을 확인할 수 있었습니다.
    let dateSelection = UICalendarSelectionSingleDate(delegate: self)
    calendarView.selectionBehavior = dateSelection
  • 추가로 아래 코드를 작성하여 캘린더뷰가 열릴 때부터 날짜가 선택된 효과를 적용할 수 있었습니다.
    dateSelection.selectedDate = DateComponents(year: year, month: month, day: day)

7. 📚 주요 학습 내용

✏️ Modern Collection View - DiffableDataSource 사용하기

  • 일반 CollectionView
    • ViewControllerUICollectionViewDataSource 프로토콜 채택 후 필요 메서드를 구현합니다.
    • 이후 CollectionViewdataSourceself로 지정합니다.
  • Modern Collection View
    • dataSource로 사용할 UICollectionViewDiffableDataSource 클래스를 인스턴스화 합니다.
    • DiffableDataSource를 인스턴스화 할때는 CollectionView, 사용할 데이터(e.g. DTO, Model 등), Section, IndexPath가 필요로 합니다.
    • DiffableDataSource에서 사용하는 데이터 정보가 추가, 삭제, 변경이 되는 경우는 NSDiffableDataSourceSnapshot 클래스를 사용합니다.
    • SnapShot에는 Section정보와 Items정보를 각각 전달합니다.
    • 이후 dataSource인스턴스에 Snapshotapply합니다.

✏️ iOS14버전 이하와도 호환이 되는 CollectionView 구성하기

  • CollectionView 요소를 구성할 때, 버전 호환 문제와 직면하였습니다.
  1. 디테일 악세사리 구현 시 예시에 제시되어 있는 디테일 악세사리를 UICellAccessory에서 지원해주었습니다.

    cell.accessories = [ 
        .disclosureIndicator(options: .init(tintColor: .systemGray)), 
    ]

    하지만 UICellAccessory은 iOS 14.0 이상부터 지원이 가능하였습니다.

    참고 - UICellAccessory 공식 문서

    이를 사용하면 iOS14.0 이하 버전을 지원할 수 없기 때문에 다른 방식으로 구현해보고자 했습니다. 하여 별도의 label을 만들어 디테일 악세사리뷰와 같은 형태를 띌 수 있도록 하였습니다.

    private let disclosureIndicatorLabel: UILabel = {
        var label = UILabel()
        label.text = ""
        label.textColor = UIColor(displayP3Red: 0.8, green: 0.8, blue: 0.8, alpha: 1)
        return label
    }()
  2. 셀 Separator 구현 시 UICollectionViewListCell의 프로퍼티 중 separator를 사용하면 각 CollecionViewCell 별로 구분선을 생성할 수 있습니다. 하지만 UICollectionViewListCell은 iOS14.0 이상 버전에서만 지원이 가능합니다.

    참고 - UICollectionViewListCell 공식 문서

    하여 iOS14.0이하 버전과의 호환을 위해 CustomCell의 내용을 View로 감싸서 위,아래 높이 1pt 여백 공간을 만들어 separator로 보일 수 있게금 코드 작성을 했습니다.

    private lazy var separatorLineView: UIView = {
        let view = UIView()
        view.backgroundColor = .init(displayP3Red: 0.9, green: 0.9, blue: 0.9, alpha: 1)
        view.frame.size.width = view.frame.width
        view.translatesAutoresizingMaskIntoConstraints = false
        
        return view
    }()

✏️ animatedImage를 활용하여 Loading 화면 구성

  • 이미지 로딩 화면을 구성 시 어떤 방법을 사용할 지 고민이 많았습니다. BoxOfficeViewController처럼 activityIndicatorView를 사용할 수도 있었지만, 다른 종류의 로딩화면도 구현해보고자 하였습니다. 고민을 하던 중 통상적인 앱에서 로딩화면서 움직이는 이미지를 참고하여 이와 비슷하게 구현을 해보고자 하였습니다.
  • assetgif 이미지를 framepng파일로 분리하여 저장하였습니다. 이를 UIImage에서 animatedImage를 활용하여 임의의 duration을 지정하여 자연스럽게 움직이는 형상을 보여줄 수 있도록 하였습니다.
  • 현재 저희 프로젝트에서 로딩하는 이미지는 빠른 속도로 처리가 되기 때문에 저희가 구성한 Image Loading화면이 짧은 찰나에 깜빡이고 사라지는 형상을 띄게 되었습니다. 저희는 오히려 이렇게 짧은 로딩화면이 user에게 오류가 나는 형상처럼 보여질 수 있다 생각하였습니다. 하여 이미지가 로딩 중이라는 것을 user에게 명시하기 위해 usleep(500000)을 주어 Image Loading의 과정이 보다 저희의 의도와 맞게끔 조정하였습니다.

✏️ URLCache in Memory

  • 저희는 프로젝트에 NSCache를 적용했지만, URLCache도 공부해 보았습니다.
  • URLCache는 기본적으로 캐시 저장이 ondisk인 것을 확인했고, 이것을 변경하기 위해 StoragePolicyallowedInMemoryOnly로 지정해 보았습니다. 하지만 저희의 예상과 달리 StoragePolicy를 변경하였음에도 캐시 데이터가 Memory에 저장 되지 않았습니다.
  • 아래와 같이 여러 실험 끝에 (30 * 1024 * 1024) 부터는 URLCache메모리에 저장이 되는 것을 확인할 수 있었습니다.
    ------------------------------------------------------------------------------
    URLCache.shared의 memoryCapacity: 512,000 bytes
                      diskCapacity: 10,000,000 bytes
    
    CachedURLResponse의 storagePolicy가 .allowedInMemoryOnly일 때,
    memoryCapacity: 10, 20 (* 1024 * 1024)일 때는 실패함. 30부터 성공. 31,457,280 bytes
    첫번째 data - 1,469,837 bytes
    두번째 data - 1,078,478 bytes
    ------------------------------------------------------------------------------
    
  • 때문에 저희는 저장되어야하는 데이터 보다 지정 memoryCapacity가 클 때만 URLCacheinmemory Policy가 적용된다고 추측했습니다.

8. 💭 팀 회고

팀 회고

우리팀이 잘한 점😃

추후 작성 예정

우리팀이 아쉬웠던 점😭

추후 작성 예정


9. 🔗 참고 링크

🍎 Developer Apple

📒 Blog

👾 Git

🌊 stack overflow