# OpenAI API 연결 오류: APIConnectionError는 경로부터 확인하세요

> APIConnectionError가 발생하면 키를 바꾸기 전에 같은 서버 프로세스의 연결 경로와 원래 예외를 확인하세요. DNS·인증서·프록시·엔드포인트에 맞는 수정과 Python·Node의 진단 설정, 같은 요청으로 복구를 확인하는 절차를 설명합니다.

- URL: https://blog.laozhang.ai/ko/posts/openai-api-error-connection-error
- Published: 2026-05-06
- Updated: 2026-10-07
- Author: LaoZhang AI Team (https://blog.laozhang.ai/ko/about)
- Topic: API 가이드
- Tags: OpenAI API, APIConnectionError, 연결 오류, SDK, API 오류

---
`openai.APIConnectionError: Connection error`가 발생하면 **실패한 서버 프로세스에서 실제 목적지와 원래 예외부터 확인하세요.** DNS 조회, TLS 인증서 검증, 프록시 연결, 외부 통신 허용 여부 중 어느 단계에서 실패했는지에 따라 고칠 설정이 달라집니다. 노트북에서 호출이 성공해도 컨테이너나 배포 서버의 연결이 정상이라는 뜻은 아닙니다.

반대로 `401`, `429`, `500`, `503`처럼 HTTP 응답을 받았다면 응답의 오류 본문을 읽어야 합니다. 연결 오류라는 문구 하나로 키를 재발급하거나 크레딧을 충전하지 마세요. OpenAI 공식 문서도 연결 문제와 API가 반환한 HTTP 오류를 구분합니다. [공식 오류 코드 안내](https://developers.openai.com/api/docs/guides/error-codes)

응답이나 요청 ID를 못 받았다고 **요청이 서버에 도착하지 않았거나 처리되지 않았다고 확정할 수는 없습니다.** 요청을 보낸 뒤 응답을 기다리다가 연결이 끊겼을 수도 있습니다. 특히 시간 초과와 스트리밍 중단은 재시도 전에 기존 처리 여부를 확인해야 합니다.

## 먼저 연결 실패와 HTTP 오류를 구분하세요

예외 이름, HTTP 상태, 응답의 오류 코드, 요청 ID를 함께 확인합니다. Python에서는 `APITimeoutError`가 `APIConnectionError`의 하위 클래스이므로 먼저 처리해야 시간 초과를 따로 기록할 수 있습니다. `APIStatusError`에는 반환된 HTTP 상태와 응답이 있습니다. JavaScript에서는 `APIConnectionTimeoutError`와 `APIConnectionError`를 구별합니다. [Python 오류 처리](https://developers.openai.com/api/reference/python), [JavaScript 오류 처리](https://developers.openai.com/api/reference/typescript)

| 실제로 확인한 증상 | 먼저 확인할 것 | 다음 조치 |
| --- | --- | --- |
| 연결 예외와 DNS 관련 원인 | 실제 hostname, 해당 프로세스의 DNS 설정 | 주소 오타 또는 배포 환경의 DNS 문제 수정 |
| 인증서 검증 또는 TLS 오류 | 인증서 신뢰 체인, CA 파일, 프록시의 TLS 처리 | 승인된 CA와 인증서 설정을 해당 HTTP 클라이언트에 적용 |
| 프록시 연결·인증 실패 | 사용 중인 프록시 주소와 전송 설정 | 승인된 프록시 설정과 런타임별 HTTP 클라이언트 설정 수정 |
| 시간 초과 | 연결·쓰기·읽기 중 실패 시점, SDK 재시도, 상위 요청 제한 시간 | 원인별 제한 시간과 전체 작업 시간을 함께 조정 |
| HTTP `401` 또는 `403` | 목적지 제공자, 키의 소속과 접근 권한 | 해당 제공자의 인증·권한 문제 해결 |
| HTTP `429` | 응답의 `error.code`, `error.type`, 제한 헤더 | [잔액·지출 한도·요청 제한 구분](https://blog.laozhang.ai/ko/posts/openai-api-rate-limit) |
| HTTP `500` 또는 `503` | 오류 본문, 요청 ID, 발생 시각과 서비스 상태 | 안내된 대기 조건에 따라 제한적으로 재시도하거나 지원 요청 |

중간 프록시가 자체 오류 페이지를 반환할 수도 있습니다. HTTP 상태가 있다는 사실과 OpenAI API의 응답을 받았다는 사실은 구별해야 합니다. 응답의 형식과 필요한 헤더를 확인하되 인증 헤더나 사용자 입력 전문을 로그에 남기지는 마세요.

## 같은 서버에서 실제 목적지를 확인하세요

검사는 실패한 애플리케이션이 실행되는 호스트·컨테이너·함수에서 시작합니다. 로컬 터미널과 배포 서버는 DNS, 프록시, 인증서 저장소, 외부 연결 정책이 다를 수 있습니다. 같은 컨테이너에서 실행한 curl도 SDK와 HTTP 클라이언트가 다르므로, 마지막 판단에는 **원래 프로세스의 SDK 오류와 실제 요청 결과**가 필요합니다.

우선 애플리케이션에 적용된 `base_url` 또는 `baseURL`의 scheme, hostname, port, 경로를 확인합니다. URL에 인증 정보나 민감한 쿼리가 들어 있다면 제거하고 기록하세요. 코드의 기본값만 보지 말고 배포 시 적용되는 환경 설정과 클라이언트 생성 인자를 맞춰 봅니다.

- OpenAI에 직접 요청하는 일반적인 API 경로는 `https://api.openai.com/v1`입니다. 다른 공식 엔드포인트를 사용 중이라면 그 설정을 기준으로 확인합니다.
- Azure OpenAI는 해당 리소스의 엔드포인트, 배포명, API 버전과 Azure 클라이언트 설정이 필요합니다. OpenAI의 일반 `base_url`과 섞지 않습니다.
- OpenAI 호환 게이트웨이는 그 제공자의 URL과 인증 방식이 기준입니다. 게이트웨이에서 실패했다는 이유만으로 OpenAI 직접 연결 장애라고 판단하지 않습니다.

Python의 기본 URL 재정의와 Azure 전용 설정은 [공식 SDK 참조](https://developers.openai.com/api/reference/python)에 설명되어 있습니다. 목적지를 바꾸는 것은 별도 제공자로 요청을 보내는 일이므로, 키를 임의의 호스트에 보내며 시험하지 마세요.

같은 시각의 [OpenAI 상태 페이지](https://status.openai.com/)도 확인합니다. 장애가 표시되면 오류 발생 시각·영향 서비스와 비교할 수 있지만, 정상 표시가 개별 서버의 연결 정상 여부를 증명하지는 않습니다. 게이트웨이나 Azure를 사용한다면 해당 제공자의 상태도 따로 확인해야 합니다.

## curl로 DNS·TLS·HTTP 응답을 좁혀 보세요

아래는 OpenAI에 직접 연결하는 경우의 **인증 없는 경로 확인 예시**입니다. 실패한 서버에서 실행하며 API 키를 넣지 않습니다. 다른 제공자를 사용 중이면 관리자가 확인한 HTTPS 주소와 인증 없이 확인해도 되는 경로를 사용하세요. 모델을 호출하는 추론 검사가 아니며, 성공하더라도 키·모델·계정의 정상 작동을 확인한 것은 아닙니다.

```bash
url='https://api.openai.com/v1/models'
curl -q --connect-timeout 5 --max-time 15 \
  --silent --show-error --output /dev/null \
  --write-out 'http=%{http_code} dns=%{time_namelookup}s connect=%{time_connect}s tls=%{time_appconnect}s total=%{time_total}s\n' \
  "$url"
curl_result=$?
printf 'curl_exit=%s\n' "$curl_result"
```

`-q`는 첫 인자로 두어 기본 curlrc를 읽지 않게 합니다. 프록시 환경 변수까지 무시하지는 않습니다. `--connect-timeout`은 DNS와 연결·TLS 협상에 걸리는 시간을 제한하고, `--max-time`은 이 호출의 전체 시간을 제한합니다. **위의 5초·15초는 진단 예시이며 권장 운영값이나 보장된 복구 시간은 아닙니다.** [curl 공식 설명](https://curl.se/docs/manpage.html)

| curl 결과 | 결과가 가리키는 범위 | 다음 확인 |
| --- | --- | --- |
| 종료 코드 `5` / `6` | 프록시 / 목적지 이름 조회 실패 | 프록시 hostname과 목적지 hostname을 구별해 DNS 확인 |
| `7` | 연결 실패 | 대상 포트, 승인된 외부 연결, 프록시 접근 가능 여부 확인 |
| `35` / `60` / `77` | TLS 협상 / 인증서 검증 / CA 파일 문제 | 원래 오류 메시지, 신뢰 체인, CA 파일 경로·권한 확인 |
| `28` | 설정한 시간 안에 완료하지 못함 | DNS·연결·TLS 시간과 애플리케이션의 실패 단계 비교 |
| `52` / `56` | 빈 응답 / 응답 수신 실패 | 프록시·로드밸런서·서버의 연결 종료 기록과 비교 |
| `97` | 프록시 협상 오류 | 프록시 주소, 인증 방식, 허용 대상 확인 |
| HTTP 응답과 종료 코드 `0` | curl이 HTTP 응답을 받음 | API 응답인지 중간 서버 응답인지 확인 후 SDK와 비교 |

이 예시는 `--fail`을 사용하지 않으므로 HTTP `401`, `429`, `503`도 curl 종료 코드 `0`과 함께 나올 수 있습니다. 프로세스의 성공과 API 요청의 성공은 다릅니다. `http=000`은 이 검사에서 HTTP 응답 코드를 얻지 못했다는 뜻이며, 다른 요청의 처리 여부나 과금 여부를 설명하지 않습니다. [curl 종료 코드](https://curl.se/docs/manpage.html)

## 원인에 맞는 설정을 고친 뒤 같은 검사를 반복하세요

![원래 서버나 컨테이너의 목적지, DNS·CA·프록시와 SDK 요청을 차례로 확인하는 그림](https://blog.laozhang.ai/posts/ko/openai-api-error-connection-error/img/same-process-network-checks.webp)

### DNS와 컨테이너 외부 연결이 실패한다면

실제 hostname의 오타와 잘못된 `base_url`을 먼저 수정합니다. 주소가 맞다면 컨테이너의 DNS 설정과 해당 클러스터·네트워크의 승인된 DNS 서버가 동작하는지 확인합니다. 호스트에서는 조회되지만 컨테이너에서는 실패한다면 컨테이너 쪽 DNS와 네트워크 구성을 수정할 근거가 됩니다.

이름 조회는 되는데 연결이 실패하면 컨테이너·함수의 외부 HTTPS 연결, 네트워크 정책, 방화벽, NAT 또는 승인된 프록시 경로를 확인합니다. 필요한 목적지와 포트의 통신을 운영 정책에 맞게 허용한 뒤 다시 검사합니다. 임의의 IP를 고정하거나 DNS를 우회하면 인증서 hostname 검증과 실제 서비스 라우팅을 함께 망가뜨릴 수 있습니다.

### TLS 인증서 검증이 실패한다면

CA 파일이 없는지, 애플리케이션 사용자에게 읽기 권한이 있는지, 필요한 신뢰 체인이 들어 있는지 확인합니다. 회사 프록시가 TLS를 처리하는 환경에서는 브라우저가 신뢰하는 회사 CA를 Python HTTP 클라이언트가 신뢰하지 않을 수 있습니다. 보안 담당자가 승인한 CA를 사용하고, 적용 후 **같은 클라이언트에서 인증서 검증이 정상인지** 확인하세요. 검증을 끄는 `verify=False`나 curl의 `-k`를 해결책으로 사용하지 않습니다.

2026년 10월 6일의 Python 참조는 `DefaultHttpx2Client`와 `SSLContext`를 통한 설정을 설명합니다. 아래는 해당 인터페이스를 지원하는 버전에서, 승인된 회사 CA를 추가하는 **클라이언트 구성 예시**입니다. 파일 경로를 실제 승인된 파일로 바꾸고 키·모델·엔드포인트는 기존 설정을 유지해야 합니다. 이 코드는 일반 서버 인증서 신뢰 설정이며, mTLS 등록이나 클라이언트 인증서가 필요하다는 뜻은 아닙니다. [Python HTTP 클라이언트 설정](https://developers.openai.com/api/reference/python)

```python
import ssl
from openai import OpenAI, DefaultHttpx2Client

context = ssl.create_default_context()
context.load_verify_locations(cafile="/approved/certs/company-ca.pem")

client = OpenAI(
    base_url="https://api.openai.com/v1",
    http_client=DefaultHttpx2Client(verify=context),
)
```

`OpenAI()`는 기본 인증 환경 설정을 사용합니다. 이 예시는 직접 OpenAI에 연결하는 서버용이며, 기존에 별도 키·프로젝트·엔드포인트를 지정했다면 그 설정을 함께 유지합니다. 이전 SDK가 HTTPX와 `DefaultHttpxClient`를 사용한다면 위 클래스 이름을 그대로 복사하지 말고 설치 버전의 문서에 맞추세요. 인증서 문제를 해결하려고 SDK 내부 파일을 수정하거나 무조건 업그레이드할 필요는 없습니다.

### 프록시를 사용한다면 실제 SDK 전송 설정에 적용하세요

curl이 프록시를 사용한다고 SDK도 같은 프록시를 사용하는 것은 아닙니다. 실제 프로세스에 적용된 프록시, 프록시 제외 대상, 사용자 지정 HTTP 클라이언트를 비교하세요. 프록시 인증 오류라면 승인된 인증 설정을 갱신하고, 허용 대상 문제라면 관리자가 API 목적지를 허용하도록 처리합니다. 접근 정책을 우회하기 위해 프록시를 임의로 끄지 않습니다.

현재 Python 문서의 `DefaultHttpx2Client`는 `proxy` 인자를 사용합니다. 위 예시의 HTTP 클라이언트를 `DefaultHttpx2Client(verify=context, proxy="http://proxy.example.internal:8080")`처럼 구성할 수 있지만, 주소는 조직에서 승인한 실제 프록시로 바꿔야 합니다. 프록시 URL에 인증 정보를 넣었다면 로그에 그대로 출력하지 않습니다. 이전 HTTPX 기반 구성은 생성자 인자가 다를 수 있습니다. [Python 프록시 설정](https://developers.openai.com/api/reference/python)

Node에서는 사용하는 `fetch`와 프록시 설정이 맞아야 합니다. 다음은 `undici`를 설치한 Node 서버에서 사용하는 구성 예시입니다. 프록시 인증, 인증서와 기존 키·프로젝트·목적지 설정은 해당 환경에 맞게 별도로 유지합니다.

```javascript
import OpenAI from "openai";
import { fetch as undiciFetch, ProxyAgent } from "undici";

const dispatcher = new ProxyAgent("http://proxy.example.internal:8080");
const client = new OpenAI({
  fetch: undiciFetch,
  fetchOptions: { dispatcher },
  maxRetries: 0,
  timeout: 30_000,
});
```

이 예시에서 `dispatcher`는 `undiciFetch`와 함께 쓰는 설정입니다. 다른 fetch 구현에 이 옵션만 붙여도 된다고 가정하지 마세요. Bun은 `proxy`, Deno는 `createHttpClient`를 사용하는 등 구성이 다르며, 모든 런타임이 프록시 환경 변수를 자동으로 따르는 것도 아닙니다. [JavaScript 런타임별 프록시 설정](https://developers.openai.com/api/reference/typescript)

## Python에서 원래 예외와 요청 ID를 기록하는 방법

연결 예외에 붙은 `__cause__`를 확인하면 DNS·TLS·읽기 시간 초과 등 실제 원인을 좁힐 수 있습니다. 처음에는 예외 종류와 오류 코드만 기록하고, 더 자세한 메시지가 필요할 때 민감한 URL·인증 정보·사용자 내용을 제거합니다.

아래 함수는 **이미 올바르게 구성한 동기식 OpenAI 클라이언트**를 받습니다. 별도의 프로세스를 만드는 대신 원래 실패한 프로세스에 붙여 사용합니다. `model`과 `input_text`도 호출자가 전달하므로, 적용하려면 기존 코드에서 `diagnose_response(client, model, input_text)`를 호출해야 합니다. 실제 호출은 사용량에 따라 과금될 수 있습니다. 진단 중 자동 재시도를 끄고 30초의 timeout을 지정하며, 이 시간은 예시입니다.

```python
import uuid
import openai


def cause_types(error):
    result = []
    seen = set()
    cause = error.__cause__
    while cause is not None and id(cause) not in seen:
        seen.add(id(cause))
        result.append({
            "type": type(cause).__name__,
            "errno": getattr(cause, "errno", None),
        })
        cause = cause.__cause__
    return result


def diagnose_response(client, model, input_text):
    client_id = str(uuid.uuid4())
    try:
        response = client.with_options(
            max_retries=0, timeout=30.0
        ).responses.create(
            model=model,
            input=input_text,
            extra_headers={"X-Client-Request-Id": client_id},
        )
        print({"result": "success", "request_id": response._request_id,
               "client_id": client_id})
        return response
    except openai.APITimeoutError as error:
        print({"result": "timeout", "causes": cause_types(error),
               "client_id": client_id})
        raise
    except openai.APIConnectionError as error:
        print({"result": "connection", "causes": cause_types(error),
               "client_id": client_id})
        raise
    except openai.APIStatusError as error:
        print({"result": "http_error", "status": error.status_code,
               "request_id": error.request_id, "client_id": client_id})
        raise
```

시간 초과를 부모 예외보다 먼저 잡고, 오류를 기록한 뒤 다시 발생시키므로 호출자가 실패를 성공으로 오해하지 않습니다. `APIStatusError`에서는 상태와 요청 ID를 얻고 응답 본문의 필요한 오류 필드를 추가로 확인할 수 있습니다. 사용자 지정 전송기나 hook에서 발생한 애플리케이션 예외는 SDK 연결 오류로 변환되지 않고 그대로 전달될 수 있습니다. [Python 예외·요청 ID 참조](https://developers.openai.com/api/reference/python)

설치된 `openai` 버전과 현재 프로세스가 사용하는 Python 환경도 함께 기록하세요. 다른 가상 환경을 업그레이드해 놓고 서버는 이전 SDK를 계속 사용하는 경우에는 설정 변경이 적용되지 않습니다. 연결 풀은 적절한 애플리케이션 수명 동안 재사용하고, 종료 시 닫습니다. 비동기 클라이언트는 사용 중인 이벤트 루프에 맞춰 관리하고 루프 종료 전에 `await client.close()`로 정리합니다. [Python 연결 자원 관리](https://developers.openai.com/api/reference/python)

## Node에서는 시간 단위와 cause를 확인하세요

JavaScript SDK의 `timeout`은 밀리초입니다. Python의 `timeout=30.0`을 Node에 `timeout: 30`으로 옮기면 30초가 아닌 30밀리초가 됩니다. 두 SDK의 기본 제한 시간은 현재 문서상 10분이고 재시도는 기본 두 번이지만, 이 기본값이 작업 큐·웹 서버·서버리스 함수의 전체 제한 시간까지 맞춰 주지는 않습니다. [JavaScript timeout·재시도](https://developers.openai.com/api/reference/typescript), [Python timeout](https://developers.openai.com/api/reference/python)

아래는 기존 Node 클라이언트에서 Responses 호출을 진단하는 함수입니다. 사용자 입력과 키, 전체 오류 객체는 출력하지 않습니다. API 호출 함수이므로 연결 검사만 하려는 경우에는 실행하지 않습니다.

```javascript
import OpenAI from "openai";
import { randomUUID } from "node:crypto";

export async function diagnoseResponse(client, model, input) {
  const clientId = randomUUID();
  try {
    const response = await client.responses.create(
      { model, input },
      { maxRetries: 0, timeout: 30_000,
        headers: { "X-Client-Request-Id": clientId } },
    );
    console.log({ result: "success", requestId: response._request_id,
                  clientId });
    return response;
  } catch (error) {
    if (error instanceof OpenAI.APIConnectionTimeoutError) {
      console.log({ result: "timeout", clientId });
    } else if (error instanceof OpenAI.APIConnectionError) {
      console.log({ result: "connection", clientId,
                    causeName: error.cause?.name,
                    causeCode: error.cause?.code });
    } else if (error instanceof OpenAI.APIError) {
      console.log({ result: "api_error", status: error.status,
                    requestId: error.request_id, clientId });
    }
    throw error;
  }
}
```

`cause`가 없다면 더 구체적인 원인을 얻지 못한 것입니다. 있다고 해도 오류 코드 하나를 모든 환경에서 동일한 원인으로 해석하지 말고, 사용 중인 fetch와 프록시의 오류를 함께 확인하세요. AbortSignal로 요청을 취소한 경우에도 서버 처리와 과금이 취소됐다는 의미로 받아들이면 안 됩니다.

## timeout·재시도·스트리밍 중단은 어떻게 처리하나요?

![시간 단위와 재시도 예산을 확인하고 끊긴 스트림의 부분 결과와 추적 ID를 보존하는 그림](https://blog.laozhang.ai/posts/ko/openai-api-error-connection-error/img/timeout-stream-recovery-evidence.webp)

연결 단계에서 시간 초과가 나면 DNS, 외부 연결과 프록시를 먼저 고칩니다. 연결 후 읽기 시간 초과가 나면 요청 크기·처리 시간, 응답이 오가는 중간 서버의 제한 시간, 스트리밍 유휴 제한을 함께 확인합니다. 실제 처리에 필요한 시간이 클라이언트 설정을 넘는 것으로 확인되면 읽기 제한을 조정하고, 작업 전체가 상위 서버의 제한 시간 안에 끝나는지도 맞춰야 합니다. 긴 작업을 웹 요청 안에서 계속 기다릴 수 없다면 큐나 비동기 처리로 옮기는 설계를 검토합니다.

재시도는 수정 후 한 번의 요청으로 원인을 확인한 다음 적용합니다. 현재 Python SDK는 연결 오류와 `408`, `409`, `429`, `5xx`를 기본 재시도 대상으로 설명하지만, 다시 보낼 수 있는 요청 본문에 한합니다. SDK와 작업 큐 양쪽에서 반복하면 한 작업이 여러 요청으로 늘어나므로 총 시도 횟수와 전체 대기 시간을 함께 제한하세요. 차단된 외부 연결, 틀린 CA, 잘못된 목적지는 재시도 횟수를 늘려도 고쳐지지 않습니다. [Python 재시도 조건](https://developers.openai.com/api/reference/python)

스트리밍 도중 일부 텍스트를 받았다면 시작부터 다시 보내는 것이 단순한 복구가 아닙니다. 이미 사용자에게 표시한 출력이 중복될 수 있고, 도구 실행이나 후속 작업도 두 번 수행될 수 있습니다. 부분 결과를 저장하고 해당 작업을 실패·미완료로 표시한 뒤, 애플리케이션이 지원하는 복구 방식과 중복 처리 정책에 따라 재개하거나 새로 시작합니다. 현재 Python의 `Stream`·`AsyncStream` 읽기 실패는 자동으로 재생하지 않으며, Assistants helper와 raw `with_streaming_response`는 별도의 기존 동작을 유지합니다. [스트리밍 예외 처리](https://developers.openai.com/api/reference/python)

응답을 못 받은 timeout에는 처리 여부가 불확실한 구간이 있습니다. 이를 확인할 때 `X-Client-Request-Id`가 도움이 됩니다. OpenAI는 지원되는 엔드포인트에서 이 값을 기록하고, 서버의 요청 ID를 못 얻었을 때 지원팀이 수신 여부를 찾는 데 사용할 수 있다고 설명합니다. 값은 직접 지정해야 하며 ASCII 512자 이하입니다. 위 예시의 UUID는 호출별 식별용으로 사용합니다. **이 헤더는 중복 실행을 막는 idempotency key가 아니며 과금 여부를 보장하지 않습니다.** 다른 제공자는 별도 문서를 확인해야 합니다. [클라이언트 요청 ID 안내](https://developers.openai.com/api/reference/overview#supplying-your-own-request-id-with-x-client-request-id)

## 복구 확인은 원래 SDK와 같은 요청 조건으로 하세요

설정을 고친 뒤에는 다음 순서로 확인합니다.

1. 실패했던 실행 환경에서 같은 목적지로 DNS·TLS·HTTP 경로 검사를 반복합니다. 원래 실패 단계가 정상으로 바뀌었는지 기록합니다.
2. 원래 프로세스의 SDK, 키·프로젝트, 제공자·모델 설정을 유지하고 자동 재시도와 병렬 실행을 멈춘 상태에서 작은 요청 하나를 보냅니다. 이 단계는 실제 API 사용이며 비용이 발생할 수 있습니다.
3. 정상 응답과 요청 ID를 받으면 입력 크기와 출력 조건을 원래 업무에 맞춰 확인합니다. 원래 작업이 스트리밍이면 스트리밍이 끝까지 완료되는지도 확인해야 합니다.
4. 낮은 동시 실행 수로 업무를 재개하고 연결 오류·시간 초과·HTTP 오류를 따로 관찰합니다. 처리량을 늘렸을 때만 실패한다면 연결 풀과 큐, 외부 통신 용량을 다시 점검합니다.

경로 검사 뒤 `401`이나 `429`가 반환된다면 다음에 해결할 문제가 인증 또는 계정·요청 한도로 바뀐 것입니다. 연결 오류가 사라졌더라도 전체 업무가 복구된 것은 아닙니다. 다른 호스트나 모델에서 성공한 결과로 원래 배포·모델의 복구를 대신 판단하지 마세요.

오류가 지속되어 지원 요청이 필요하면 발생 시각과 시간대, 제공자와 민감 정보가 제거된 URL, 런타임·SDK·전송 클라이언트 버전, 프록시 사용 여부, 실패 단계, 예외 종류·원인, HTTP 상태와 요청 ID를 정리합니다. 클라이언트 요청 ID를 보냈다면 함께 적고, 어떤 설정을 바꿨을 때 어떤 결과가 달라졌는지도 남깁니다. API 키·프록시 비밀번호·인증 헤더·사용자 입력 전문은 제외합니다.

## 자주 묻는 질문

### APIConnectionError가 나오면 OpenAI 장애인가요?

예외 이름만으로는 알 수 없습니다. 실제 서버의 DNS·TLS·프록시·외부 연결 또는 엔드포인트 설정이 원인일 수 있습니다. 오류 발생 시각의 [서비스 상태](https://status.openai.com/)와 같은 환경의 검사 결과를 함께 보세요. OpenAI 공식 문서도 네트워크, 프록시, 인증서, 방화벽과 컨테이너 설정을 확인하도록 설명합니다. [오류 코드 안내](https://developers.openai.com/api/docs/guides/error-codes)

### 로컬에서는 되는데 Docker에서만 실패하면 무엇부터 보나요?

컨테이너 안의 실제 목적지, DNS, 승인된 외부 HTTPS 경로와 CA 파일부터 비교합니다. 호스트 브라우저의 인증서·프록시 설정이 컨테이너의 Python이나 Node에 적용되어 있다고 가정하지 마세요. 그다음 같은 컨테이너의 원래 SDK에서 예외 원인을 확인합니다. curl 성공만으로 SDK의 전송 설정까지 정상이라고 판단할 수는 없습니다.

### request ID가 없으면 처리되지 않았으니 다시 보내도 되나요?

그렇게 단정할 수 없습니다. 요청을 보낸 뒤 응답이 끊겼다면 서버에서 처리했을 가능성이 남습니다. timeout과 부분 스트리밍은 기존 작업 상태·사용량 기록과 후속 작업을 확인한 다음 재실행 여부를 결정하세요. `X-Client-Request-Id`는 지원팀의 요청 추적에 도움이 되지만 중복 방지나 무료 처리 보장은 아닙니다. [공식 요청 ID 설명](https://developers.openai.com/api/reference/overview#supplying-your-own-request-id-with-x-client-request-id)

### API 키를 바꾸거나 6초 기다리면 해결되나요?

보장되지 않습니다. `401`이면 해당 제공자의 인증 설정을 확인하지만, DNS 실패나 인증서·프록시 문제에는 그 원인을 고쳐야 합니다. 현재 SDK 문서는 기본 재시도와 지수 백오프를 설명하며 모든 연결 오류에 고정된 6초 대기나 클라이언트 재생성을 요구하지 않습니다. 원래 예외와 실패 단계를 기준으로 조치하세요. [Python 재시도 설명](https://developers.openai.com/api/reference/python)

이 글의 코드는 공식 SDK 인터페이스를 바탕으로 만든 설명용 예시이며 구문과 합성 오류 처리만 확인했습니다. 실제 계정·네트워크·유료 API 요청을 실행한 복구 실험은 아닙니다.

## 참고 자료

이 글이 링크한 외부 페이지를 본문에 나온 순서대로 정리했습니다. 마지막 업데이트: 2026-10-07.

- [공식 오류 코드 안내](https://developers.openai.com/api/docs/guides/error-codes) (developers.openai.com)
- [Python 오류 처리](https://developers.openai.com/api/reference/python) (developers.openai.com)
- [JavaScript 오류 처리](https://developers.openai.com/api/reference/typescript) (developers.openai.com)
- [OpenAI 상태 페이지](https://status.openai.com/) (status.openai.com)
- [curl 공식 설명](https://curl.se/docs/manpage.html) (curl.se)
- [클라이언트 요청 ID 안내](https://developers.openai.com/api/reference/overview) (developers.openai.com)
