🤖 Swift와 SwiftUI로 UI 코드 자동 생성 앱 만들기

💡이 글은 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

댓글 1