본문 바로가기
인턴

Meta 그래프 api를 이용한 데이터 조회

by sepang 2023. 4. 11.

  지금까지 각 광고 채널의 api를 이용하여 광고의 설정값이나 성과 데이터를 가져온 뒤 이를 가공하여 팀장님이 만들어놓은 모델에 넣어주는 업무를 수행하고 있었다. 본인은 facebook 광고 채널을 담당했는데, 코드를 작성하다가 요구사항이 바뀌어 다시 구조를 바꾸기도 하는 등 우여곡절이 있었다. 이 글과 다음 글에 거쳐 메타의 api를 이용해 데이터를 가져오는 방법과 파이썬의 requests 라이브러리를 사용해 광고 객체를 조회하는 것에 대해 적어보고자 한다.

Meta graph api

  그래프 api는 Facebook 플랫폼에서 데이터를 가져오거나 내보내는 수단이다. marketing api도 이러한 graph api를 사용한다. graph api는 기본적으로 node, edge, fields로 구성된다. 참고로 graph api를 사용하기 위해서는 그에 맞는 적절한 access_token을 같이 실어 요청을 보내야 하는데 이를 얻거나 조작하는 방법은 여기를 참고하자.

node

  노드는 고유 id를 갖는 개별 개체이다. 회원, 게시글, 페이지, 광고 등 모든 객체를 노드라고 볼 수 있다.

curl -i -X GET \
  "https://graph.facebook.com/<USER_ID>?access_token=ACCESS-TOKEN"
{
  "name": "Your Name",
  "id": "YOUR-USER-ID"
}

  예를 들어 위와 같은 요청은 <USER_ID>에 해당하는 유저의 정보를 조회하는 GET 요청인 것이다.

edge

  엣지는 두 노드간의 연결을 의미한다. 나는 게시글-댓글 같은 1:n 관계에서 n의 정보들을 가져오려고 할 때 사용한다고 생각하니 이해가 쉬웠다.

curl -i -X GET \
  "https://graph.facebook.com/<USER_ID>/photos?access_token=ACCESS-TOKEN"
{
  "data": [
    {
      "created_time": "2017-06-06T18:04:10+0000",
      "id": "1353272134728652"
    },
    {
      "created_time": "2017-06-06T18:01:13+0000",
      "id": "1353269908062208"
    }
  ],
}

  위의 예시를 살펴보면 <USER_ID>에 해당하는 유저의 사진들(photos)에 대한 정보를 가져오고 있다

field

  필드는 노드의 속성이다. 위의 노드나 엣지에 대한 예시에서는 따로 필드값을 주지 않았기 때문에 기본값으로 설정된 필드 세트(id, name, created_time, ...)가 반환되었다. 하지만 필드 매개변수를 사용하여 조회하고자 하는 필드값들을 나열하면 해당 정보들도 조회할 수 있다.

curl -i -X GET \
  "https://graph.facebook.com/USER-ID?fields=id,name,email,picture&access_token=ACCESS-TOKEN"
{
  "id": "USER-ID",
  "name": "EXAMPLE NAME",
  "email": "EXAMPLE@EMAIL.COM",
  "picture": {
    "data": {
      "height": 50,
      "is_silhouette": false,
      "url": "URL-FOR-USER-PROFILE-PICTURE",
      "width": 50
    }
  }
}

  노드에서의 예시와 달리 필드 매개변수로 'id, name, email, picture'를 추가해주니 해당 정보도 반환되는 것을 확인할 수 있다.

 

Pagination

  노드나 에지에 대한 api 요청으로 원하는 데이터를 가져올 수 있을 것이라 생각했지만 실제로는 그렇지 못했다. 왜냐하면 api 요청 시 모든 결과를 단일 응답으로 받을 순 없기 때문이다. 아마 한번에 너무 많은 데이터를 반환하면 서버에 부하가 발생하기 때문일 것이다.

  그렇기 때문에 graph api의 응답에서는 pagination을 사용한다(여기서는 커서 기반 pagination을 기준으로 하지만 다른 pagination 방법도 존재). 예를 들어 1,000개의 캠페인 정보를 가져오고 싶을 때, 한번의 응답으로 보내기엔 너무 많으니 20개씩 끊어서 반환하는 것이다.예를 들어 edge를 읽을 때 다음과 같은 응답이 반환된다. 

{
  "data": [
     ... Endpoint data is here
  ],
  "paging": {
    "cursors": {
      "after": "MTAxNTExOTQ1MjAwNzI5NDE=",
      "before": "NDMyNzQyODI3OTQw"
    },
    "previous": "https://graph.facebook.com/{your-user-id}/albums?limit=25&before=NDMyNzQyODI3OTQw"
    "next": "https://graph.facebook.com/{your-user-id}/albums?limit=25&after=MTAxNTExOTQ1MjAwNzI5NDE="
  }
}

   limit 매개변수를 통해 한 페이지에 몇개의 객체 정보를 반환할 지 설정할 수 있다. 그러나 한 응답에 몇 개의 객체 데이터를 담을 수 있는지에 대한 기본값이나 최댓값은 문서에 없는 것 같다. after/before는 각각 반환된 페이지의 시작과 끝을 가리키는 커서다. 이를 사용하여 요청을 보내면 다음/이전 페이지를 조회할 수 있는데, 이에 해당하는 요청이 next/previous이다. 만약 next 값이 없다면 마지막 페이지라는 뜻이고 preovious 값이 없다면 첫번째 페이지라는 뜻이다. 만약 객체 수가 적어 단일 응답에 모든 객체 데이터가 담긴다면 next나 previous라는 key 값은 확인할 수 없다.

 

Batch Requests

  일괄 요청은 여러 개의 graph api를 호출하는 하나의 HTTP 요청이다. 각 api 호출은 병렬적으로(종속적 작업은 순차적)으로 처리된 후, 모든 작업이 완료되면 통합된 응답으로 반환된다. 이러한 일괄 요청을 보내는 형식은 다음과 같다.

POST /ENDPOINT?batch=[JSON-OBJECT]
curl -i -X POST 'https://graph.facebook.com/me?batch=  
  [
    {
      "method":"GET",
      "relative_url":"PAGE-A-ID"
    },  
    {
      "method":"GET",
      "relative_url":"PAGE-B-ID"
    }
  ]
  &include_headers=false             // Included to remove header information
  &access_token=ACCESS-TOKEN'

  즉 batch 매개변수 내부에 json으로 각 api 요청에 대한 정보를 넣어주면 된다. 위 요청은 '/me/PAGE-A-ID'와 '/me/PAGE-B-ID' 요청을 한번에 보냈다고 할 수 있다. 이렇게 보낸 후 응답으로 문자열 인코딩 된 json 객체가 반환된다.

[
  {
    "code": 200,
    "body": "{
      \"name\": \"Page A Name\",
      \"id\": \"PAGE-A-ID\"
      }"
  },
  {
    "code": 200,
    "body": "{
      \"name\": \"Page B Name\",
      \"id\": \"PAGE-B-ID\"
      }"
  }
]

  더 복잡한 형식으로 일괄 요청을 활용할 수도 있지만 일단 이 정도로만 알고 넘어가자.

 

Nested Requests

  중첩 요청은 graph api의 필드 확장 기능이다. 이를 이용하면 여러 graph 쿼리를 단일 호출에 효과적으로 중첩할 수 있다. 중첩요청은 다음과 같은 형식을 가진다.

GET graph.facebook.com/{node-id}?fields=LEVEL-ONE{LEVEL-TWO}

  LEVEL-ONE은 상위 노드(node-id)의 하나 이상의 필드 또는 에지이고 LEVEL-TWO는 첫 번째 수준 노드의 하나 이상의 필드 또는 에지이다. 말이 좀 어렵긴 한데 예시를 보면 감이 잡힐 것이다.

GET graph.facebook.com
  /me?fields=albums.limit(5){name, photos.limit(2){name, picture, tags.limit(2)}},posts.limit(5)

  다음 요청을 앞에서부터 이해해보자. 우선 엔드포인트는 me(access token을 보유한 사용자나 페이지의 개체 id로 변환되는 특수 엔드포인트)이다. 그리고 필드값에 albums, posts라는 에지를 주고 있다. 그 중 albums는 name 필드와 photos라는 에지를 주고 있고 이 photos는 name, picture라는 필드값과 tags라는 에지를 주고 있다. 즉 본인이 가지고 있는 앨범들(albums)의 이름(name)과 각 앨범 속 사진들(photos)의 이름(name)과, 사진정보(picture), 사진의 태크들(tags) 그리고 본인이 가지고 있는 게시글에 대한 정보를 조회하는 요청인 것이다.

  중첩 요청은 요청 내용을 보면 알겠지만 데이터 계층 구조를 유지하고 있다. 그러므로 응답또한 데이터 계층 구조를 유지하게 된다. 이는 단일 요청에서 서로 연관되지 않은 graph api를 호출하는 일괄 요청과는 차이가 있다.

댓글