이 문서는 iOS SDK(Kakao SDK for iOS)를 사용한 카카오톡 공유 API 구현 방법을 안내합니다.
카카오디벨로퍼스의 메시지 발송 기능은 카카오톡 공유와 카카오톡 메시지 두 가지입니다. 메시지 발송 기능 안내를 참고해 사용할 기능을 선택합니다. 카카오톡 공유를 사용하려는 경우, Step 2 이후의 내용을 확인합니다.
템플릿 종류를 참고하여 어떤 메시지 템플릿을 사용할지 결정합니다.
구성 방식 비교을 참고해 어떤 방식으로 메시지를 구성할지 결정합니다. 사전에 정의된 기본 템플릿을 바탕으로 객체 형태로 구성하거나, 서비스에 맞게 직접 구성한 사용자 정의 템플릿 방식을 사용할 수 있습니다.
메시지 발송 API를 호출합니다. 요청이 성공하면 iOS SDK는 카카오톡을 실행하거나, 웹 페이지에서 카카오계정으로 로그인해 메시지를 보낼 친구 및 대화방 목록을 보여줍니다. 사용자가 메시지를 보낼 친구 또는 대화방을 선택하면 메시지가 전송됩니다.
카카오톡 공유 완료 시 반환되는 값은 없으며, 전송 성공 여부는 카카오톡 공유 웹훅으로 확인할 수 있습니다.
사용자가 카카오톡 메시지의 버튼으로 앱을 실행할 수 있도록 하려면 앱 실행 허용 목록을 설정해야 합니다. 카카오톡 공유와 카카오톡 메시지 사용 시, LSApplicationQueriesSchemes
설정에 "kakaolink" 값이 필요합니다. 이 설정은 kakao${YOUR_NATIVE_APP_KEY}://kakaolink
형식의 앱 실행을 위한 커스텀 URL 스킴(Custom URL Scheme)을 만드는 데 쓰입니다.
네이티브 앱의 경우, 커스텀 URL 스킴으로 앱 실행 시 서비스의 필요에 따라 추가 정보를 전달할 수 있습니다. androidExecutionParams
, iosExecutionParams
파라미터로 앱 실행 시 전달할 키와 값을 설정할 수 있습니다. 해당 파라미터 사용 시, 카카오톡 공유 메시지에서 앱을 실행하는 버튼을 클릭하면 아래와 같은 스킴이 호출됩니다.
kakao${YOUR_NATIVE_APP_KEY}://kakaolink?${androidExecutionParams}
kakao${YOUR_NATIVE_APP_KEY}://kakaolink?${iosExecutionParams}
// 예시
kakao${YOUR_NATIVE_APP_KEY}://kakaolink?key1=value1&key2=value2&key3=value3
레퍼런스 | 앱 설정 |
---|---|
[SDK, RxSDK] shareDefault() [SDK] isKakaoTalkSharingAvailable() [SDK] makeDefaultUrl() [SDK] SharingResult |
설치 모듈 설정 초기화 |
권한 | 사전 설정 | 카카오 로그인 | 동의항목 |
---|---|---|---|
- | 플랫폼 등록 | - | - |
사전 정의된 기본 템플릿을 사용해 카카오톡으로 메시지를 공유합니다.
isKakaoTalkSharingAvailable()
을 호출하여 사용자 기기에 카카오톡이 설치되어 있는지 확인합니다.shareDefault()
을 호출하여 SharingResult
객체를 반환받습니다. 해당 객체의 intent
를 사용해 액티비티를 실행하여 카카오톡으로 메시지를 공유하도록 구현합니다.WebSharerClient
의 makeDefaultUrl()
으로 웹 공유 URL을 생성한 후, 기본 브라우저나 웹뷰로 해당 URL을 열도록 구현합니다.DefaultTemplate
인터페이스를 구현한 후, 원하는 템플릿 종류에 따라 아래 클래스 중 하나를 사용하여 템플릿 객체를 구성합니다. 또는 고급: 생성자를 사용해 메시지 만들기를 참고해 templateObject
객체를 생성하여 메시지 전송 시 사용합니다.
shareDefault()
또는 makeDefaultUrl()
호출 시, 앞서 구성한 템플릿 객체를 templatable
파라미터로 전달합니다.//in ViewController
var safariViewController : SFSafariViewController? // to keep instance
//...
guard let templatable = try? SdkJSONDecoder.custom.decode(FeedTemplate.self, from: feedTemplateJsonStringData) else {
return
}
// 카카오톡 설치여부 확인
if ShareApi.isKakaoTalkSharingAvailable() {
// 카카오톡으로 카카오톡 공유 가능
// templatable 예시는 문서 참고: https://developers.kakao.com/docs/latest/ko/message-template/default
ShareApi.shared.shareDefault(templatable: templatable) {(sharingResult, error) in
if let error = error {
print(error)
}
else {
print("shareDefault() success.")
if let sharingResult = sharingResult {
UIApplication.shared.open(sharingResult.url,
options: [:], completionHandler: nil)
}
}
}
else {
// 카카오톡 미설치: 웹 공유 사용 권장
// Custom WebView 또는 디폴트 브라우져 사용 가능
// 웹 공유 예시 코드
if let url = ShareApi.shared.makeDefaultUrl(templatable: templatable) {
self.safariViewController = SFSafariViewController(url: url)
self.safariViewController?.modalTransitionStyle = .crossDissolve
self.safariViewController?.modalPresentationStyle = .overCurrentContext
self.present(self.safariViewController!, animated: true) {
print("웹 present success")
}
}
}
// Class member property
let disposeBag = DisposeBag()
// templatable 예시는 문서 참고: https://developers.kakao.com/docs/latest/ko/message-template/default
if let templatable = try? SdkJSONDecoder.custom.decode(FeedTemplate.self, from: feedTemplateJsonStringData) {
ShareApi.shared.rx.shareDefault(templatable:templatable)
.subscribe(onSuccess: { (sharingResult) in
print("shareDefault() success.")
UIApplication.shared.open(sharingResult.url, options: [:], completionHandler: nil)
}, onFailure: {error in
print(error)
})
.disposed(by: disposeBag)
}
레퍼런스 | 앱 설정 |
---|---|
[SDK, RxSDK] shareCustom() [SDK] isKakaoTalkSharingAvailable() [SDK] makeCustomUrl() [SDK] SharingResult |
설치 모듈 설정 초기화 |
권한 | 사전 설정 | 카카오 로그인 | 동의항목 |
---|---|---|---|
- | 플랫폼 등록 | - | - |
[도구] > [메시지 템플릿]에서 직접 구성한 사용자 정의 템플릿을 사용하여 카카오톡으로 메시지를 공유하는 기능입니다. 메시지 구성 방법은 사용자 정의 템플릿을 참고합니다.
isKakaoTalkSharingAvailable()
을 호출하여 사용자 기기에 카카오톡이 설치되어 있는지 확인합니다.shareCustom()
을 호출하여 SharingResult
객체를 반환받습니다. 해당 객체의 requestUrl
을 열어 카카오톡으로 메시지를 공유하도록 구현합니다.makeCustomUrl()
로 웹 공유 URL을 생성한 후, 기본 브라우저나 웹뷰로 해당 URL을 열도록 구현합니다.shareCustom()
또는 makeCustomUrl()
호출 시, 메시지 템플릿 도구에서 구성한 템플릿 ID를 templateId
파라미터로 전달합니다.templateArgs
파라미터로 키와 값을 전달합니다. 사용자 정의 템플릿에 사용자 인자가 포함되었음에도 해당 파라미터를 사용하지 않을 경우, 사용자 인자로 지정된 부분이 ${KEY}
형식으로 메시지에 그대로 노출됩니다.let templateId = 12345
// 카카오톡 설치여부 확인
if ShareApi.isKakaoTalkSharingAvailable() {
// 카카오톡으로 카카오톡 공유 가능
ShareApi.shared.shareCustom(templateId: templateId, templateArgs:["title":"제목입니다.", "description":"설명입니다."]) {(sharingResult, error) in
if let error = error {
print(error)
}
else {
print("shareCustom() success.")
if let sharingResult = sharingResult {
UIApplication.shared.open(sharingResult.url, options: [:], completionHandler: nil)
}
}
}
}
else {
// 카카오톡 미설치: 웹 공유 사용 권장
// Custom WebView 또는 디폴트 브라우져 사용 가능
// 웹 공유 예시 코드
if let url = ShareApi.shared.makeCustomUrl(templateId: templateId, templateArgs:["title":"제목입니다.", "description":"설명입니다."]) {
self.safariViewController = SFSafariViewController(url: url)
self.safariViewController?.modalTransitionStyle = .crossDissolve
self.safariViewController?.modalPresentationStyle = .overCurrentContext
self.present(self.safariViewController!, animated: true) {
print("웹 present success")
}
}
}
// Class member property
let disposeBag = DisposeBag()
let templateId = 12345
ShareApi.shared.rx.shareCustom(templateId:templateId, templateArgs:["title":"제목입니다.", "description":"설명입니다."])
.subscribe(onSuccess: { (sharingResult) in
print("shareCustom() success.")
UIApplication.shared.open(sharingResult.url, options: [:], completionHandler: nil)
}, onFailure: {error in
print(error)
})
.disposed(by: disposeBag)
레퍼런스 | 앱 설정 |
---|---|
[SDK, RxSDK] shareScrap() [SDK] isKakaoTalkSharingAvailable() [SDK] makeScrapUrl() [SDK] SharingResult |
설치 모듈 설정 초기화 |
권한 | 사전 설정 | 카카오 로그인 | 동의항목 |
---|---|---|---|
- | 플랫폼 등록 | - | - |
지정한 웹 페이지를 스크랩한 정보로 스크랩 메시지를 구성하여 카카오톡으로 메시지를 공유하는 기능입니다.
isKakaoTalkSharingAvailable()
을 호출하여 사용자 기기에 카카오톡이 설치되어 있는지 확인합니다.shareScrap()
을 호출하여 SharingResult
객체를 반환받습니다. 해당 객체의 intent
를 사용해 액티비티를 실행하여 카카오톡으로 메시지를 공유하도록 구현합니다.WebSharerClient
의 makeScrapUrl()
으로 웹 공유 URL을 생성한 후, 기본 브라우저나 웹뷰로 해당 URL을 열도록 구현합니다.shareScrap()
또는 makeScrapUrl()
호출 시, 스크랩할 웹 페이지의 URL을 requestUrl
파라미터로 전달해야 합니다. 스크랩할 웹 페이지의 도메인은 앱 관리 페이지의 [앱] > [일반] > [플랫폼] > [Web]에 등록돼 있어야 합니다.templateId
파라미터로 전달해야 합니다. 템플릿 구성 방법은 사용자 정의 템플릿을 참고합니다. 메시지에 변동되는 정보를 포함하려면 사용자 인자를 사용합니다. 이 경우, 반드시 templateArgs
파라미터로 키와 값을 전달해야 합니다.let requestUrl = "https://developers.kakao.com"
// 카카오톡 설치여부 확인
if ShareApi.isKakaoTalkSharingAvailable() {
// 카카오톡으로 카카오톡 공유 가능
ShareApi.shared.shareScrap(requestUrl: requestUrl) {(sharingResult, error) in
if let error = error {
print(error)
}
else {
print("shareScrap() success.")
if let sharingResult = sharingResult {
UIApplication.shared.open(sharingResult.url, options: [:], completionHandler: nil)
}
}
}
}
else {
// 카카오톡 미설치: 웹 공유 사용 권장
// Custom WebView 또는 디폴트 브라우져 사용 가능
// 웹 공유 예시 코드
if let url = ShareApi.shared.makeScrapUrl(requestUrl: requestUrl) {
self.safariViewController = SFSafariViewController(url: url)
self.safariViewController?.modalTransitionStyle = .crossDissolve
self.safariViewController?.modalPresentationStyle = .overCurrentContext
self.present(self.safariViewController!, animated: true) {
print("웹 present success")
}
}
}
// Class member property
let disposeBag = DisposeBag()
let requestUrl = "https://developers.kakao.com"
ShareApi.shared.rx.shareScrap(requestUrl: requestUrl)
.subscribe(onSuccess: { (sharingResult) in
print("shareScrap() success.")
UIApplication.shared.open(sharingResult.url, options: [:], completionHandler: nil)
}, onFailure: {error in
print(error)
})
.disposed(by: disposeBag)
let requestUrl = "https://developers.kakao.com"
let templateId = 12345
// 카카오톡 설치여부 확인
if ShareApi.isKakaoTalkSharingAvailable() {
// 카카오톡으로 카카오톡 공유 가능
ShareApi.shared.shareScrap(requestUrl: requestUrl, templateId: templateId) {(sharingResult, error) in
if let error = error {
print(error)
}
else {
print("shareScrap() success.")
if let sharingResult = sharingResult {
UIApplication.shared.open(sharingResult.url, options: [:], completionHandler: nil)
}
}
}
else {
// 카카오톡 미설치: 웹 공유 사용 권장
// Custom WebView 또는 디폴트 브라우져 사용 가능
// 웹 공유 예시 코드
if let url = ShareApi.shared.makeScrapUrl(requestUrl: requestUrl, templateId: templateId) {
self.safariViewController = SFSafariViewController(url: url)
self.safariViewController?.modalTransitionStyle = .crossDissolve
self.safariViewController?.modalPresentationStyle = .overCurrentContext
self.present(self.safariViewController!, animated: true) {
print("웹 present success")
}
}
}
// Class member property
let disposeBag = DisposeBag()
let requestUrl = "https://developers.kakao.com"
let templateId = 12345
ShareApi.shared.rx.shareScrap(requestUrl: requestUrl, templateId: templateId)
.subscribe(onSuccess: { (sharingResult) in
print("shareScrap() success.")
UIApplication.shared.open(sharingResult.url, options: [:], completionHandler: nil)
}, onFailure: {error in
print(error)
})
.disposed(by: disposeBag)
카카오톡 공유 웹훅은 사용자가 선택한 친구나 채팅방으로 카카오톡 공유 메시지가 성공적으로 전달된 경우, 카카오디벨로퍼스에 설정된 웹훅 URL로 메시지가 성공적으로 전달되었음을 알려주는 기능입니다. 카카오톡 공유 메시지 전송 시에만 사용할 수 있고, 카카오톡 메시지 전송에는 지원되지 않습니다. 카카오톡 공유는 사용자가 카카오톡에서 메시지를 전송하므로 서비스에서 전송 성공 여부를 직접 확인할 수 없기 때문에 메시지 전송 성공 시 알림을 받는 웹훅 기능을 제공합니다.
이 기능을 사용하려면 아래를 수행해야 합니다.
서비스 서버에서 카카오톡 공유 웹훅을 받을 때, 미리 설정해둔 사용자 정의(Custom) 파라미터로 사용자가 공유한 콘텐츠가 무엇인지 등 추가 정보를 알 수 있습니다. 서비스 서버로 보내지는 알림은 자세한 메시지 전송 관련 정보를 포함하고 있지 않으므로 어떤 메시지의 전송 결과인지, 사용자가 무슨 정보를 공유했는지 등 서비스에서 필요한 추가 정보로 파라미터를 구성합니다. 앱 관리 페이지에서 카카오톡 공유 웹훅을 설정하였더라도 사용자 정의 파라미터가 없을 경우에는 카카오톡 공유 웹훅이 전달되지 않습니다.
serverCallbackArgs
파라미터에 Dictionary
자료형으로 키와 값의 쌍으로 구성한 정보를 담아 카카오톡 공유 API 요청 시 전달해야 하며, 키에는 시스템 예약어인 CHAT_TYPE
, HASH_CHAT_ID
, TEMPLATE_ID
를 사용할 수 없습니다. 해당 키는 카카오톡 공유 웹훅의 명세에 정의된 값으로 알림에 포함됩니다.
아래는 카카오톡 공유 웹훅 파라미터 설정 예제입니다.
// 템플릿 ID
let templateId = 12345;
// 템플릿 Arguments
let templateArgs = ["title": "제목 영역입니다.", "description": "설명 영역입니다."]
// 서버에서 웹훅으로 받을 정보
let serverCallbackArgs = ["user_id": "abcd", "product_id": "1234"]
// 카카오톡 설치여부 확인
if ShareApi.isKakaoTalkSharingAvailable() {
// 카카오톡으로 카카오톡 공유 가능
ShareApi.shared.shareCustom(templateId:templateId,
templateArgs:templateArgs,
serverCallbackArgs: serverCallbackArgs) { (sharingResult, error) in
if let error = error {
print(error)
}
else {
print("shareCustom() success.")
if let sharingResult = sharingResult {
UIApplication.shared.open(sharingResult.url, options: [:], completionHandler: nil)
}
}
}
}
else {
// 카카오톡 미설치: 웹 공유 사용 권장
// Custom WebView 또는 디폴트 브라우져 사용 가능
// 웹 공유 예시 코드
if let url = ShareApi.shared.makeCustomUrl(templateId:templateId,
templateArgs:templateArgs,
serverCallbackArgs: serverCallbackArgs) {
self.safariViewController = SFSafariViewController(url: url)
self.safariViewController?.modalTransitionStyle = .crossDissolve
self.safariViewController?.modalPresentationStyle = .overCurrentContext
self.present(self.safariViewController!, animated: true) {
print("웹 present success")
}
}
}
// Class member property
let disposeBag = DisposeBag()
// 템플릿 ID
let templateId = 12345;
// 템플릿 Arguments
let templateArgs = ["title": "제목 영역입니다.", "description": "설명 영역입니다."]
// 서버에서 웹훅으로 받을 정보
let serverCallbackArgs = ["user_id": "abcd", "product_id": "1234"]
ShareApi.shared.rx.shareCustom(templateId:templateId,
templateArgs:templateArgs,
serverCallbackArgs: serverCallbackArgs)
.subscribe(onSuccess: { (sharingResult) in
print("shareCustom() success.")
UIApplication.shared.open(sharingResult.url, options: [:], completionHandler: nil)
}, onFailure: {error in
print(error)
})
.disposed(by: disposeBag)
}
위와 같이 설정된 파라미터는 서비스 서버의 웹훅 URL으로 전달하는 알림에 요청 파라미터 형태로 전달됩니다. 카카오가 보내는 카카오톡 공유 웹훅 요청 전문은 카카오톡 공유 웹훅을 확인합니다.
레퍼런스 | 앱 설정 |
---|---|
[SDK, RxSDK] imageUpload() [SDK, RxSDK] imageScrap() [SDK] ImageUploadResult |
설치 모듈 설정 초기화 |
권한 | 사전 설정 | 카카오 로그인 | 동의항목 |
---|---|---|---|
- | 플랫폼 등록 | - | - |
메시지에 넣을 이미지는 URL 형태로 메시지 템플릿 구성 시에 첨부하거나, 메시지 템플릿 도구에서 미리 업로드할 수 있습니다. 기기에 저장된 이미지 파일은 서버에 업로드하고 이미지 파일 URL 값을 구해야 메시지 전송에 사용할 수 있습니다.
이미지 파일 URL을 구하기 어려운 경우, 웹 페이지 속 이미지 파일을 카카오 서버로 업로드하거나 스크랩해두는 기능을 이용할 수 있습니다. 파일 용량 5MB 이하 이미지만 업로드할 수 있습니다. 카카오 서버에 업로드된 이미지는 최대 100일간 보관되고, 기간이 지나면 자동으로 삭제됩니다.
요청 성공 시 업로드된 이미지의 URL 정보를 문자열(String) 값으로 받습니다. 이 URL을 메시지 구성 시 사용할 수 있습니다.
이미 서비스 서버에 업로드되어 있는 이미지 파일의 정보를 스크랩하고, 카카오 서버에 저장하여 메시지 전송에 사용할 수도 있습니다. 이미지 파일 스크랩에는 imageScrap()
API를 사용합니다.
if let image = UIImage(named: "sample1") {
ShareApi.shared.imageUpload(image:image) { [weak self] (imageUploadResult, error) in
if let error = error {
print(error)
}
else {
print("imageUpload() success.")
}
}
}
// Class member property
let disposeBag = DisposeBag()
if let image = UIImage(named: "sample1") {
ShareApi.shared.rx.imageUpload(image:image)
.subscribe(onSuccess: { (imageUploadResult) in
print("imageUpload() success.")
}, onFailure: {error in
print(error)
})
.disposed(by: disposeBag)
}
if let url = URL(string:"https://t1.kakaocdn.net/kakaocorp/Service/KakaoTalk/pc/slide/talkpc_theme_01.jpg") {
ShareApi.shared.imageScrap(imageUrl: url, completion: { [weak self] (imageUploadResult, error) in
if let error = error {
print(error)
}
else {
print("imageUpload() success.")
}
})
}
// Class member property
let disposeBag = DisposeBag()
if let url = URL(string:"https://t1.kakaocdn.net/kakaocorp/Service/KakaoTalk/pc/slide/talkpc_theme_01.jpg") {
ShareApi.shared.rx.imageScrap(imageUrl: url)
.subscribe(onSuccess: { (imageUploadResult) in
print(String(describing:imageUploadResult))
}, onFailure: {error in
print(error)
})
.disposed(by: disposeBag)
}
메시지는 JSON
형식으로 구성하는 것이 기본적인 방법이지만, 메시지 유형별 템플릿 클래스의 생성자를 사용해 메시지를 만들 수도 있습니다. 이 방법을 사용할 경우 구성 요소들을 보다 명시적으로 파악하고 정의할 수 있다는 장점이 있습니다. 메시지 유형별 템플릿 클래스 객체는 메시지 전송 요청에 바로 사용할 수 없고, 실제 요청 파라미터에 쓰일 templateObject
객체 생성에 사용해야 합니다.
let link = Link(webUrl: URL(string:"https://developers.kakao.com"),
mobileWebUrl: URL(string:"https://developers.kakao.com"))
let appLink = Link(androidExecutionParams: ["key1": "value1", "key2": "value2"],
iosExecutionParams: ["key1": "value1", "key2": "value2"])
let button1 = Button(title: "웹으로 보기", link: link)
let button2 = Button(title: "앱으로 보기", link: appLink)
let social = Social(likeCount: 286,
commentCount: 45,
sharedCount: 845)
let content = Content(title: "딸기 치즈 케익",
imageUrl: URL(string:"https://mud-kage.kakao.com/dn/Q2iNx/btqgeRgV54P/VLdBs9cvyn8BJXB3o7N8UK/kakaolink40_original.png")!,
description: "#케익 #딸기 #삼평동 #카페 #분위기 #소개팅",
link: link)
let feedTemplate = FeedTemplate(content: content, social: social, buttons: [button1, button2])
//메시지 템플릿 encode
if let feedTemplateJsonData = (try? SdkJSONEncoder.custom.encode(feedTemplate)) {
//생성한 메시지 템플릿 객체를 jsonObject로 변환
if let templateJsonObject = SdkUtils.toJsonObject(feedTemplateJsonData) {
ShareApi.shared.shareDefault(templateObject:templateJsonObject) {(sharingResult, error) in
if let error = error {
errorHandler(error)
}
else {
print("shareDefault(templateObject:templateJsonObject) success.")
// 성공 시 동작 구현
guard let sharingResult = sharingResult else { return }
UIApplication.shared.open(sharingResult.url, options: [:], completionHandler: nil)
}
}
}
}
// Class member property
let disposeBag = DisposeBag()
let link = Link(webUrl: URL(string:"https://developers.kakao.com"),
mobileWebUrl: URL(string:"https://developers.kakao.com"))
let appLink = Link(androidExecutionParams: ["key1": "value1", "key2": "value2"],
iosExecutionParams: ["key1": "value1", "key2": "value2"])
let button1 = Button(title: "웹으로 보기", link: link)
let button2 = Button(title: "앱으로 보기", link: appLink)
let social = Social(likeCount: 286,
commentCount: 45,
sharedCount: 845)
let content = Content(title: "딸기 치즈 케익",
imageUrl: URL(string:"https://mud-kage.kakao.com/dn/Q2iNx/btqgeRgV54P/VLdBs9cvyn8BJXB3o7N8UK/kakaolink40_original.png")!,
description: "#케익 #딸기 #삼평동 #카페 #분위기 #소개팅",
link: link)
let feedTemplate = FeedTemplate(content: content, social: social, buttons: [button1, button2])
//생성한 메시지 템플릿 encode
if let feedTemplateJsonData = (try? SdkJSONEncoder.custom.encode(feedTemplate)) {
//생성한 메시지 템플릿을 jsonObject로 변환
if let templateJsonObject = SdkUtils.toJsonObject(feedTemplateJsonData) {
ShareApi.shared.rx.shareDefault(templateObject:templateJsonObject)
.subscribe(onSuccess: { (sharingResult) in
print("success.")
// 성공 시 동작 구현
UIApplication.shared.open(sharingResult.url, options: [:], completionHandler: nil)
}, onFailure: {error in
print(error)
})
.disposed(by: disposeBag)
}
}