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 36 commits
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
21 changes: 21 additions & 0 deletions OpenMarket/.swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
included:
- OpenMarket # 프로젝트 이름
excluded: # 린트 과정에서 무시할 파일 경로. `included`보다 우선순위 높음
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pods도 보통 excluded 처리해주곤 합니다~!
나중에 외부 라이브러리들을 사용할때 한번 해보세요ㅎㅎ

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오! 맞아요! 그렇더라구요! 외부라이브러리를 쓰게되면 꼭 활용해보겠습니다!

- OpenMarket/AppDelegate.swift
- OpenMarket/SceneDelegate.swift
identifier_name:
min_length:
- 2 # only min_length
error: 4 # only error
leeari95 marked this conversation as resolved.
Show resolved Hide resolved
excluded: # 제외할 문자열 목록 사용
- id
leeari95 marked this conversation as resolved.
Show resolved Hide resolved
- URL
- url
- GlobalAPIKey
disabled_rules: # 실행에서 제외할 룰 식별자들
- colon
- control_statement
- trailing_whitespace
- vertical_parameter_alignment
opt_in_rules: # 일부 룰은 옵트 인 형태로 제공
- empty_count
Comment on lines +1 to +21
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호 SwiftLint를 써보셨군요!👍👍
저는 현업에서 두가지를 혼합해서 사용하고 있는데 하나가 바로 SwiftFormat입니다!
Apple에서 만들었기에 한번 보시면 좋을것 같아요🙌
https://github.com/apple/swift-format

345 changes: 342 additions & 3 deletions OpenMarket/OpenMarket.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"data" : [
{
"filename" : "product.json",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
28 changes: 28 additions & 0 deletions OpenMarket/OpenMarket/Assets.xcassets/product.dataset/product.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"id": 16,
"vendor_id": 2,
"name": "팥빙수",
"thumbnail": "https://s3.ap-northeast-2.amazonaws.com/media.yagom-academy.kr/training-resources/2/thumb/8279f1c16c6111ecbf33d51698ab7ead.png",
leeari95 marked this conversation as resolved.
Show resolved Hide resolved
"currency": "KRW",
"price": 2000.0,
"bargain_price": 2000.0,
"discounted_price": 0.0,
"stock": 0,
"created_at": "2022-01-03 00:00:00.000",
"issued_at": "2022-01-03 00:00:00.000",
"images": [
{
"id": 7,
"url": "https://s3.ap-northeast-2.amazonaws.com/media.yagom-academy.kr/training-resources/2/origin/8279f1c16c6111ecbf33d51698ab7ead.png",
"thumbnail_url": "https://s3.ap-northeast-2.amazonaws.com/media.yagom-academy.kr/training-resources/2/thumb/8279f1c16c6111ecbf33d51698ab7ead.png",
"succeed": true,
"issued_at": "2022-01-03 00:00:00.000"
}
],
"vendors": {
"name": "dacodaco",
"id": 2,
"created_at": "2021-12-26 00:00:00.000",
"issued_at": "2021-12-26 00:00:00.000"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"data" : [
{
"filename" : "products.json",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"page_no": 1,
"items_per_page": 20,
"total_count": 5,
"offset": 0,
"limit": 20,
"pages": [
{
"id": 15,
"vendor_id": 3,
"name": "pizza",
"thumbnail": "https://s3.ap-northeast-2.amazonaws.com/media.yagom-academy.kr/training-resources/3/thumb/f510cb6e689f11ecbf33d124b2c61dc4.jpg",
"currency": "KRW",
"price": 25000,
"bargain_price": 25000,
"discounted_price": 0,
"stock": 0,
"created_at": "2021-12-29 00:00:00.000",
"issued_at": "2021-12-29 00:00:00.000"
},
{
"id": 13,
"vendor_id": 2,
"name": "팥빙수",
"thumbnail": "https://s3.ap-northeast-2.amazonaws.com/media.yagom-academy.kr/training-resources/2/thumb/f70ad56a689911ecbf33f11af721febf.png",
"currency": "KRW",
"price": 2000,
"bargain_price": 2000,
"discounted_price": 0,
"stock": 0,
"created_at": "2021-12-29 00:00:00.000",
"issued_at": "2021-12-29 00:00:00.000"
},
{
"id": 4,
"vendor_id": 3,
"name": "Test Product",
"thumbnail": "https://s3.ap-northeast-2.amazonaws.com/media.yagom-academy.kr/training-resources/3/thumb/87aa7c8966df11ecad1df993f20d4a2a.jpg",
"currency": "KRW",
"price": 1000,
"bargain_price": 900,
"discounted_price": 100,
"stock": 0,
"created_at": "2021-12-27 00:00:00.000",
"issued_at": "2021-12-27 00:00:00.000"
},
{
"id": 3,
"vendor_id": 3,
"name": "Test Product",
"thumbnail": "https://s3.ap-northeast-2.amazonaws.com/media.yagom-academy.kr/training-resources/3/thumb/2f6021a066dc11ec9626955448777bf5.jpg",
"currency": "KRW",
"price": 1000,
"bargain_price": 1000,
"discounted_price": 0,
"stock": 0,
"created_at": "2021-12-27 00:00:00.000",
"issued_at": "2021-12-27 00:00:00.000"
},
{
"id": 2,
"vendor_id": 2,
"name": "팥빙수",
"thumbnail": "https://s3.ap-northeast-2.amazonaws.com/media.yagom-academy.kr/training-resources/2/thumb/a3257844661911ec8eff5b6e36134cb4.png",
"currency": "KRW",
"price": 2000,
"bargain_price": 2000,
"discounted_price": 0,
"stock": 0,
"created_at": "2021-12-26 00:00:00.000",
"issued_at": "2021-12-26 00:00:00.000"
}
],
"last_page": 1,
"has_next": false,
"has_prev": false
}
18 changes: 13 additions & 5 deletions OpenMarket/OpenMarket/Base.lproj/LaunchScreen.storyboard
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
Expand All @@ -11,15 +14,20 @@
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,4 @@ class ViewController: UIViewController {
super.viewDidLoad()
// Do any additional setup after loading the view.
}


}

25 changes: 25 additions & 0 deletions OpenMarket/OpenMarket/Error/NetworkError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// NetworkError.swift
// OpenMarket
//
// Created by 이호영 on 2022/01/04.
//

import Foundation

enum NetworkError: LocalizedError {
case responseCasting
leeari95 marked this conversation as resolved.
Show resolved Hide resolved
case statusCode(Int)
case notFoundURL

var errorDescription: String {
switch self {
case .responseCasting:
return "캐스팅에 실패하였습니다."
case .statusCode(let code):
return "상태 코드 에러 : \(code)"
case .notFoundURL:
return "URL을 찾을 수 없습니다."
}
}
}
25 changes: 25 additions & 0 deletions OpenMarket/OpenMarket/Error/ParserError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// ParserError.swift
// OpenMarket
//
// Created by Ari on 2022/01/03.
//

import Foundation

enum ParserError: LocalizedError {
case assestNotfound
leeari95 marked this conversation as resolved.
Show resolved Hide resolved
case decoding
case encoding
leeari95 marked this conversation as resolved.
Show resolved Hide resolved

var errorDescription: String {
switch self {
case .assestNotfound:
return "에셋 데이터를 찾을 수 없습니다."
case .decoding:
return "디코딩을 하는 도중 에러가 발생했습니다."
case .encoding:
return "인코딩을 하는 도중 에러가 발생했습니다."
}
}
leeari95 marked this conversation as resolved.
Show resolved Hide resolved
}
17 changes: 17 additions & 0 deletions OpenMarket/OpenMarket/Extension/Data+extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Data+extension.swift
// OpenMarket
//
// Created by 이호영 on 2022/01/04.
//

import Foundation

extension Data {
mutating func append(_ string: String) {
guard let data = string.data(using: .utf8) else {
return
}
self.append(data)
}
}
leeari95 marked this conversation as resolved.
Show resolved Hide resolved
32 changes: 32 additions & 0 deletions OpenMarket/OpenMarket/Model/Network/Address.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// NetworkConstant.swift
// OpenMarket
//
// Created by Ari on 2022/01/04.
//

import Foundation

enum Address {
static let baseURL = "https://market-training.yagom-academy.kr/api/products"
case products(page: UInt, itemsPerPage: UInt)
case product(id: UInt)
case register
case secret(id: UInt, secret: String)
case delete(id: UInt, secret: String)

var url: URL? {
switch self {
case .products(let page, let itemsPerPage):
return URL(string: Address.baseURL + "?page-no=\(page)" + "&items-per-page=\(itemsPerPage)")
case .product(let id):
return URL(string: Address.baseURL + "/\(id)")
case .register:
return URL(string: Address.baseURL)
case .secret(let id, let secret):
return URL(string: Address.baseURL + "/\(id)" + "/\(secret)")
case .delete(let id, let secret):
return URL(string: Address.baseURL + "/\(id)" + "/\(secret)")
}
}
}
leeari95 marked this conversation as resolved.
Show resolved Hide resolved
15 changes: 15 additions & 0 deletions OpenMarket/OpenMarket/Model/Network/HTTPMethod.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// HTTPMethod.swift
// OpenMarket
//
// Created by Ari on 2022/01/06.
//

import Foundation

enum HTTPMethod: String {
case get = "GET"
case post = "POST"
case patch = "PATCH"
case delete = "DELETE"
}
leeari95 marked this conversation as resolved.
Show resolved Hide resolved
35 changes: 35 additions & 0 deletions OpenMarket/OpenMarket/Model/Network/Network.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Network.swift
// OpenMarket
//
// Created by 이호영 on 2022/01/04.
//

import Foundation

final class Network: Networkable {
let session: URLSession
leeari95 marked this conversation as resolved.
Show resolved Hide resolved

init(session: URLSession = .shared) {
self.session = session
}
leeari95 marked this conversation as resolved.
Show resolved Hide resolved

func execute(request: URLRequest, completion: @escaping (Result<Data?, Error>) -> Void) {
leeari95 marked this conversation as resolved.
Show resolved Hide resolved
session.dataTask(with: request) { data, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let response = response as? HTTPURLResponse else {
completion(.failure(NetworkError.responseCasting))
return
}
guard (200...299).contains(response.statusCode) else {
completion(.failure(NetworkError.statusCode(response.statusCode)))
return
}
completion(.success(data))
}.resume()
}

}
Loading