-
Notifications
You must be signed in to change notification settings - Fork 26
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
AI 챗봇 앱 [STEP 2] 토미, 이지 #42
base: d_Easy
Are you sure you want to change the base?
Changes from all commits
9e888d0
d526d02
70c7a81
7a1f1ad
da4153d
1fcfe85
c48cf43
4b7736b
1ab9a9c
e703a3d
cdd02f7
f739150
ac01d9e
b4a5bdc
d58b3f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// | ||
// APIClient.swift | ||
// ChatBot | ||
// | ||
// Created by nayeon on 4/3/24. | ||
// | ||
|
||
import Alamofire | ||
|
||
enum APIClient { | ||
|
||
static func request<T: Decodable>(_ object: T.Type, | ||
router: URLRequestConvertible, | ||
completion: @escaping (NetworkResult<T>) -> Void) { | ||
AF.request(router) | ||
.validate(statusCode: 200..<500) | ||
.responseDecodable(of: object) { response in | ||
switch response.result { | ||
case .success(let decodedData): | ||
completion(.success(decodedData)) | ||
case .failure(let error): | ||
var errorMessage: String? | ||
if let data = response.data, let message = String(data: data, encoding: .utf8) { | ||
errorMessage = message | ||
} | ||
|
||
if let statusCode = response.response?.statusCode { | ||
switch statusCode { | ||
case 400...499: | ||
completion(.failure(.pathError(message: errorMessage))) | ||
case 500...599: | ||
completion(.failure(.serverError(message: errorMessage ?? "server error"))) | ||
default: | ||
completion(.failure(.networkFail)) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// | ||
// APIConstants.swift | ||
// ChatBot | ||
// | ||
// Created by nayeon on 4/3/24. | ||
// | ||
|
||
import Foundation | ||
|
||
enum APIConstants { | ||
static let baseURL = "https://api.openai.com" | ||
} | ||
|
||
enum HTTPHeaderField: String { | ||
case authentication = "Authorization" | ||
case contentType = "Content-Type" | ||
} | ||
|
||
enum ContentType: String { | ||
case json = "application/json" | ||
} | ||
Comment on lines
+14
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. HTTPHeaderField, ContentType도 사용하는 방법을 보니 API요청시 필요한 기본 세팅 문자열을 다루고 있네요. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. API 요청에서 반복적으로 사용되는 HTTP 헤더 필드와 콘텐츠 타입을 정의함으로써 모듈화와 코드의 가독성을 높였습니다. 하드코딩하는 대신 의미 있는 이름을 사용할 수 있고, API 요청에 필요한 기본 세팅이 변경될 경우, 해당 세팅을 열거형의 값만 수정하여 유지보수를 쉽게 할 수 있습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 애플에서는 기본적으로 특별한 이유가 없다면
열거형도 값 타입으로서 struct를 사용 할 때와 같은 기준으로 사용하지만 연관된 값들을 그룹화하여 표현하는 데 유리한 점이 있기 때문에 선택지를 제한하거나 관련된 값들을 묶어서 사용할 때 선택합니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 먼저 공통으로 사용되는 값들을 이렇게 분리해서 별도로 선언하여 재사용할 수 있게 구현하신 것은 좋은 방법이라고 생각합니다.
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// | ||
// APIRouter.swift | ||
// ChatBot | ||
// | ||
// Created by nayeon on 4/3/24. | ||
// | ||
|
||
import Alamofire | ||
|
||
enum APIRouter: NetworkRouter, URLRequestConvertible { | ||
case chatCompletion(requestDTO: RequestDTO) | ||
|
||
var baseURL: String { | ||
return APIConstants.baseURL | ||
} | ||
|
||
var path: String { | ||
switch self { | ||
case .chatCompletion: | ||
return "/v1/chat/completions" | ||
} | ||
} | ||
|
||
var method: HTTPMethod { | ||
switch self { | ||
case .chatCompletion: | ||
return .post | ||
} | ||
} | ||
|
||
var headers: [String: String] { | ||
return [ | ||
HTTPHeaderField.contentType.rawValue: ContentType.json.rawValue, | ||
HTTPHeaderField.authentication.rawValue: "Bearer \(AppConfig.openAIAPIKey)" | ||
] | ||
} | ||
|
||
var parameters: [String: Any]? { | ||
switch self { | ||
case .chatCompletion(let requestDTO): | ||
return requestDTO.dictionaryRepresentation() | ||
} | ||
} | ||
|
||
var encoding: ParameterEncoding { | ||
switch self { | ||
case .chatCompletion: | ||
return JSONEncoding.default | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// | ||
// NetworkResult.swift | ||
// ChatBot | ||
// | ||
// Created by nayeon on 4/3/24. | ||
// | ||
|
||
enum NetworkResult<T> { | ||
case success(T) | ||
case failure(NetworkError) | ||
} | ||
|
||
enum NetworkError: Error { | ||
case pathError(message: String?) | ||
case serverError(message: String?) | ||
case networkFail | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
현재 빌드가 정상적으로 되지 않아요.
혹시 이 파일을 gitignore에 추가하신 이유가 있으실까요??
여러분들의 로컬에 있는 프로젝트를 삭제한 이후에 다시 클론을 받아서 빌드를 진행해보시면 좋을 것 같아요.
gitignore에 추가한 파일이 어떤파일인지 어떤 역할을 하는 파일인지 알아보시면 좋을 것 같아요.
그리고 이 문제를 어떻게 해결할 수 있을지도 확인해보세요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
xcconfig란?
Xcode 프로젝트의 빌드 설정을 외부화하여 관리할 수 있게 해주는 파일입니다.
.xcconfig 확장자로 저장되며, 이를 사용하면 빌드 설정을 코드로 관리할 수 있어 복잡한 프로젝트에서 빌드 설정을 좀 더 쉽게 관리할 수 있습니다.
api key를 git에 노출시키지 않도록 하기 위해서 추가하였습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
의도는 이해했습니다.
그렇지만 git을 통해서 pull을 받았을때 정상 빌드가 되지 않고 xcconfig를 사용하지 않고 빌드하는 경우 api key가 없어 API요청에 실패하게 되어있습니다.
데이터의 보안에 관련해서는 어떻게 처리하면 좋을지 추후에 조금 더 알아보시고 이번에는 추가해주시면 좋을 것 같네요 ㅎㅎ