Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
674 changes: 104 additions & 570 deletions KoreaOneStep.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions KoreaOneStep/Application/Common/DTOModelType.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// DTOModelType.swift
// KoreaOneStep
//
// Created by SUCHAN CHANG on 10/27/24.
//

import Foundation

protocol DTOModelType: Decodable {
associatedtype Response: ResponseType

var response: Response { get }
}

protocol ResponseType: Decodable {
associatedtype Header: HeaderType
associatedtype Body: BodyType

var header: Header { get }
var body: Body { get }
}

protocol HeaderType: Decodable {
var resultCode: String { get }
var resultMsg: String { get }
}

protocol BodyType: Decodable {
associatedtype Items : ItemType

var items: Items { get }
var numOfRows: Int { get }
var pageNo: Int { get }
var totalCount: Int { get }
}

protocol ItemType: Decodable {
associatedtype Item: Decodable

var item: [Item] { get }
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
guard let windowScene = (scene as? UIWindowScene) else { return }

window = UIWindow(windowScene: windowScene)
window?.rootViewController = TabBarViewController()
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
//
// KoreaTravelingAPI.swift
// KoreaTravelingAPI2.swift
// KoreaOneStep
//
// Created by SUCHAN CHANG on 4/1/24.
// Created by SUCHAN CHANG on 10/28/24.
//

import Foundation
import Alamofire
import Moya

enum KoreaTravelingAPI {
static let radiusDefaultValue = FilteringOrder.FilteringDistance.oneKiloMeter.rawValue
static let arrageDefaultValue = FilteringOrder.title.sortingCode
static let contentTypeIdDefaultValue = ""
static let areaCodeDefaultValue = ""
static let sigunguCodeDefaultValue = ""

case providedImpairmentAidServices(contentId: String)
case touristDestionationCommonInformation(
contentId: String,
Expand All @@ -33,34 +27,36 @@ enum KoreaTravelingAPI {
areaCode: String,
sigunguCode: String
)

var baseURL: String {
return "https://apis.data.go.kr/B551011/KorWithService1"
}

extension KoreaTravelingAPI: TargetType {
var baseURL: URL {
return URL(string: APIKeys.baseURL)!
}

var endpoint: String {
var path: String {
switch self {
case .providedImpairmentAidServices:
return "\(baseURL)/detailWithTour1"
return "/detailWithTour1"
case .touristDestionationCommonInformation:
return "\(baseURL)/detailCommon1"
return "/detailCommon1"
case .locationBasedTourismInformation:
return "\(baseURL)/locationBasedList1"
return "/locationBasedList1"
case .areaCode:
return "\(baseURL)/areaCode1"
return "/areaCode1"
case .keywordBasedSearching:
return "\(baseURL)/searchKeyword1"
return "/searchKeyword1"
}
}

var method: HTTPMethod {
var method: Moya.Method {
return .get
}

var parameters: [String: String] {
var task: Moya.Task {
switch self {
case .providedImpairmentAidServices(let contentId):
return [
let parameters: [String: String] = [
"serviceKey": APIKeys.serviceKey, // 필수, 인증키(서비스키)
"numOfRows": "30", // 한페이지결과수
"pageNo": "1", // 페이지번호
Expand All @@ -69,8 +65,9 @@ enum KoreaTravelingAPI {
"contentId": contentId, // 필수, 콘텐츠ID
"_type": "json" // 응답메세지 형식 : REST방식의 URL호출 시 json값 추가(디폴트 응답메세지 형식은XML)
]
return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString)
case .touristDestionationCommonInformation(let contentId, let contentTypeId):
return [
let parameters: [String: String] = [
"serviceKey": APIKeys.serviceKey, // 필수, 인증키(서비스키)
"numOfRows": "30", // 한페이지결과수
"pageNo": "1", // 페이지번호
Expand All @@ -87,8 +84,9 @@ enum KoreaTravelingAPI {
"_type": "json", // 응답메세지 형식 : REST방식의 URL호출 시 json값 추가(디폴트 응답메세지 형식은XML)
"contentTypeId": contentTypeId // 관광타입(관광지, 숙박 등) ID
]
return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString)
case .locationBasedTourismInformation(let latitude, let longitude, let radius, let arrange, let contentTypeId):
return [
let parameters: [String: String] = [
"serviceKey": APIKeys.serviceKey, // 인증키
"numOfRows": "30", // 한페이지 결과수
"pageNo": "1", // 페이지 번호
Expand All @@ -102,8 +100,9 @@ enum KoreaTravelingAPI {
"_type": "json", // 응답메세지 형식 : REST방식의 URL호출 시 json값 추가(디폴트 응답메세지 형식은XML)
"contentTypeId": contentTypeId // 관광타입(12:관광지, 14:문화시설, 15:축제공연행사, 25:여행코스, 28:레포츠, 32:숙박, 38:쇼핑, 39:음식점) ID
]
return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString)
case .areaCode(let areaCode):
return [
let parameters: [String: String] = [
"serviceKey": APIKeys.serviceKey, // 필수, 인증키(서비스키)
"numOfRows": "500", // 한페이지 결과수
"pageNo": "1", // 페이지 번호
Expand All @@ -112,8 +111,9 @@ enum KoreaTravelingAPI {
"_type": "json", // 응답메세지 형식 : REST방식의 URL호출 시 json값 추가(디폴트 응답메세지 형식은XML)
"areaCode": areaCode // 지역코드
]
return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString)
case .keywordBasedSearching(let keyword, let areaCode, let sigunguCode):
return [
let parameters: [String: String] = [
"serviceKey": APIKeys.serviceKey, // 필수, 인증키(서비스키)
"numOfRows": "300", // 한페이지 결과수
"pageNo": "1", // 페이지 번호
Expand All @@ -126,6 +126,11 @@ enum KoreaTravelingAPI {
"areaCode": areaCode, // 지역코드
"sigunguCode": sigunguCode // 시군구 코드(지역코드 필수)
]
return .requestParameters(parameters: parameters, encoding: URLEncoding.queryString)
}
}

var headers: [String : String]? {
return ["Content-Type": "application/json"]
}
}
40 changes: 40 additions & 0 deletions KoreaOneStep/Data/Network/NetworkManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// NetworkManager2.swift
// KoreaOneStep
//
// Created by SUCHAN CHANG on 10/28/24.
//

import Foundation
import Moya
import RxSwift

protocol NetworkManagerProtocl {
func request(_ target: KoreaTravelingAPI) -> Single<Response>
}

final class NetworkManager: NetworkManagerProtocl {
private let provider: MoyaProvider<KoreaTravelingAPI>

init() {
provider = MoyaProvider<KoreaTravelingAPI>()
}

func request(_ target: KoreaTravelingAPI) -> Single<Response> {
return Single<Response>.create { [weak self] singleObserver in
guard let self else { return Disposables.create() }

provider.request(target) { result in
switch result {
case .success(let response):
singleObserver(.success(response))
case .failure(let moyaError):
print(moyaError)
// TODO: - 네트워크 오류 처리하기
// singleObserver(.failure(moyaError))
}
}
return Disposables.create()
}
}
}
61 changes: 61 additions & 0 deletions KoreaOneStep/Data/Repository/KoreaTravelingRepository.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// KoreaTravelingRepository2.swift
// KoreaOneStep
//
// Created by SUCHAN CHANG on 10/28/24.
//

import Foundation
import RxMoya
import RxSwift

protocol KoreaTravelingRepositoryProtocol {
func fetchProvidedImpairmentAidServices(api: KoreaTravelingAPI) -> Single<IASItem>
func fetchTouristDestionationCommonInformation(api: KoreaTravelingAPI) -> Single<CIItem>
func fetchLocationBasedTourismInformation(api: KoreaTravelingAPI) -> Single<[LBItem]>
func fetchAreaCode(api: KoreaTravelingAPI) -> Single<[ACItem]>
func fetchKeywordBasedSearching(api: KoreaTravelingAPI) -> Single<[KSItem]>
}

final class KoreaTravelingRepository: KoreaTravelingRepositoryProtocol {
private let network: NetworkManagerProtocl

init(network: NetworkManagerProtocl) {
self.network = network
}

func fetchProvidedImpairmentAidServices(api: KoreaTravelingAPI) -> Single<IASItem> {
network
.request(api)
.map(ProvidedImpairmentAidServicesDTO.self)
.map { $0.response.body.items.item[0] }
}

func fetchTouristDestionationCommonInformation(api: KoreaTravelingAPI) -> Single<CIItem> {
network
.request(api)
.map(TouristDestionationCommonInformationDTO.self)
.map { $0.response.body.items.item[0] }
}

func fetchLocationBasedTourismInformation(api: KoreaTravelingAPI) -> Single<[LBItem]> {
network
.request(api)
.map(LocationBasedTourismInformationDTO.self)
.map { $0.response.body.items.item }
}

func fetchAreaCode(api: KoreaTravelingAPI) -> Single<[ACItem]> {
network
.request(api)
.map(AreaCodeDTO.self)
.map { $0.response.body.items.item }
}

func fetchKeywordBasedSearching(api: KoreaTravelingAPI) -> Single<[KSItem]> {
network
.request(api)
.map(KeywordBasedSearchingDTO.self)
.map { $0.response.body.items.item }
}
}
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
//
// AreaCodeModel.swift
// AreaCodeDTO.swift
// KoreaOneStep
//
// Created by SUCHAN CHANG on 3/18/24.
// Created by SUCHAN CHANG on 10/27/24.
//

import Foundation

struct AreaCodeModel: Decodable {
struct AreaCodeDTO: DTOModelType {
let response: ACResponse
}

struct ACResponse: Decodable {
struct ACResponse: ResponseType {
let header: ACHeader
let body: ACBody
}

struct ACHeader: Decodable {
struct ACHeader: HeaderType {
let resultCode: String
let resultMsg: String
}

struct ACBody: Decodable {
struct ACBody: BodyType {
let items: ACItems
let numOfRows: Int
let pageNo: Int
let totalCount: Int
}

struct ACItems: Decodable {
struct ACItems: ItemType {
let item: [ACItem]
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
//
// KeywordBasedSearchgingModel.swift
// KeywordBasedSearchingDTO.swift
// KoreaOneStep
//
// Created by SUCHAN CHANG on 3/19/24.
// Created by SUCHAN CHANG on 10/27/24.
//

import Foundation

struct KeywordBasedSearchgingModel: Decodable {
struct KeywordBasedSearchingDTO: DTOModelType {
let response: KSResponse
}

struct KSResponse: Decodable {
struct KSResponse: ResponseType {
let header: KSHeader
let body: KSBody
}

struct KSHeader: Decodable {
struct KSHeader: HeaderType {
let resultCode: String
let resultMsg: String
}

struct KSBody: Decodable {
struct KSBody: BodyType {
let items: KSItems
let numOfRows: Int
let pageNo: Int
let totalCount: Int
}

struct KSItems: Decodable {
struct KSItems: ItemType {
let item: [KSItem]
}

// TODO: - 모델 공통부분 통합 처리
struct KSItem: Decodable {
let addr1: String // 주소
let addr2: String // 상세주소
Expand Down
Loading