Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

오픈 마켓 [STEP 1] 아리,제리 #82

Merged
merged 43 commits into from
Jan 7, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ca846b3
style: SwfitLint 라이브러리 추가
leeari95 Jan 3, 2022
d04a121
feat: Products 타입 추가 #1
llghdud921 Jan 3, 2022
2b14a79
feat: Product 타입 추가 #1
leeari95 Jan 3, 2022
f57c0e3
chore: products 파일 Assests에 추가
llghdud921 Jan 3, 2022
82fafce
feat: 파싱해주는 타입 Parser을 추가 #1
leeari95 Jan 3, 2022
a8e9388
test: ParsetTest 추가 #2
llghdud921 Jan 3, 2022
59f34d1
test: product를 파싱하는 테스트 추가 #2
leeari95 Jan 4, 2022
c4406dd
feat: network class 타입 및 NetworkError 추가 #3
llghdud921 Jan 4, 2022
4c22c0a
feat: URL과 HTTPMethod를 담고있는 타입 추가 #3
leeari95 Jan 4, 2022
2af414a
feat: NetworkManager 추가 #3
llghdud921 Jan 4, 2022
4446fd0
feat: 상품 리스트 조회시 필요한 request를 반환하는 메소드 추가 #3
leeari95 Jan 4, 2022
826aaf3
feat: 상품 상세 조회를 위한 request메서드 추가 #3
llghdud921 Jan 4, 2022
2679eef
feat: 상품의 Secret을 조회할 때 필요한 Request 반환하는 메소드 추가 #3
leeari95 Jan 4, 2022
c67be7b
feat: 상품 삭제를 위한 request 메소드 추가 #3
llghdud921 Jan 4, 2022
0cefe03
feat: 상품 수정을 위한 request 메소드 추가 #3
leeari95 Jan 4, 2022
b088b10
feat: 상품 등록을 위한 request 추가 #3
llghdud921 Jan 4, 2022
be0cb43
refactor: NetworkManager 내부 리팩토링 #4
leeari95 Jan 4, 2022
27fa33f
refactor: NetworkError 내부 리팩토링 및 ProductSecret 타입명 변경 #4
llghdud921 Jan 4, 2022
e73b5fc
refactor: MultipartForm 프로토콜을 Protocol 그룹으로 이동 #4
leeari95 Jan 4, 2022
a54a4ce
refactor: Products 내 CodingKeys 수정 #4
llghdud921 Jan 4, 2022
3294a3d
test: Network의 excute 메소드를 테스트하는 코드 추가 #5
leeari95 Jan 5, 2022
7872ab5
test: NetworkManager의 fetch를 테스트하는 코드 추가 #5
llghdud921 Jan 5, 2022
cacce89
test: URLProtocol을 재정의하여 테스트 코드를 전반적으로 수정 #5
leeari95 Jan 5, 2022
aa5b4d2
refactor: NetworkManager내 multipart image 경로 수정 #4
llghdud921 Jan 5, 2022
fb39366
test: 상품리스트 조회에 맞는 Request를 반환하는 테스트코드 추가 #5
leeari95 Jan 5, 2022
b0eb1e0
test: 상품 상세 조회를 반환하는 request를 확인하는 테스트코드 추가 #5
llghdud921 Jan 5, 2022
e4cdd8a
test: 상품 삭제 Secret 조회에 맞는 Request를 반환하는 테스트코드 추가 #5
leeari95 Jan 5, 2022
7f373fc
test: 상품 삭제를 반환하는 request를 확인하는 테스트코드 추가 #5
llghdud921 Jan 5, 2022
a245770
test: 상품 수정에 맞는 Request를 반환하는 테스트코드 추가 #5
leeari95 Jan 5, 2022
42a798d
test: 상품 등록을 반환하는 request를 확인하는 테스트코드 추가 #5
llghdud921 Jan 5, 2022
1bde0bd
refactor: multipartFormRequest 메소드 내부에 request의 헤더를 추가하는 부분 수정 #4
leeari95 Jan 6, 2022
cfd7f09
refactor: MockURLProtocol내 주석 제거 #4
llghdud921 Jan 6, 2022
79c207a
refactor: NetworkConstant를 Address와 HTTPMethod로 분리 #4
leeari95 Jan 6, 2022
69352ee
docs: Step1 README 작성
llghdud921 Jan 6, 2022
164da38
docs: README.md 파일 수정
leeari95 Jan 6, 2022
afa5c2a
refactor: 테스트 코드에 중복되는 부분 리팩토링 #6
leeari95 Jan 6, 2022
dd21787
refactor: test code내 주석 및 줄바꿈 수정 #6
llghdud921 Jan 6, 2022
7bd46d8
refactor: Image의 프로퍼티 네이밍을 명확하게 수정 #6
leeari95 Jan 6, 2022
513ae69
refator: Content-type,MultipartForm String값 상수로 정의 #6
llghdud921 Jan 6, 2022
e3b81a7
refactor: 에러의 케이스중 네이밍을 명확하게 개선 #6
leeari95 Jan 6, 2022
05fddcb
refactor: Parser, Parsable에 JSON을 추가한 네이밍으로 개선 #6
llghdud921 Jan 6, 2022
e44134c
refactor: Network 프로퍼티에 접근제어 부여하여 개선 #6
leeari95 Jan 6, 2022
d553f99
refactor: Address를 APIAdress로 네이밍 개선 #6
llghdud921 Jan 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
refator: Content-type,MultipartForm String값 상수로 정의 #6
- MultiPartForm 프로토콜을MultiPartFormProtocol로 변경
- MultipartForm, contentType enum 구현 및 관련 코드 수정
- 오버로딩된 request 함수명 명확하게 개선
- 들여쓰기 컨벤션 개선
  • Loading branch information
llghdud921 committed Jan 6, 2022
commit 513ae69cb572f0c3d3bdb44fa4dc84eef4b4bb07
16 changes: 12 additions & 4 deletions OpenMarket/OpenMarket.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
9A1CFDCA27841CD0003BEC69 /* ProductSecret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1CFDC927841CD0003BEC69 /* ProductSecret.swift */; };
9A1CFDCC27842755003BEC69 /* ProductModification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1CFDCB27842755003BEC69 /* ProductModification.swift */; };
9A1CFDCE27842E2E003BEC69 /* Currency.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1CFDCD27842E2E003BEC69 /* Currency.swift */; };
9A1CFDD1278469D5003BEC69 /* MultipartForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1CFDD0278469D5003BEC69 /* MultipartForm.swift */; };
9A1CFDD1278469D5003BEC69 /* MultipartFormProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1CFDD0278469D5003BEC69 /* MultipartFormProtocol.swift */; };
9A1CFDD3278526B8003BEC69 /* NetworkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1CFDD2278526B8003BEC69 /* NetworkTests.swift */; };
9A1CFDD527852721003BEC69 /* MockSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1CFDD427852721003BEC69 /* MockSession.swift */; };
9AAA3EAE2785726A00D6E407 /* StubProducts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AAA3EAD2785726A00D6E407 /* StubProducts.swift */; };
Expand All @@ -40,6 +40,8 @@
F35B1A8B2785386B0031A755 /* StubParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = F35B1A8A2785386B0031A755 /* StubParser.swift */; };
F35B1A8F27853DE60031A755 /* NetworkManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F35B1A8E27853DE60031A755 /* NetworkManagerTests.swift */; };
F39BD72A2782DFA000D4B32D /* Products.swift in Sources */ = {isa = PBXBuildFile; fileRef = F39BD7292782DFA000D4B32D /* Products.swift */; };
F3D3B5AD2787329600943720 /* MultipartForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D3B5AC2787329600943720 /* MultipartForm.swift */; };
F3D3B5AF278732C700943720 /* ContentType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3D3B5AE278732C700943720 /* ContentType.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -62,7 +64,7 @@
9A1CFDC927841CD0003BEC69 /* ProductSecret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductSecret.swift; sourceTree = "<group>"; };
9A1CFDCB27842755003BEC69 /* ProductModification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductModification.swift; sourceTree = "<group>"; };
9A1CFDCD27842E2E003BEC69 /* Currency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Currency.swift; sourceTree = "<group>"; };
9A1CFDD0278469D5003BEC69 /* MultipartForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipartForm.swift; sourceTree = "<group>"; };
9A1CFDD0278469D5003BEC69 /* MultipartFormProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipartFormProtocol.swift; sourceTree = "<group>"; };
9A1CFDD2278526B8003BEC69 /* NetworkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkTests.swift; sourceTree = "<group>"; };
9A1CFDD427852721003BEC69 /* MockSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MockSession.swift; path = "Test Doubles/MockSession.swift"; sourceTree = "<group>"; };
9AAA3EAD2785726A00D6E407 /* StubProducts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StubProducts.swift; path = "Test Doubles/StubProducts.swift"; sourceTree = "<group>"; };
Expand All @@ -89,6 +91,8 @@
F35B1A8A2785386B0031A755 /* StubParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StubParser.swift; path = "Test Doubles/StubParser.swift"; sourceTree = "<group>"; };
F35B1A8E27853DE60031A755 /* NetworkManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkManagerTests.swift; sourceTree = "<group>"; };
F39BD7292782DFA000D4B32D /* Products.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Products.swift; sourceTree = "<group>"; };
F3D3B5AC2787329600943720 /* MultipartForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipartForm.swift; sourceTree = "<group>"; };
F3D3B5AE278732C700943720 /* ContentType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentType.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -112,7 +116,7 @@
9A1CFDCF278469A6003BEC69 /* Protocol */ = {
isa = PBXGroup;
children = (
9A1CFDD0278469D5003BEC69 /* MultipartForm.swift */,
9A1CFDD0278469D5003BEC69 /* MultipartFormProtocol.swift */,
F35B1A86278537BD0031A755 /* Networkable.swift */,
F35B1A882785380D0031A755 /* Parserable.swift */,
);
Expand Down Expand Up @@ -240,6 +244,8 @@
9A1CFDC72783EE09003BEC69 /* Address.swift */,
F35B1A6727840CA80031A755 /* NetworkManager.swift */,
9AAA3F352786B92400D6E407 /* HTTPMethod.swift */,
F3D3B5AC2787329600943720 /* MultipartForm.swift */,
F3D3B5AE278732C700943720 /* ContentType.swift */,
);
path = Network;
sourceTree = "<group>";
Expand Down Expand Up @@ -389,8 +395,10 @@
F39BD72A2782DFA000D4B32D /* Products.swift in Sources */,
F35B1A73278442F40031A755 /* ImageFile.swift in Sources */,
9A1CFDC82783EE09003BEC69 /* Address.swift in Sources */,
9A1CFDD1278469D5003BEC69 /* MultipartForm.swift in Sources */,
F3D3B5AD2787329600943720 /* MultipartForm.swift in Sources */,
9A1CFDD1278469D5003BEC69 /* MultipartFormProtocol.swift in Sources */,
F35B1A892785380D0031A755 /* Parserable.swift in Sources */,
F3D3B5AF278732C700943720 /* ContentType.swift in Sources */,
9A1CFD7A2782E683003BEC69 /* Parser.swift in Sources */,
9A1CFDC62783DD63003BEC69 /* Vendors.swift in Sources */,
9A1CFD7C2782EB88003BEC69 /* ParserError.swift in Sources */,
Expand Down
25 changes: 25 additions & 0 deletions OpenMarket/OpenMarket/Model/Network/ContentType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// ContentType.swift
// OpenMarket
//
// Created by 이호영 on 2022/01/06.
//

import Foundation

enum ContentType {
case contentType
case json
case formData(boundary: String)

var string: String {
switch self {
case .contentType:
return "Content-Type"
case .json:
return "application/json"
case .formData(let boundary):
return "multipart/form-data; boundary=\"\(boundary)\""
}
}
}
34 changes: 34 additions & 0 deletions OpenMarket/OpenMarket/Model/Network/MultipartForm.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// MultipartForm.swift
// OpenMarket
//
// Created by 이호영 on 2022/01/06.
//

import Foundation

enum MultipartForm {
case boundary(baseBoundary: String)
case contentDisposition(name: String)
case value(_ value: Any)
case imageContentDisposition(filename: String)
case imageContentType(imageType: String)
case imageValue(data: Data)

var string: String {
switch self {
case .boundary(let baseBoundary):
return "--\(baseBoundary)\r\n"
case .contentDisposition(let name):
return "Content-Disposition: form-data; name=\"\(name)\"\r\n\r\n"
case .value(let value):
return "\(value)\r\n"
case .imageContentDisposition(let filename):
return "Content-Disposition: form-data; name=\"images[]\"; filename=\"\(filename)\"\r\n"
case .imageContentType(let imageType):
return "Content-Type: \(imageType)\r\n\r\n"
case .imageValue(let data):
return "\(data)\r\n"
}
}
}
57 changes: 31 additions & 26 deletions OpenMarket/OpenMarket/Model/Network/NetworkManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ struct NetworkManager {
self.parser = parser
}

func fetch<T: Decodable>(request: URLRequest,
decodingType: T.Type,
completion: @escaping (Result<T, Error>) -> Void) {

func fetch<T: Decodable>(
request: URLRequest,
decodingType: T.Type,
completion: @escaping (Result<T, Error>) -> Void
) {
network.execute(request: request) { result in
switch result {
case .success(let data):
Expand All @@ -44,23 +45,23 @@ struct NetworkManager {
}

// GET - 상품 리스트 조회
func request(page: UInt, itemsPerPage: UInt) -> URLRequest? {
func requestListSearch(page: UInt, itemsPerPage: UInt) -> URLRequest? {
guard let url = Address.products(page: page, itemsPerPage: itemsPerPage).url else {
return nil
}
return URLRequest(url: url)
}

// GET - 상품 상세 조회
func request(id: UInt) -> URLRequest? {
func requestDetailSearch(id: UInt) -> URLRequest? {
guard let url = Address.product(id: id).url else {
return nil
}
return URLRequest(url: url)
}

// POST - 상품 삭제 Secret 상세 조회
func request<T: Encodable>(data: T, id: UInt, secret: String) -> Result<URLRequest?, Error> {
func requestSecretSearch<T: Encodable>(data: T, id: UInt, secret: String) -> Result<URLRequest?, Error> {
guard let url = Address.secret(id: id, secret: secret).url else {
return .failure(NetworkError.notFoundURL)
}
Expand All @@ -84,7 +85,7 @@ struct NetworkManager {
}

// DELET - 상품 삭제
func request(id: UInt, secret: String) -> URLRequest? {
func requestDelete(id: UInt, secret: String) -> URLRequest? {
guard let url = Address.delete(id: id, secret: secret).url else {
return nil
}
Expand All @@ -97,7 +98,7 @@ struct NetworkManager {
}

// PATCH - 상품 수정
func request<T: Encodable>(data: T, id: UInt) -> Result<URLRequest?, Error> {
func requestModify<T: Encodable>(data: T, id: UInt) -> Result<URLRequest?, Error> {
guard let url = Address.product(id: id).url else {
return .failure(NetworkError.notFoundURL)
}
Expand All @@ -114,31 +115,36 @@ struct NetworkManager {

request.httpMethod = HTTPMethod.patch.rawValue
request.httpBody = encodeData
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue(ContentType.json.string, forHTTPHeaderField: ContentType.contentType.string)
request.addValue("80c47530-58bb-11ec-bf7f-d188f1cd5f22", forHTTPHeaderField: "identifier")

return .success(request)
}

// POST - 상품 등록
func request<T: MultipartForm>(params: T, images: [ImageFile]) -> Result<URLRequest?, Error> {
func requestRegister<T: MultipartFormProtocol>(params: T, images: [ImageFile]) -> Result<URLRequest?, Error> {
guard let url = Address.register.url else {
return .failure(NetworkError.notFoundURL)
}
let request = multipartFormRequest(url: url, params: params, images: images)
let request = requestMultipartForm(url: url, params: params, images: images)
return .success(request)
}

}

extension NetworkManager {
private func multipartFormRequest<T: MultipartForm>(url: URL, params: T, images: [ImageFile]) -> URLRequest {
private func requestMultipartForm<T: MultipartFormProtocol>(
url: URL,
params: T,
images: [ImageFile]
) -> URLRequest {
let boundary = baseBoundary
let encodeBody = createBody(parameters: params.dictionary, images: images, boundary: boundary)
var request = URLRequest(url: url)

request.httpMethod = HTTPMethod.post.rawValue
request.setValue("multipart/form-data; boundary=\"\(boundary)\"", forHTTPHeaderField: "Content-Type")
request.setValue(ContentType.formData(boundary: boundary).string,
forHTTPHeaderField: ContentType.contentType.string)
request.addValue("80c47530-58bb-11ec-bf7f-d188f1cd5f22", forHTTPHeaderField: "identifier")
request.httpBody = encodeBody

Expand All @@ -149,32 +155,31 @@ extension NetworkManager {
var body = Data()
for (key, value) in parameters {
if let value = value {
body.append(convertedMultiPartForm(name: key, value: value, boundary: boundary))
body.append(jsonMultiPartForm(name: key, value: value, boundary: boundary))
} else {
continue
}
}
for image in images {
body.append(convertedMultiPartForm(image: image, boundary: boundary))
body.append(imageMultiPartForm(image: image, boundary: boundary))
}
return body
}

private func convertedMultiPartForm(name: String, value: Any, boundary: String) -> Data {
private func jsonMultiPartForm(name: String, value: Any, boundary: String) -> Data {
var data = Data()
data.append("--\(boundary)\r\n")
data.append("Content-Disposition: form-data; name=\"\(name)\"\r\n\r\n")
data.append("\(value)\r\n")
data.append(MultipartForm.boundary(baseBoundary: boundary).string)
data.append(MultipartForm.contentDisposition(name: name).string)
data.append(MultipartForm.value(value).string)
return data
}

private func convertedMultiPartForm(image: ImageFile, boundary: String) -> Data {
private func imageMultiPartForm(image: ImageFile, boundary: String) -> Data {
var data = Data()
data.append("--\(boundary)\r\n")
data.append("Content-Disposition: form-data; name=\"images[]\"; filename=\"\(image.name)\"\r\n")
data.append("Content-Type: \(image.type.description)\r\n\r\n")
data.append("\(image.data)\r\n")
data.append(MultipartForm.boundary(baseBoundary: boundary).string)
data.append(MultipartForm.imageContentDisposition(filename: image.name).string)
data.append(MultipartForm.imageContentType(imageType: image.type.description).string)
data.append(MultipartForm.imageValue(data: image.data).string)
return data
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

struct ProductRegistration: Codable, MultipartForm {
struct ProductRegistration: Codable, MultipartFormProtocol {
let name: String
let description: String
let price: Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@

import Foundation

protocol MultipartForm {
protocol MultipartFormProtocol {
var dictionary: [String: Any?] { get }
}
12 changes: 6 additions & 6 deletions OpenMarket/OpenMarketTests/NetworkManagerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class NetworkManagerTests: XCTestCase {
let url = Address.products(page: 1, itemsPerPage: 10).url

//when
let result = sutNetworkManager?.request(page: 1, itemsPerPage: 10)
let result = sutNetworkManager?.requestListSearch(page: 1, itemsPerPage: 10)

//then
XCTAssertNotNil(result)
Expand All @@ -117,7 +117,7 @@ class NetworkManagerTests: XCTestCase {
let url = Address.product(id: 1).url

//when
let result = sutNetworkManager?.request(id: 1)
let result = sutNetworkManager?.requestDetailSearch(id: 1)

//then
XCTAssertNotNil(result)
Expand All @@ -130,7 +130,7 @@ class NetworkManagerTests: XCTestCase {
let url = Address.secret(id: 1, secret: "123").url

//when
let result = sutNetworkManager?.request(data: Data(), id: 1, secret: "123")
let result = sutNetworkManager?.requestSecretSearch(data: Data(), id: 1, secret: "123")

switch result {
case .success(let request):
Expand All @@ -150,7 +150,7 @@ class NetworkManagerTests: XCTestCase {
let url = Address.delete(id: 1, secret: "123").url

//when
let result = sutNetworkManager?.request(id: 1, secret: "123")
let result = sutNetworkManager?.requestDelete(id: 1, secret: "123")

//then
XCTAssertNotNil(result)
Expand All @@ -163,7 +163,7 @@ class NetworkManagerTests: XCTestCase {
let url = Address.product(id: 1).url

//when
let result = sutNetworkManager?.request(data: Data(), id: 1)
let result = sutNetworkManager?.requestModify(data: Data(), id: 1)

switch result {
case .success(let request):
Expand All @@ -184,7 +184,7 @@ class NetworkManagerTests: XCTestCase {
let params = ProductRegistration(name: "", description: "", price: 1, currency: .krw, discountedPrice: nil, stock: nil, secret: "")

//when
let result = sutNetworkManager?.request(params: params, images: [])
let result = sutNetworkManager?.requestRegister(params: params, images: [])

switch result {
case .success(let request):
Expand Down