IOS/개발 프로젝트

[iOS] Naver CLOVA AI Summary 기능을 이용해서 SwiftUI iOS 앱 만들기

버스트 캐넌 2024. 1. 4. 23:13

글 작성에 앞서 본 블로그의 모든 게시글은 블로그 주인의 개발 일지(일기) 형태의 게시글입니다.

정보를 나누는 방식보단, 제가 했던 방식을 공유하는 식의 글이라 읽어도 제대로 이해를 못 하실 수 있거나 더 좋은 다른 방법이 존재할 수 있습니다.

이 점 양해해 주시며 본 블로그의 게시글을 읽어주시면 감사하겠습니다.

 

안녕하세요 버스트캐넌입니다.

 

오늘은 Naver CLOVA AI 기능 중 하나인 Summary 기능을 이용해서 간단한 iOS 앱을 만들어 볼 예정입니다.

 

https://www.ncloud.com/product/aiService/clovaSummary

 

NAVER CLOUD PLATFORM

cloud computing services for corporations, IaaS, PaaS, SaaS, with Global region and Security Technology Certification

www.ncloud.com

 

Naver CLOVA AI summary는, 문서에서 가려낸 주요 내용을 기반으로 전체 내용을 간결하게 요약하는 API입니다.

 

 

어쩌고저쩌고 하면서 기능을 알려주는데 저희는 구현이 목적이다 보니 크게 신경 쓸 필요 없을 것 같습니다.

 

 

알아 두어야 할 유의사항 일 것 같아 들고 왔습니다.

영어가 지원 안 되는 게 매우 아쉽네요. 최대 글자수 2,000자 인 것도 알아둡시다.

 

 

요금 안내 사항도 존재하네요. 매달 1,000회 이상 호출하게 될 시에는 요금이 부과됩니다.

하지만 방금 유의사항에도 적혀있듯이, 호출 제한을 걸 수 있기도 하고, 처음 가입하면 API 요금 용도인 100,000 크레딧을 주어서 신경 쓸 필요 없을 것 같습니다.

 

맨 밑 이용신청을 통해 Naver CLOVA AI Summary 기능을 사용할 수 있습니다.

로그인이 안된 분들은 로그인하시고, 네이버 아이디로 쉽게 가입도 가능하기에 계정이 없으신 분들은 네이버로 쉽게 만들 수 있습니다.

 

 

로그인을 하고 나면 이 화면이 나올 겁니다.

저는 이미 한번 테스트용으로 써서 한 개가 등록 돼있네요.

 

중간에 '+ Application 등록'이라고 적힌 하늘색 버튼을 눌러 App을 추가해 봅시다.

 

 

Application 이름은 각자 앱 이름으로 하면 됩니다. 저는 임시로 SummaryAPITest라고 해두었습니다.

그리고 저희는 CLOVA Summary 만 사용할 것이라 Summary만 체크해두었습니다.

 

 

서비스 환경 등록 화면입니다.

각자 App의 Bundle ID를 적으시면 됩니다.

 

 

App Bundle ID는 Xcode에 있는 Bundle Identifier에서 확인가능합니다.

App Bundle ID를 작성 후 추가를 누르면 추가가 됩니다.

그런 뒤 등록 버튼을 누르면 Summary 기능을 사용해 볼 수 있습니다.

 

 

제가 방금 만든 SummaryAPITest가 정상적으로 생성된 것을 볼 수 있습니다.

이 화면에서 바로 한도 설정을 할 수 있으니까 바로 설정해봅시다.

 

 

대부분 개인이 사용하겠지만 저는 혹시나 하는 마음에 둘 다 1,000회로 설정한 후 저장 했습니다.

 

이제 본인의 App에 적용시켜 봅시다.

Naver CLOVA AI Summary 기능을 사용해 보기 위해 Summary 문서로 들어가 봅시다.

 

https://api.ncloud-docs.com/docs/ai-naver-clovasummary-api

 

문서요약

 

api.ncloud-docs.com

 

 

Naver CLOVA AI Summary 기능은 HTTP 기반의 REST API라고 합니다.

해당 링크와 3개의 헤더를 이용해 요청할 수 있습니다.

 

 

document, option이라는 요청바디가 필요하고 이것들은 DocumentObject, OptionObject로 세분화되어있습니다.

응답 바디도 존재하네요.

 

이것들을 Swift 식으로 만들어 줍시다.

 

 

저는 따로 SummaryModel이라는 Swift 파일을 만들어서 따로 작성하였습니다.

 

struct RequestBody: Codable {
    let document: DocumentObject
    let option: OptionObject
}

struct DocumentObject: Codable {
    let title: String?
    let content: String
}

struct OptionObject: Codable {
    let language: String
    let model: String
    let tone: Int
    let summaryCount: Int
}
struct ApiResponse: Codable {
    let summary: String
}

 

Swift로 코드를 작성해 보았습니다.

Summary 문서에 있는 것을 토대로 코드를 작성하였고, 제목에 해당하는 title은 제가 테스트해보았을 때 없어도 오류가 안 나서 title?로 작성하였습니다.

 

class APIClient {
    static let shared = APIClient()
    private init() {}

    func postRequestToAPI(title: String, content: String) async throws -> String {
        let apiKeyID = "put your apiKeyID"
        let apiKey = "put your apiKey"
        let apiEndpoint = "https://naveropenapi.apigw.ntruss.com/text-summary/v1/summarize"

        guard let url = URL(string: apiEndpoint) else {
            throw URLError(.badURL)
        }

        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.addValue(apiKeyID, forHTTPHeaderField: "X-NCP-APIGW-API-KEY-ID")
        request.addValue(apiKey, forHTTPHeaderField: "X-NCP-APIGW-API-KEY")
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")

        let requestBody = RequestBody(
            document: DocumentObject(title: title, content: content),
            option: OptionObject(language: "ko", model: "general", tone: 0, summaryCount: 3)
        )

        request.httpBody = try JSONEncoder().encode(requestBody)

        let (data, _) = try await URLSession.shared.data(for: request)

        do {
            let decoder = JSONDecoder()
            let decodedData = try decoder.decode(ApiResponse.self, from: data)
            return decodedData.summary
        } catch {
            throw URLError(.badServerResponse)
        }
    }

}

 

그런 다음 APIClient라는 Class를 작성했습니다.

APIKeyID와 APIKey를 선언하였고, HTTP링크를 선언했습니다. 

한도를 설정했지만, 프로젝트 파일을 GitHub 같은 public 사이트에 올릴 경우, 유출을 고려하여 따로 빼두어 보안을 유지하면 됩니다.

 

put your apikeyID와 put your apikey에서는 각자의 APIKeyID, APIKey를 적으시면 됩니다.

APIKeyID와 APIKey는 아까 한도를 설정한 인터넷 페이지에서 인증정보를 눌러서 확인할 수 있습니다.

 

 

SummaryModel에 있는 코드는 작성완료 했습니다.

이제 간단하게 화면을 구성해 봅시다.

 

struct ContentView: View {
    @State private var title: String = "'하루 2000억' 판 커지는 간편송금 시장"
    @State private var content: String = "간편송금 이용금액이 하루 평균 2000억원을 넘어섰다. 한국은행이 17일 발표한 '2019년 상반기중 전자지급서비스 이용 현황'에 따르면 올해 상반기 간편송금서비스 이용금액(일평균)은 지난해 하반기 대비 60.7% 증가한 2005억원으로 집계됐다. 같은 기간 이용건수(일평균)는 34.8% 늘어난 218만건이었다. 간편 송금 시장에는 선불전자지급서비스를 제공하는 전자금융업자와 금융기관 등이 참여하고 있다. 이용금액은 전자금융업자가 하루평균 1879억원, 금융기관이 126억원이었다. 한은은 카카오페이, 토스 등 간편송금 서비스를 제공하는 업체 간 경쟁이 심화되면서 이용규모가 크게 확대됐다고 분석했다. 국회 정무위원회 소속 바른미래당 유의동 의원에 따르면 카카오페이, 토스 등 선불전자지급서비스 제공업체는 지난해 마케팅 비용으로 1000억원 이상을 지출했다. 마케팅 비용 지출규모는 카카오페이가 491억원, 비바리퍼블리카(토스)가 134억원 등 순으로 많았다."
    @State private var summary: String = ""
    
    var body: some View {
        VStack(spacing: 10) {
            Text(title)
                .font(.title)
            Text(content)
            Button(action: {
                Task {
                    let trimmedContent = content.trimmingCharacters(in: .whitespacesAndNewlines)
                    summary = try await APIClient.shared.postRequestToAPI(title: title, content: trimmedContent)
                }}, label: {
                    Text("요약하기")
                })
            .padding(10)
            .foregroundColor(.white)
            .background(Color.blue)
            .cornerRadius(40)
            Text(summary)
        }
        .padding()
    }
}

 

Summary 문서에 있는 예제를 들고 와 간단하게 화면을 구성해 보았습니다.

실제로 작동하는지, 요약하기 버튼을 눌러 실행해 봅시다.

 

 

요약하기 버튼 밑에 3줄로 요약된 summary가 정상적으로 출력된 것이 보입니다.

 

 

SummaryModel.Swift에 있는 option부분을 건드려 Summary 문서에 있는 것처럼 요약 내용을 변경 가능합니다.

Picker 등을 이용하여 앱 화면에서 실시간으로 값을 바꿔서도 할 수 있겠으나, 이번에는 간단하게 코드만 변경하여 잘 되는지 알아보겠습니다.

 

 

저는 명사형 종결체인 tone 3을 사용하였고, 요약 문장수는 2로 바꾸어 봤습니다.

 

 

이것 또한 잘 되는 것을 볼 수 있습니다.

마무리 하며...

제가 이걸 조금 사용하면서 살짝 아쉽다고 생각했는데, 위의 예시로 들자면

" 간편 송금 이용금액과 이용건수가 지난해에 비해 크게 상승하였다. 그 이유는 간편 송금 업체 간 경쟁이 심화되면서 이용 규모가 크게 확대되었다고 한은에서 분석하였다."

처럼 요약이 아닌, 중요하다고 생각하는 문장을 그대로 추출해오는 게 아쉽다고 생각했습니다.

다만 그걸 실행하고 있는 카카오톡 요약서비스의 성능이 처참하다는 걸 생각하면... ㅎㅎ

 

그리고 한글, 일본어 두 언어만 지원하고 (영어가 안됩니다...), 한글 일본어 혼용인경우도 안됩니다.

또, 요약할 문장이 적으면 인식을 못하더라구요... 300자 이상은 되어야 인식이 돼서 한줄 겨우 요약 되네요...

아직은 요약 기능을 지원한다 라고만 생각하시면 될것 같습니다.

 

이상 마무리 하겠습니다.

 

포스팅 읽어주셔서 감사합니다.

 

편안한 하루 보내세요~

 

궁금한 점이나 지적해야 할 부분이 있으시면 댓글 남겨주세요. 블로그 주인의 상황에 따라 답변이 없을 수 있으나, 최대한 피드백해 드리겠습니다.

'IOS > 개발 프로젝트' 카테고리의 다른 글

[iOS / SwiftUI] .sheet 이것저것  (1) 2024.02.25