MovieRank App 기획 + URLSession

주방·2023년 4월 26일
0

MovieRank

목록 보기
1/8

배경

  1. 현재까지 개발공부를 진행하면서 디자인 패턴과 여러 라이브러리를 통해 여러 실습 앱을 만들었음.
  2. 학습했지만 영상을 따라하거나 과제 수행을 위해 이해없이 실제 구현에만 집중해 놓친 부분이 많음을 알게 되었음. 동작에 대한 의미를 묻더라도 '그냥' 이라고 답변하는 경우가 많아 간단한 예제를 스스로 설정하고 학습 흐름을 정해보았음.
  3. 먼저 주제는 TMDB에서 제공하는 주간 영화순위 정보를 가져와 CollectionView에 표시하고, 셀을 클릭할 경우 세부 정보를 표시하는 앱으로 설정하였음.
  4. 구현 순서의 경우 아래와 같다.
    • 아래
      • MVC로 구현하기: MVC (Model-View-Controller) 디자인 패턴을 사용하여 기본적인 구조를 이해하고, 애플리케이션을 구현
      • MVVM으로 구현하기: MVVM (Model-View-ViewModel) 디자인 패턴을 사용하여 애플리케이션의 코드를 개선하고, ViewModel을 도입하여 View와 Model을 분리
      • ViewModel 입출력 표현 및 RxSwift 사용: ViewModel의 입력과 출력을 프로토콜을 사용하여 명확하게 구분하고, RxSwift를 사용하여 비동기적으로 데이터를 전달하고 처리
      • Coordinator 패턴 사용하기: 화면 전환과 관련된 로직을 Coordinator 패턴을 사용하여 분리하고, 애플리케이션의 구조 개선
      • Dependency Injection: 의존성 주입 패턴을 사용하여 애플리케이션의 구성 요소 간의 결합도를 낮추고, 유연한 구조 개선
  5. 학습에 정해진 기한은 없으며, 이전에 잘 이해하지 못하고 썼었던 개념이나 스스로 몰랐다고 생각된 부분을 되짚어 보고자 함.(나를 위한 글)

오늘의 진행

  1. MVC로 구현하기를 진행되고 있음. 포스터 이미지와 영화 타이틀의 경우 CollectionView를 통해 구현하였음. (CollectionView를 사용한 것은 이제껏 TableView 위주로 구현했기 때문에 사용하였음.)
  2. CollectionView의 경우 layout을 잡을 때 Sanpkit을 사용하여 구현하였음.
  3. View에 이미지, 타이틀을 표시하기 위해 TMDB API를 가지고, 영화 정보를 가져오고자 함.(이 과정을 통해 URLSession에 대한 기록을 남겨야겠다는 생각을 함)

구현 GIF


URLSession

  1. 평소 네트워크 통신의 경우 무척 중요한 부분으로 받아들이고 있었으나, 세심하게 들여다 보지 않고, 구현하기 쉬운 Alamofire 라이브러리를 사용해 빠르게 구현했음.
  2. 네트워크 통신을 위한 도구, 라이브러리의 경우 여러가지가 있겠지만, 대표적으로 URLSession, Alamofire, Moya가 있음.
  3. 이번엔 URLSession을 사용할 것임.
  4. 네트워크 통신 작업 순서이다.
    • Api 문서 확인: api의 엔드포인트, 요청메서드, 헤더, 파라미터 등을 이해함
    • postman을 통해 API 응답확인: 문서를 통해 정상적으로 요청했을 경우 어떤 값이 응답되고 있는지 봐야 한다. 이를 통해 model을 작성함.
    • model 작성: api 응답의 json 형태를 기반으로 codable 프로토콜을 구현한 모델 구조체를 작성한다. Codingkey 열거형을 사용해 json 키와 모델의 속성 사이의 매핑을 정의
    • API 통신 코드 작성: URLSession, URLRequest 등을 사용해 API 요청을 전송하는 코드를 작성함. 이때 API 문서에 있는 요청메서드, 헤더, 파라미터등을 설정함
      • URLSession 객체 생성: URLSession 객체를 생성
      • URL 객체 생성: 요청을 보낼 URL 객체를 생성
      • URLRequest 객체 생성: URL 객체를 기반으로 URLRequest 객체를 생성합니다. 이 객체는 실제로 요청을 보낼 때 사용되는 객체로, HTTP 메서드, 헤더, 바디 등의 정보 포함
      • URLSessionDataTask 객체 생성 및 실행: URLRequest 객체를 기반으로 URLSessionDataTask 객체를 생성
    • 응답데이터 처리
  5. 이와 같은 흐름으로 작업을 진행하였음.

코드로 통신 작업 순서 살펴보기

  • Api 문서 확인: api의 엔드포인트, 요청메서드, 헤더, 파라미터 등을 이해함

    • 링크를 통해서 api 정보를 확인하였음.
  • postman을 통해 API 응답확인: 문서를 통해 정상적으로 요청했을 경우 어떤 값이 응답되고 있는지 봐야 한다. 이를 통해 model을 작성함.

  • model 작성: api 응답의 json 형태를 기반으로 codable 프로토콜을 구현한 모델 구조체를 작성한다. Codingkey 열거형을 사용해 json 키와 모델의 속성 사이의 매핑을 정의
struct MovieResponse: Codable{
    let page: Int
    let results: [Movie]
}

struct Movie: Codable {
    let title: String
    let posterPath: String?
    let releaseDate: String
    let voteAverage: Double
    let overview: String
    
    enum CodingKeys: String, CodingKey{
        case title
        case posterPath = "poster_path"
        case releaseDate = "release_date"
        case voteAverage = "vote_average"
        case overview
    }
}
// 필요한 정보만 model로 설정하였음.
  • API 통신 코드 작성: URLSession, URLRequest 등을 사용해 API 요청을 전송하는 코드를 작성함. 이때 API 문서에 있는 요청메서드, 헤더, 파라미터등을 설정함

    • URLSession 객체 생성: URLSession 객체를 생성
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)
    • URL 객체 생성: 요청을 보낼 URL 객체를 생성
    • URLRequest 객체 생성: URL 객체를 기반으로 URLRequest 객체를 생성합니다. 이 객체는 실제로 요청을 보낼 때 사용되는 객체로, HTTP 메서드, 헤더, 바디 등의 정보 포함
    let requestURL = URL(string: "https://api.themoviedb.org/3/trending/movie/week?api_key=\(APIKey.apiKey)")
    
    guard let url = requestURL else {
        let error = NSError(domain: "", code: 0)
        completion(.failure(error))
        return
    }
    • URLSessionDataTask 객체 생성 및 실행: URLRequest 객체를 기반으로 URLSessionDataTask 객체를 생성
     private func performRequest(url: URL, completion: @escaping (Result<Data, Error>) -> Void) {
            let config = URLSessionConfiguration.default
            let session = URLSession(configuration: config)
            
            let dataTask = session.dataTask(with: url) { data, response, error in
                if let error = error {
                    completion(.failure(error))
                    return
                }
                
                guard let data = data else {
                    let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Data not found"])
                    completion(.failure(error))
                    return
                }
                
                completion(.success(data))
            }
            dataTask.resume()
        }
    
    performRequest(url: url) { result in
                switch result {
                case .success(let data):
                    do {
                        let decoder = JSONDecoder()
                        let movieResponse = try decoder.decode(MovieResponse.self, from: data)
                        completion(.success(movieResponse))
                    } catch let error {
                        completion(.failure(error))
                    }
                case .failure(let error):
                    completion(.failure(error))
                }
            }
  • 응답데이터 처리


정리

Alamofire를 사용하지 않고, URLSession을 이용해 구현을 하면서 네트워크 통신 작업의 흐름을 다시 한번 되짚어 볼 수 있었음.
이에 다른 라이브러리의 사용하더라도 유사한 흐름으로 작업할 수 있겠다는 생각을 했음.

0개의 댓글