> For the complete documentation index, see [llms.txt](https://developers-apps-in-toss.toss.im/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers-apps-in-toss.toss.im/documentation/common/permission/contact.md).

# 연락처

{% hint style="info" %}
**권한 설정이 필요해요**

`fetchContacts`를 사용하기 전에 연락처 권한을 설정해야 해요. 권한 설정 가이드를 먼저 확인해 주세요.
{% endhint %}

***

### 연락처 가져오기

**SDK 함수:** `fetchContacts`

`fetchContacts`는 사용자의 연락처 목록을 페이지 단위로 가져오는 함수예요.

**시그니처**

```typescript
function fetchContacts(options: {
  size: number;
  offset: number;
  query?: {
    contains?: string;
  };
}): Promise<ContactResult>;
```

**파라미터**

* **options** · 필수

  연락처를 가져올 때 지정하는 옵션 객체예요.

  * **options.size** · 필수

    한 번에 가져올 연락처 개수예요. 예를 들어, 10을 전달하면 최대 10개의 연락처를 가져와요.
  * **options.offset** · 필수

    가져올 연락처의 시작 지점이에요. 처음 호출할 때는 `0`을 전달해야 해요. 이후에는 이전 호출에서 반환된 `nextOffset` 값을 사용해요.

    * **options.query** · 필수

      추가적인 필터링 옵션이에요.

      * **options.query.contains** · 필수

        이름에 특정 문자열이 포함된 연락처만 가져오고 싶을 때 사용해요. 이 값을 전달하지 않으면 모든 연락처를 가져와요.

**프로퍼티**

* openPermissionDialog

  연락처 읽기 권한을 다시 요청하는 다이얼로그를 표시해요. 사용자는 "허용", "한 번만 허용", "안하기" 중 하나를 선택할 수 있어요. "허용"이나 "한 번만 허용"을 선택하면 `allowed`를 반환하고, "안하기"를 선택하면 `denied`를 반환해요.
* getPermission

  연락처 읽기 권한의 현재 상태를 반환해요. `allowed`는 사용자가 연락처 읽기 권한을 허용한 상태예요. `denied`는 사용자가 연락처 읽기 권한을 거부한 상태예요. `notDetermined`는 연락처 읽기 권한 요청을 한 번도 하지 않은 상태예요. 토스앱 설정에서 연락처 권한이 거절되어 있는 경우에는 `osPermissionDenied`를 반환해요.

**반환 값**

* `Promise<ContactResult>`

연락처 목록과 페이지네이션 정보를 포함한 객체를 반환해요.

* `result`: 가져온 연락처 목록이에요.
* `nextOffset`: 다음 호출에 사용할 오프셋 값이에요. 더 가져올 연락처가 없으면 `null`이에요.
* `done`: 모든 연락처를 다 가져왔는지 여부를 나타내요. 모두 가져왔다면 `true`예요.

### 연락처 권한 에러

**에러 타입:** `FetchContactsPermissionError`

연락처 권한이 거부되었을 때 발생하는 에러예요. 에러가 발생했을 때 `error instanceof FetchContactsPermissionError`를 통해 확인할 수 있어요.

**시그니처**

```typescript
class FetchContactsPermissionError extends PermissionError {
  constructor();
}
```

**예제**

**특정 문자열이 포함된 연락처 목록 가져오기**

연락처 목록을 가져오는 예제예요. "권한 확인하기"버튼을 눌러서 현재 연락처 읽기 권한을 확인해요. 사용자가 권한을 거부했거나 시스템에서 권한이 제한된 경우에는 `FetchContactsPermissionError`를 반환해요. "권한 요청하기"버튼을 눌러서 연락처 읽기 권한을 요청할 수 있어요.

{% tabs %}
{% tab title="js" %}

```js
import { fetchContacts, FetchContactsPermissionError } from '@apps-in-toss/web-framework';

async function handleFetchContacts() {
  try {
    const response = await fetchContacts({
      size: 10,
      offset: 0,
      query: { contains: '김' },
    });

    return response;
  } catch (error) {
    if (error instanceof FetchContactsPermissionError) {
      console.log('연락처 읽기 권한 없음');
    }
    console.error('연락처를 가져오는 데 실패했어요:', error);
  }
}

async function handleGetPermissionForFetchContacts() {
  const permission = await fetchContacts.getPermission();
  return permission;
}

async function handleOpenPermissionDialogForFetchContacts() {
  const permission = await fetchContacts.openPermissionDialog();
  return permission;
}
```

{% endtab %}

{% tab title="React" %}

```tsx
import { ContactEntity, fetchContacts, FetchContactsPermissionError } from '@apps-in-toss/web-framework';
import { useState } from 'react';

function ContactsList() {
  const [contacts, setContacts] = useState<{
    result: ContactEntity[];
    nextOffset: number | null;
    done: boolean;
  }>({
    result: [],
    nextOffset: null,
    done: false,
  });

  const handlePress = async () => {
    try {
      if (contacts.done) {
        console.log('모든 연락처를 가져왔어요.');
        return;
      }

      const response = await fetchContacts({
        size: 10,
        offset: contacts.nextOffset ?? 0,
        query: { contains: '김' },
      });
      setContacts((prev) => ({
        result: [...prev.result, ...response.result],
        nextOffset: response.nextOffset,
        done: response.done,
      }));
    } catch (error) {
      if (error instanceof FetchContactsPermissionError) {
        console.log('연락처 읽기 권한 없음');
      }
      console.error('연락처를 가져오는 데 실패했어요:', error);
    }
  };

  return (
    <div>
      {contacts.result.map((contact, index) => (
        <span key={index}>
          {contact.name}: {contact.phoneNumber}
        </span>
      ))}
      <input
        type="button"
        value={contacts.done ? '모든 연락처를 가져왔어요.' : '다음 연락처 가져오기'}
        disabled={contacts.done}
        onClick={handlePress}
      />
      <input
        type="button"
        value="권한 확인하기"
        onClick={async () => {
          const permission = await fetchContacts.getPermission();
          alert(permission);
        }}
      />
      <input
        type="button"
        value="권한 요청하기"
        onClick={async () => {
          const permission = await fetchContacts.openPermissionDialog();
          alert(permission);
        }}
      />

  );
}
```

{% endtab %}

{% tab title="React Native" %}

```tsx
import { ContactEntity, fetchContacts, FetchContactsPermissionError } from '@apps-in-toss/framework';
import { useState } from 'react';
import { Alert, Button, Text, View } from 'react-native';

function ContactsList() {
  const [contacts, setContacts] = useState<{
    result: ContactEntity[];
    nextOffset: number | null;
    done: boolean;
  }>({
    result: [],
    nextOffset: null,
    done: false,
  });

  const handlePress = async () => {
    try {
      if (contacts.done) {
        console.log('모든 연락처를 가져왔어요.');
        return;
      }

      const response = await fetchContacts({
        size: 10,
        offset: contacts.nextOffset ?? 0,
        query: { contains: '김' },
      });
      setContacts((prev) => ({
        result: [...prev.result, ...response.result],
        nextOffset: response.nextOffset,
        done: response.done,
      }));
    } catch (error) {
      if (error instanceof FetchContactsPermissionError) {
        console.log('연락처 읽기 권한 없음');
      }
      console.error('연락처를 가져오는 데 실패했어요:', error);
    }
  };

  return (
    <View>
      {contacts.result.map((contact, index) => (
        <Text key={index}>
          {contact.name}: {contact.phoneNumber}
        </Text>
      ))}
      <Button
        title={contacts.done ? '모든 연락처를 가져왔어요.' : '다음 연락처 가져오기'}
        disabled={contacts.done}
        onPress={handlePress}
      />
      <Button
        title="권한 확인하기"
        onPress={async () => {
          const permission = await fetchContacts.getPermission();
          Alert.alert(permission);
        }}
      />
      <Button
        title="권한 요청하기"
        onPress={async () => {
          const permission = await fetchContacts.openPermissionDialog();
          Alert.alert(permission);
        }}
      />
    </View>
  );
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers-apps-in-toss.toss.im/documentation/common/permission/contact.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
