Taehyeon-Kim/SeSAC

Builder 패턴 이용해서 URLSession Network Layer 구성해보기

Taehyeon-Kim opened this issue · 0 comments

요즘 공부의 어느 정도 시간은 네트워크 통신 부분에 대한 학습, 네트워크 레이어 추상화에 대한 것을 연구해보고 있다.
그리고 나만의 네트워크 라이브러리 선택 기준도 고민해보는 중

네트워크 통신은 정말 요청(Request)과 응답(Response)이 다라는 것을 요즘 더 강하게 느낀다.

스스로 정리가 얼추 되면, 네트워크 통신에 대해서 내 나름대로 정리해보려고 한다. 자원(리소스)이 있는 서버 쪽에 요청할 요청서를 만들고, 가져온 자원을 앱의 상황에 맞게 적절히 해독하고 가공해서 쓰는 것 이것이 다라고 생각한다. 요청을 통해 자원을 생성하는 경우도 있지만 대부분의 경우 데이터를 받아쓰는 클라이언트의 입장에서는 요청이 특히나 중요하다고 본다.

요청서에 필요한 정보는 크게 다음과 같다.

  • URL(Path, Query ...) (필수)
  • HTTPMethod (필수)
  • HTTPHeader (반 필수)
  • HTTPParameter (선택)
  • 기타 정보 .. (timeout, caching policy, network connection ...)

다음의 정보를 잘 조합시켜서 요청서(요청정보 == URLRequest)를 만드는 것이 네트워크 통신에 있어 가장 중요한 작업 중 하나가 아닐까 싶다. 이것만 잘 이해한다면 통신은 80~90% 끝이라고 본다. (아니라고 생각하면 어쩔 수 없다. .)

Builder 패턴으로 네트워크 레이어를 추상화 해봄

  • https://github.com/hmlongco/RequestBuilder
  • 위의 레포지터리를 공부하면서 Rx 형태로 변화시켜보려고 함.
  • BaseSessionManager.swift 파일 부분에서 nil 값이 생겨서 정상적으로 결과를 반환하지 못했음
    • LLDB로 이슈를 조금 빠른 속도로 찾아볼 수 있었음. (print 찍었으면 날 밤 샜을 듯)
  • Builder 패턴을 이용하면 SwiftUI 처럼 선언형으로 코드 조각을 구성해볼 수 있음.
    • Request에 필요한 내용들이 어느 정도 정해져있는 네트워크 레이어의 경우 해당 패턴으로 구성하면 적절하게 잘 쓸 수 있을 것 같아서 공부해보고 싶었음.
    • 지금은 아직 완벽히 구현은 하지 않은 상태라 애매한데, 필요한 파일만 남기면 괜찮게 이용해볼 수 있을 것 같음.
    • Alamofire, Moya 정말 좋은 라이브러리들인데, 지금 드는 생각은 생각보다 정말 일부 기능만 쓰고 있다는 생각이 들었음. 사용하지 않은 기능에 대한 코드는 불필요하게 낭비되는 경우도 많다고 봄. (1) 개발 기간이 어느 정도 확보되어있거나 (2) 혼자 개발하거나 한다면 URLSession으로 필요한 기능만 추상화해서 사용하는 것도 나쁘지 않다고 생각함. 물론 숙련도가 어느 정도 있거나 한다면 Alamofire, Moya를 쓰는 것이 효율성 측면에서는 좋아보임.

사용 예시

지금은 data 메서드의 return 타입이 RxSwift의 Single Traits이기 때문에 사용 예시가 아래와 같음. Combine과도 섞어볼 수 있고 다양한 형태로 가공할 수 있을 것 같음

let base = URL(string: SeSACAPI.baseURL)
let sessionManager = BaseSessionManager(base: base, session: URLSession.shared)

sessionManager.request()
    .add(path: SeSACAPI.profile.path)
    .add(headers: SeSACAPI.profile.headers)
    .method(.get)
    .data(type: UserResponse.self, decoder: JSONDecoder())
    .subscribe { response in
        print(response)
        print("🎊 :: 프로필 불로오기 성공 :: \(response.user)")
    } onFailure: { error in
        print("😿 :: 프로필 불로오기 실패 :: \(error.localizedDescription)")
    }.disposed(by: disposeBag)

오늘은 여기까지

좀만 더 정리되면 기존에 많이 볼 수 있는 글처럼 단순히 네트워크 라이브러리 사용법에 대한 내용이 아닌 내가 이해한대로 네트워크 통신을 몇 편(미정)의 글로 정리해보고자 한다. (할 수 있겠지 ...? ^^)