-
Notifications
You must be signed in to change notification settings - Fork 26
AI 챗봇 앱 [Step 1&2] 이안, 홍 #47
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
base: d_Hong
Are you sure you want to change the base?
Conversation
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.
수고하셨습니다! 질문 주신 것들은 코멘트에 직접 답변 드렸습니다..!
| guard let _ = (scene as? UIWindowScene) else { return } | ||
| guard let windowScene = (scene as? UIWindowScene) else { return } | ||
|
|
||
| // TODO: - rootViewController 설정 |
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.
이후 스텝에서 구현하실 예정인거죠??👍
|
|
||
| import UIKit | ||
|
|
||
| class ViewController: UIViewController { |
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.
조금 더 구체적인 이름을 지어주는건 어떨까요??
|
|
||
| class ViewController: UIViewController { | ||
|
|
||
| var networkManger = NetworkManger() |
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.
networkManager를 ViewController에게 주입 시키는 방법은 어떨까요? (init 을 통해서)
이렇게 하는것을 의존성 주입이라고 부르는데, 의존성 주입의 장점에 대해서 알고 계실까요?!
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.
var 인 이유가 있을까요?!
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.
networkManger 오타가 있는것 같네요ㅎㅎ
|
|
||
| struct ChatRequest: Codable { | ||
| var model: String = "gpt-3.5-turbo-1106" | ||
| var isFalse: Bool = false |
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.
isFalse 는 뭐가 false 인걸까요??🤔 변수명에 표현이 되면 좋을것 같아요!
| struct ChatResponse: Codable { | ||
| let id: String | ||
| let object: String | ||
| let created: Int |
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.
createdAt 같은 네이밍은 어떠신가요??ㅎ
| request.allHTTPHeaderFields = header | ||
| request.setValue("application/json", forHTTPHeaderField: "Content-Type") | ||
|
|
||
| let bodyData = ChatRequest(messages: [.init(role: "system", content: "어렵다"),Message(role: "user", content: "swift언어 설명해줘 ")]) |
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.
지금 리퀘스트 bodyData의 타입을 이렇게 NetworkManager.urlRequest() 메서드 안에서 직접 의존하도록 구현을 하셨는데
이렇게하면 문제점이 뭘까요??🤔
Hint: 다른 API 통신이 추가되는 경우?!
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.
messages에 들어가는 배열에 첫번째는 .init 으로 생성을하고 두번째는 Message로 직접 생성을 하셨는데 차이를 두신 이유가 있을까요?!
| var OPENAI_API_KEY: String { | ||
| guard let file = self.path(forResource: "Api_Key", ofType: "plist") else { return "" } | ||
|
|
||
| // .plist를 딕셔너리로 받아오기 | ||
| guard let resource = NSDictionary(contentsOfFile: file) else { return "" } | ||
|
|
||
| // 딕셔너리에서 값 찾기 | ||
| guard let key = resource["myApiKey"] as? String else { | ||
| fatalError("API_KEY error") | ||
| } | ||
| return key | ||
| } |
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.
오 API Key 를 숨기는 고민을 이렇게 하신거군요?! 저는 이런거 고민 사실 제대로 안해본거 같은데 아주 멋집니다!
추가로 고민하신 방법도 있을까요?? (개인적으로 궁금해서요!)
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.
개인적인 생각으로는, 진짜 숨겨야하는 API Key가 있다면
이건 결국 서버에 도움이 필요하지 않을까 싶네요..?🤔 물론 다른 방법도 있을 수는 있겠지만
가장 안전한 방법은 서버로부터 (당연히 지금 사용하는 API 를 제공하는 서버 외의 다른 서버 겠죠 ?ㅎㅎ)
API Key를 제공 받아서, Keychain에 저장하는게 안전하지 않을까 싶습니다..! (개인적인 생각)
|
|
||
| import Foundation | ||
|
|
||
| extension Bundle { |
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.
이게 Bundle 익스텐션으로 들어가게 된 이유가 있나요? (그냥 개인적으로 궁금해서요! )
| networkManger.urlDataTaks { result in | ||
| switch result { | ||
| case .success(let data): | ||
| let decodedResult: Result<ChatResponse, NetworkError> = self.networkManger.DecodedData(data: data) | ||
| switch decodedResult { |
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.
요거 코멘트로 질문 주신 내용 같네요!
switch 문을 중첩으로 안하는 방법을 여쭤보신것 같은데
지금 urlDataTaks (오타가 있는것 같네요 ! ㅎㅎ) 의 completion으로 Result 타입을 받아서, success 일때 또 self.networkManager.decodedData()를 호출하고 있네요!
개인적으로 요런 방법들이 생각나네요!
- 그냥 두개의 메서드를 networkManager에서 다 알아서 decoding 까지 해서 ViewController에게 결과를 전달한다.
- decoding 하는 부분은 별도의 메서드로 분리한다.
| request.httpBody = body | ||
|
|
||
| return request | ||
|
|
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.
리턴 다음에 줄바꿈 추가하는건 컨벤션일까요? 아니라면 제거하면 좋을것 같아요!
리뷰어:
@junbangg
버드:
@ujhong7
@ianK0909
안녕하세요! AI 챗봇 앱 프로젝트를 함께하게된 홍, 이안입니다.
잘부탁드립니다😊
구현한 코드
Open API 사용하기 위해 필요한 요청 객체, 응답 데이터 타입을 구현하고 네트워킹 요청을 하기위해 URLSession을 이용하여 메시지를 전송하고 , 응답처리를 구현 하였습니다.
API Key가 공개되어있어서 숨기는것도 구현해봤습니다.
구현하면서 궁금한점