사용자가 공유한 콘텐츠
-
💡이 글은 corca의 LLM프로덕트 dev.post 가 생성한 글입니다🤖
## ViewModel에 맞는 UI 코드를 OpenAI API로 자동 작성하기
여러분, SwiftUI를 사용하면서 UI 코드를 작성하는 과정에서 번거로움을 느낀 적 있으신가요? 만약, ViewModel에 따라 자동으로 UI를 생성해주는 앱이 있다면 얼마나 편리할까요? 오늘은 그런 놀라운 앱을 만드는 과정을 함께 알아보겠습니다!
이 프로젝트의 목표는 이미지를 입력했을 때, 그에 맞는 UI 코드를 자동으로 작성해주는 앱입니다. 이를 위해 OpenAI API를 활용하여 이미지를 기반으로 얻은 데이터를 바탕으로 SwiftUI 코드를 생성합니다. 프로젝트의 전체적인 구조와 중요한 코드 부분을 함께 살펴보겠습니다.
### ViewModel에 맞게 UI 짜기
SwiftUI에서 ViewModel을 사용하면 데이터와 UI 로직을 분리하여 더욱 깔끔한 코드를 작성할 수 있습니다. 프로젝트에는 ImageLoadViewModel
이라는 ViewModel이 있습니다. 이 ViewModel은 이미지를 분석하고, 분석 결과를 UI에 반영하는 역할을 합니다.
#### ImageLoadViewModel
코드 설명
먼저, ImageLoadViewModel
의 중요한 부분을 살펴보겠습니다:
```swift
class ImageLoadViewModel: ObservableObject {
enum ViewState {
case load, loaded, analysis, content, completed, error
}
@Published var message: String = ""
@Published var viewState: ViewState = .load
private var apiController: APIController
private var cancellables = Set<AnyCancellable>()
init(apiController: APIController = APIController()) {
self.apiController = apiController
}
func analyze(base64Image: String, userContent: String) {
viewState = .analysis
apiController.makeRequest(base64Image: base64Image, userContent: userContent)
.sink { completion in
switch completion {
case .failure(let error):
print(error)
self.viewState = .error
case .finished: break
}
} receiveValue: { response in
self.message = response.message
self.viewState = .completed
}
.store(in: &cancellables)
}
}
```
#### 주요 구성 요소 설명
- **`ViewState` 열거형**: 각기 다른 UI 상태를 표현합니다. (`load`, loaded
, analysis
, content
, completed
, error
)
- **`@Published var message`**: 분석 결과 메시지를 저장합니다.
- **`@Published var viewState`**: 현재 상태를 저장하고, 상태가 바뀔 때마다 UI가 업데이트됩니다.
- **`apiController`**: OpenAI API와 통신하는 컨트롤러.
- **`analyze` 함수**: 이미지를 분석하고 결과를 처리합니다.
### OpenAI API와의 통신
이제 OpenAI API와 통신하는 부분을 살펴보겠습니다. 이 부분에서는 Alamofire를 사용하여 네트워크 요청을 처리합니다.
```swift
class APIController {
let baseURL = "https://api.openai.com/v1/whatever"
func makeRequest(base64Image: String, userContent: String) -> AnyPublisher<Response, Error> {
let payload = Payload(model: "gpt-3.5-turbo", messages: [Message(content: userContent, imageURL: base64Image)])
let headers: HTTPHeaders = [
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_OPENAI_API_KEY"
]
return AF.request(baseURL, method: .post, parameters: payload, encoder: JSONParameterEncoder.default, headers: headers)
.validate()
.publishDecodable(type: Response.self)
.tryCompactMap { $0.value }
.eraseToAnyPublisher()
}
}
```
#### 주요 구성 요소 설명
- **`baseURL`**: OpenAI API 엔드포인트 URL.
- **`makeRequest` 함수**: API 요청을 생성하고 결과를 AnyPublisher
형식으로 반환합니다.
- **`Alamofire`**: HTTP 네트워크 요청을 관리하는 라이브러리로, AF
라는 줄임말로 사용됩니다.
### ImageLoadView UI 구현하기
이제 ViewModel을 활용하여 실제 UI를 구성하는 방법을 살펴보겠습니다. ImageLoadView
는 여러 상태에 따라 다른 UI를 보여줍니다.
```swift
struct ImageLoadView: View {
@State private var userInput: String = ""
@State private var selectedImage: Image?
@State private var selectedItem: PhotosPickerItem?
@StateObject private var viewModel = ImageLoadViewModel()
var body: some View {
VStack {
if viewModel.viewState == .load {
PhotosPicker("이미지 선택", selection: $selectedItem)
.onChange(of: selectedItem) { newItem in
Task {
if let data = try? await newItem?.loadTransferable(type: Data.self),
let uiImage = UIImage(data: data) {
selectedImage = Image(uiImage: uiImage)
viewModel.viewState = .loaded
}
}
}
.padding()
} else if viewModel.viewState == .loaded {
VStack {
selectedImage?
.resizable()
.scaledToFit()
.frame(width: 300, height: 300)
TextField("요청할 내용을 입력하세요", text: $userInput)
.padding()
.textFieldStyle(RoundedBorderTextFieldStyle())
Button("분석 요청") {
if let selectedImage = selectedImage {
// UIImage to base64
let base64Image = imageToBase64(image: selectedImage)
viewModel.analyze(base64Image: base64Image, userContent: userInput)
}
}
.padding()
}
} else if viewModel.viewState == .analysis {
ProgressView("분석 중...")
.progressViewStyle(CircularProgressViewStyle())
.padding()
} else if viewModel.viewState == .completed {
Text(viewModel.message)
.padding()
} else if viewModel.viewState == .error {
Text("에러가 발생했습니다.")
.foregroundColor(.red)
.padding()
}
}
}
private func imageToBase64(image: Image) -> String {
// Image를 Base64로 변환하는 로직
}
}
```
#### 주요 구성 요소 설명
- **`PhotosPicker`**: 이미지를 선택할 수 있는 상호작용 요소.
- **`@StateObject`와 @State
**: SwiftUI의 상태 관리를 위한 property wrappers.
- **`VStack`, TextField
, Button
**: 다양한 UI 컴포넌트들을 배치하는 데 사용됩니다.
- **상태에 따른 UI 변화**: viewState
에 따라 다른 UI가 렌더링됩니다.
### 결론
오늘은 ViewModel을 기반으로 UI 코드를 자동으로 생성해주는 앱을 만드는 과정을 살펴봤습니다. OpenAI API를 활용하여 이미지를 분석하고, 그 결과를 UI에 반영하는 방법을 배웠습니다. 이렇게 하면 보다 효율적으로 UI 코드를 작성할 수 있으며, 코드를 더욱 깔끔하게 유지할 수 있습니다. SwiftUI와 OpenAI API를 함께 활용해 보세요!
이 글이 도움이 되었기를 바랍니다. 궁금한 점이나 피드백이 있다면 언제든지 댓글로 남겨주세요. 감사합니다! 😊
다음 내용이 궁금하다면?
이미 회원이신가요?
2024년 7월 11일 오전 7:52
항상 좋은글 감사합니다!