Skip to content

Commit

Permalink
[Network] 네트워크 모듈 + API Mocking 모듈 추가 (#2)
Browse files Browse the repository at this point in the history
* 📦 Implement network module

* 📦 Implement APIService module

* ✏️ Fix typos
  • Loading branch information
WhiteHyun authored Jan 25, 2024
1 parent 7b1d054 commit 2f474cb
Show file tree
Hide file tree
Showing 16 changed files with 451 additions and 0 deletions.
8 changes: 8 additions & 0 deletions APIService/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
37 changes: 37 additions & 0 deletions APIService/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "APIService",
platforms: [.iOS(.v17)],
products: [
.library(
name: "HomeAPI",
targets: ["HomeAPI"]
),
.library(
name: "HomeAPISupport",
targets: ["HomeAPISupport"]
),
],
dependencies: [
.package(path: "../Core"),
],
targets: [
.target(
name: "HomeAPI",
dependencies: [
.product(name: "Network", package: "Core"),
]
),
.target(
name: "HomeAPISupport",
dependencies: [
"HomeAPI",
],
resources: [.process("HomeProductResponse.json")]
),
]
)
21 changes: 21 additions & 0 deletions APIService/Sources/HomeAPI/HomeEndPoint.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// HomeEndPoint.swift
//
//
// Created by 홍승현 on 1/25/24.
//

import Foundation
import Network

struct HomeEndPoint: EndPoint {
var baseURL: String

var method: HTTPMethod

var path: String

var parameters: Network.HTTPParameter

var headers: [String: String]
}
85 changes: 85 additions & 0 deletions APIService/Sources/HomeAPISupport/HomeProductResponse.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{
"count": 10,
"products": [
{
"date": "2024:01",
"img": "https://image.woodongs.com/imgsvr/item/GD_8809288634967_001.jpg",
"price": 2500,
"name": "BR)레인보우샤베트과즙워터500ML",
"tag": "1+1",
"store": "GS25"
},
{
"date": "2024:01",
"img": "https://image.woodongs.com/imgsvr/item/GD_8809288635315_003.jpg",
"price": 2500,
"name": "BR)망고탱고과즙워터500ML",
"tag": "1+1",
"store": "GS25"
},
{
"date": "2024:01",
"img": "https://image.woodongs.com/imgsvr/item/GD_8809288634974_001.jpg",
"price": 2500,
"name": "BR)피치요거트과즙워터500ML",
"tag": "1+1",
"store": "GS25"
},
{
"date": "2024:01",
"img": "https://image.woodongs.com/imgsvr/item/GD_8806002010861_865.jpg",
"price": 5000,
"name": "광동)헛개파워100ML",
"tag": "1+1",
"store": "GS25"
},
{
"date": "2024:01",
"img": "https://image.woodongs.com/imgsvr/item/GD_8806011416005_001.JPG",
"price": 5000,
"name": "동아)모닝케어D100ML",
"tag": "1+1",
"store": "GS25"
},
{
"date": "2024:01",
"img": "https://image.woodongs.com/imgsvr/item/GD_8806011415992_001.JPG",
"price": 5000,
"name": "동아)모닝케어H100ML",
"tag": "1+1",
"store": "GS25"
},
{
"date": "2024:01",
"img": "https://image.woodongs.com/imgsvr/item/GD_8809556566891_001.jpg",
"price": 5000,
"name": "서영)모닝이즈백100ML",
"tag": "1+1",
"store": "GS25"
},
{
"date": "2024:01",
"img": "https://image.woodongs.com/imgsvr/item/GD_8809125061857_002.jpg",
"price": 5000,
"name": "종근당)헛개땡큐골드100ML",
"tag": "1+1",
"store": "GS25"
},
{
"date": "2024:01",
"img": "https://image.woodongs.com/imgsvr/item/GD_8809329050015_018.jpg",
"price": 5000,
"name": "천지개벽)숙취해소음료100ML",
"tag": "1+1",
"store": "GS25"
},
{
"date": "2024:01",
"img": "https://image.woodongs.com/imgsvr/item/GD_8801013777260_001.jpg",
"price": 5000,
"name": "큐원)상쾌환부스터100ML",
"tag": "1+1",
"store": "GS25"
}
]
}
43 changes: 43 additions & 0 deletions APIService/Sources/HomeAPISupport/HomeURLProtocol.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// HomeURLProtocol.swift
//
//
// Created by 홍승현 on 1/25/24.
//

import Foundation
import Network

public final class HomeURLProtocol: URLProtocol {
private let fileName = "HomeProductResponse"

override public class func canInit(with _: URLRequest) -> Bool {
true
}

override public class func canonicalRequest(for request: URLRequest) -> URLRequest {
request
}

override public func startLoading() {
defer { client?.urlProtocolDidFinishLoading(self) }
if let data = loadMockData(fileName: fileName),
let url = request.url,
let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: nil, headerFields: nil) {
client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
client?.urlProtocol(self, didLoad: data)
} else {
client?.urlProtocol(self, didFailWithError: NetworkError.urlError)
}
}

override public func stopLoading() {}

private func loadMockData(fileName: String) -> Data? {
guard let url = Bundle.module.url(forResource: fileName, withExtension: "json")
else {
return nil
}
return try? Data(contentsOf: url)
}
}
8 changes: 8 additions & 0 deletions Core/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
23 changes: 23 additions & 0 deletions Core/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Core",
platforms: [.iOS(.v17)],
products: [
.library(
name: "Network",
targets: ["Network"]
),
],
targets: [
.target(
name: "Network"),
.testTarget(
name: "CoreTests",
dependencies: ["Network"]
),
]
)
26 changes: 26 additions & 0 deletions Core/Sources/Network/EndPoint.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// EndPoint.swift
//
//
// Created by 홍승현 on 1/25/24.
//

/// 네트워킹 작업 정보를 담습니다.
public protocol EndPoint {
/// 공통 base URL
var baseURL: String { get }

/// http request method
var method: HTTPMethod { get }

/// HTTP path
var path: String { get }

/// 요청시 넣을 파라미터입니다.
///
/// body값이거나 query값을 설정할 때 이용합니다.
var parameters: HTTPParameter { get }

/// 헤더 값을 설정합니다.
var headers: [String: String] { get }
}
14 changes: 14 additions & 0 deletions Core/Sources/Network/HTTPMethod.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// HTTPMethod.swift
//
//
// Created by 홍승현 on 1/25/24.
//

/// http 요청에서 메서드 타입을 담당합니다.
public enum HTTPMethod: String {
case get = "GET"
case post = "POST"
case delete = "DELETE"
case put = "PUT"
}
24 changes: 24 additions & 0 deletions Core/Sources/Network/HTTPParameter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// HTTPParameter.swift
//
//
// Created by 홍승현 on 1/25/24.
//

/// 통신 요청 시 필요한 파라미터 데이터를 담습니다.
public enum HTTPParameter {
/// 빈 평문입니다.
///
/// 아무런 정보 값 없이 요청할 때 사용합니다.
case plain

/// query를 설정합니다.
///
/// query문으로 요청값을 전달하고 싶을 때 사용합니다.
case query(Encodable)

/// body를 설정합니다.
///
/// `post`요청과 같이 body-field에 무언가를 담아 보내야하는 경우에 사용합니다.
case body(Encodable)
}
43 changes: 43 additions & 0 deletions Core/Sources/Network/NetworkError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// NetworkError.swift
//
//
// Created by 홍승현 on 1/25/24.
//

import Foundation

// MARK: - NetworkError

public enum NetworkError {
case urlError
case decodeError
case encodeError
case requestError(Error)
case responseError
case failedResponse(statusCode: Int)
case emptyResponse
}

// MARK: LocalizedError

extension NetworkError: LocalizedError {
public var errorDescription: String? {
switch self {
case .urlError:
"잘못된 URL 입니다."
case .decodeError:
"디코딩에 실패했습니다."
case .encodeError:
"인코딩에 실패했습니다."
case let .requestError(error):
"요청 간 에러가 발생했습니다. \(error)"
case .responseError:
"잘못된 응답입니다."
case let .failedResponse(statusCode):
"Error status code : \(statusCode)"
case .emptyResponse:
"응답이 비어있습니다."
}
}
}
Loading

0 comments on commit 2f474cb

Please sign in to comment.