Skip to content

Conversation

@ujhong7
Copy link

@ujhong7 ujhong7 commented Apr 11, 2024

리뷰어:
@junbangg

버드:
@ujhong7
@ianK0909

안녕하세요! AI 챗봇 앱 프로젝트를 함께하게된 홍, 이안입니다.
잘부탁드립니다😊

구현한 코드
Open API 사용하기 위해 필요한 요청 객체, 응답 데이터 타입을 구현하고 네트워킹 요청을 하기위해 URLSession을 이용하여 메시지를 전송하고 , 응답처리를 구현 하였습니다.

API Key가 공개되어있어서 숨기는것도 구현해봤습니다.

구현하면서 궁금한점

  • API Key를 숨기는방법을 찾아서 따라해봤는데 보통 어느방법으로 많이하는지 궁금합니다.
  • 아래코드와 같이 Switch문 이중으로 사용하였는데 혹시 다르게 구현하는방법이 있을까요?
 networkManger.urlDataTaks { result in
            switch result {
            case .success(let data):
                let decodedResult: Result<ChatResponse, NetworkError> = self.networkManger.DecodedData(data: data)
                switch decodedResult {
                case .success(let decodedData):
                    print("Decoded data:", decodedData)
                case .failure(let error):
                    print("Decoding failed with error:", error.localizedDescription)
                }
            case .failure(let error):
                print("Error:", error.localizedDescription)
            }
        }

Copy link
Contributor

@junbangg junbangg left a 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 설정
Copy link
Contributor

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 {
Copy link
Contributor

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()
Copy link
Contributor

Choose a reason for hiding this comment

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

networkManager를 ViewController에게 주입 시키는 방법은 어떨까요? (init 을 통해서)
이렇게 하는것을 의존성 주입이라고 부르는데, 의존성 주입의 장점에 대해서 알고 계실까요?!

Copy link
Contributor

Choose a reason for hiding this comment

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

var 인 이유가 있을까요?!

Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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언어 설명해줘 ")])
Copy link
Contributor

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 통신이 추가되는 경우?!

Copy link
Contributor

Choose a reason for hiding this comment

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

messages에 들어가는 배열에 첫번째는 .init 으로 생성을하고 두번째는 Message로 직접 생성을 하셨는데 차이를 두신 이유가 있을까요?!

Comment on lines +7 to +18
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
}
Copy link
Contributor

Choose a reason for hiding this comment

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

오 API Key 를 숨기는 고민을 이렇게 하신거군요?! 저는 이런거 고민 사실 제대로 안해본거 같은데 아주 멋집니다!
추가로 고민하신 방법도 있을까요?? (개인적으로 궁금해서요!)

Copy link
Contributor

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 {
Copy link
Contributor

Choose a reason for hiding this comment

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

이게 Bundle 익스텐션으로 들어가게 된 이유가 있나요? (그냥 개인적으로 궁금해서요! )

Comment on lines +21 to +25
networkManger.urlDataTaks { result in
switch result {
case .success(let data):
let decodedResult: Result<ChatResponse, NetworkError> = self.networkManger.DecodedData(data: data)
switch decodedResult {
Copy link
Contributor

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()를 호출하고 있네요!

개인적으로 요런 방법들이 생각나네요!

  1. 그냥 두개의 메서드를 networkManager에서 다 알아서 decoding 까지 해서 ViewController에게 결과를 전달한다.
  2. decoding 하는 부분은 별도의 메서드로 분리한다.

request.httpBody = body

return request

Copy link
Contributor

Choose a reason for hiding this comment

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

리턴 다음에 줄바꿈 추가하는건 컨벤션일까요? 아니라면 제거하면 좋을것 같아요!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants