티스토리 뷰
안녕하세요
Notion을 저는 개인 메모장으로 잘 쓰고있었는데 Notion Api 라는 기능이 있더라구요.
궁금해서 사용해보려고 합니다~
(편하게 노션이라고 하겠습니다!)
먼저 연동하기에 앞서 노션Api란?
노션에 끄적여있는 글이나 이미지같은 데이터를 읽어올 수 있도록 제공하는 기능이에요.
저는 노션에 있는 데이터베이스 테이블을 읽어와 아이폰에 표시하려합니다~
그럼 먼저 Api 를 만들어야겠죠?
https://www.notion.so/my-integrations
위 링크에 들어가셔서 Api 를 추가해주세요.
'이름'만 입력하면 만들 수 있어요.
Api를 만들면 시크릿키를 발급해줍니다.


저는 아래 사진처럼 'TestApi'라고 지어줬어요.

우리는 아이폰에서 저 'TestApi'를 통해 제 노션에있는 데이터베이스 테이블에 접근할 수 있어요.
이어서 읽어올 데이터베이스 테이블을 추가해주세요.
주의할점은 전체페이지로 생성해주셔야해요.

저는 데이터베이스에 이렇게 채웠어요.

데이터베이스id를 저장해둡시다.
스크린샷의 '링크 복사' 를 붙여넣어보면 아래처럼 보이는데 '데이터베이스id'라고 적은 부분을 저장해둡니다.
데이터베이스를 읽어오는 로직에 사용됩니다.
https://www.notion.so/{데이터베이스id}?v=ASDASDASDASD&pvs=4

지금 생성한 데이터베이스에 아까 만든 Api를 추가해줍니다.

이제 Api를 통해 데이터베이스 테이블에 접근할 수 있는 상태가 되었어요.
https://developers.notion.com/reference/post-database-query
Start building with the Notion API
Gets a list of Pages contained in the database, filtered and ordered according to the filter conditions and sort criteria provided in the request. The response may contain fewer than page_size of results. If the response includes a next_cursor value, refer
developers.notion.com
위 링크를 참고해서 데이터베이스를 Json 으로 출력하면 아래와같은 모습입니다.
너무 길어서 접어놨어요.
{
"object": "list",
"results": [
{
"object": "page",
"id": "cefcb06b-f59d-44ed-badf-27a2541ce7a3",
"created_time": "2023-06-09T05:13:00.000Z",
"last_edited_time": "2023-06-24T18:45:00.000Z",
"created_by": {
"object": "user",
"id": "cdc0f7a0-efed-4295-9648-dbf1ecfb4344"
},
"last_edited_by": {
"object": "user",
"id": "f039a174-6624-475d-839d-04b46f73b58d"
},
"cover": null,
"icon": null,
"parent": {
"type": "database_id",
"database_id": "{dbid}"
},
"archived": false,
"properties": {
"image": {
"id": "Afm%3D",
"type": "files",
"files": []
},
"address": {
"id": "Bbyi",
"type": "rich_text",
"rich_text": [
{
"type": "text",
"text": {
"content": "성남시",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "성남시",
"href": null
}
]
},
"age": {
"id": "%7DY_%3F",
"type": "rich_text",
"rich_text": [
{
"type": "text",
"text": {
"content": "22",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "22",
"href": null
}
]
},
"name": {
"id": "title",
"type": "title",
"title": [
{
"type": "text",
"text": {
"content": "aaa",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "aaa",
"href": null
}
]
}
},
"url": "url",
"public_url": null
},
{
"object": "page",
"id": "73018d6a-8970-44e5-ac00-515bd168959f",
"created_time": "2023-06-09T05:12:00.000Z",
"last_edited_time": "2023-06-24T18:45:00.000Z",
"created_by": {
"object": "user",
"id": "cdc0f7a0-efed-4295-9648-dbf1ecfb4344"
},
"last_edited_by": {
"object": "user",
"id": "f039a174-6624-475d-839d-04b46f73b58d"
},
"cover": null,
"icon": null,
"parent": {
"type": "database_id",
"database_id": "dbid"
},
"archived": false,
"properties": {
"image": {
"id": "Afm%3D",
"type": "files",
"files": []
},
"address": {
"id": "Bbyi",
"type": "rich_text",
"rich_text": [
{
"type": "text",
"text": {
"content": "하남시",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "하남시",
"href": null
}
]
},
"age": {
"id": "%7DY_%3F",
"type": "rich_text",
"rich_text": [
{
"type": "text",
"text": {
"content": "21",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "21",
"href": null
}
]
},
"name": {
"id": "title",
"type": "title",
"title": [
{
"type": "text",
"text": {
"content": "ㅠㅠㅠ",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "ㅠㅠㅠ",
"href": null
}
]
}
},
"url": "{url}",
"public_url": null
},
{
"object": "page",
"id": "5c6ba8a9-562b-4352-900f-01134e0df654",
"created_time": "2023-06-08T08:14:00.000Z",
"last_edited_time": "2023-06-24T18:45:00.000Z",
"created_by": {
"object": "user",
"id": "f039a174-6624-475d-839d-04b46f73b58d"
},
"last_edited_by": {
"object": "user",
"id": "f039a174-6624-475d-839d-04b46f73b58d"
},
"cover": null,
"icon": null,
"parent": {
"type": "database_id",
"database_id": "{dbid}"
},
"archived": false,
"properties": {
"image": {
"id": "Afm%3D",
"type": "files",
"files": []
},
"address": {
"id": "Bbyi",
"type": "rich_text",
"rich_text": [
{
"type": "text",
"text": {
"content": "서울특별시",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "서울특별시",
"href": null
}
]
},
"age": {
"id": "%7DY_%3F",
"type": "rich_text",
"rich_text": [
{
"type": "text",
"text": {
"content": "24",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "24",
"href": null
}
]
},
"name": {
"id": "title",
"type": "title",
"title": [
{
"type": "text",
"text": {
"content": "철수",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "철수",
"href": null
}
]
}
},
"url": "{url}",
"public_url": null
}
],
"next_cursor": null,
"has_more": false,
"type": "page",
"page": {}
}
앱 UI를 간단하게 만들어줍니다.
여기에 '철수'의 정보를 읽어와 보여줄겁니다.

읽어오는 로직은 아래와 같습니다.
네트워크통신은 Alamofire 를 사용했고,
파싱은 Codable 을 사용했습니다.
HTTPHeader 에 '시크릿키'는 Api 생성 후 발급받은 시크릿키를 넣어주세요.
let notionHeaders : HTTPHeaders = [HTTPHeader(name: "Authorization", value: "{시크릿키}"),
HTTPHeader(name: "Notion-Version", value: "2022-06-28")]
func notionRead(completion: @escaping ([HumanInfo]?) -> ()) {
AF.request("https://api.notion.com/v1/databases/{데이터베이스id}/query",
method: .post,
parameters: nil,
encoding: JSONEncoding.default,
headers: notionHeaders,
interceptor: nil,
requestModifier: nil).validate(statusCode: 200..<600).response { [weak self] response in
switch response.result {
case .success(let data):
guard let data = data else { return }
do {
guard let prettyJson = NSString(data: data, encoding: String.Encoding.utf8.rawValue) else { return }
print("get Json : \(prettyJson)")
let parsedData = try JSONDecoder().decode(BgNotionApiModel.self, from: data)
let humanInfos = self?.notionDataManufacturing(parsedData: parsedData)
completion(humanInfos)
} catch {
print("파싱 에러 : \(error)")
completion(nil)
}
case .failure(let error):
print("응답 에러 : \(error)")
completion(nil)
}
}
}
읽어온 데이터에 접근하기쉽게 notionDataManufacturing 라는 메소드를 만들었습니다.
func notionDataManufacturing(parsedData: BgNotionApiModel) -> [HumanInfo] {
var humanInfos: [HumanInfo] = []
for result in parsedData.results {
let name = getNotionText(richText: result.properties.name.title)
let age = getNotionText(richText: result.properties.age.richText)
let address = getNotionText(richText: result.properties.address.richText)
let info = HumanInfo(name: name, age: age, address: address)
humanInfos.append(info)
}
return humanInfos
}
func getNotionText(richText: [Text]) -> String {
if richText.isEmpty {
return "";
}
return richText[0].text.content
}
읽어온 데이터를 화면에 표시합니다.
(철수에 대한 정보가 리스트중 0번째에 해당하므로 0인덱스를 할당했습니다.)
func readButtonClick() {
worker.notionRead {[weak self] parsedData in
guard let parsedData = parsedData else { return }
print(parsedData)
self?.name.text = parsedData[0].name
self?.age.text = parsedData[0].age
self?.address.text = parsedData[0].address
}
}
연동이 잘 되었다면 아래처럼 표시할 수 있습니다.
