우편번호 / 주소 서비스 문서

우편번호 검색, 주소 검색, Place ID 기반 조회 등 우편번호 관련 API/서비스에 대한 상세 문서입니다.

# 우편번호 검색 API

## 📍 우편번호로 검색

우편번호를 입력하여 해당 주소 정보를 조회합니다.

### 요청

```
GET /api/v1/zipcode?zipcode={zipcode}&country={country}
```

### 파라미터

| 파라미터 | 타입 | 필수 | 설명 | 예시 |
|---------|------|------|------|------|
| `zipcode` | string | ✅ | 검색할 우편번호 | `06042` |
| `country` | string | ❌ | 국가 코드 (ISO 3166-1 alpha-2) | `KR` |

### 요청 예시

```bash
# 한국 우편번호 검색
GET /api/v1/zipcode?zipcode=06042&country=KR

# 국가 코드 생략 (기본값 사용)
GET /api/v1/zipcode?zipcode=06042
```

### 응답 예시

```json
{
"success": true,
"message": "우편번호 정보를 조회했습니다.",
"data": {
"id": 1,
"country_code": "KR",
"zipcode": "06042",
"state": "서울특별시",
"state_en": "Seoul",
"city": "강남구",
"city_en": "Gangnam-gu",
"district": null,
"district_en": null,
"town": "역삼동",
"town_en": "Yeoksam-dong",
"address": "서울특별시 강남구 테헤란로",
"address_en": "Teheran-ro, Gangnam-gu, Seoul",
"formatted_address": "서울특별시 강남구 테헤란로",
"latitude": 37.5010,
"longitude": 127.0394,
"place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
"place_name": "테헤란로",
"plus_code": null,
"bounds": {
"northeast": {
"lat": 37.5015,
"lng": 127.0400
},
"southwest": {
"lat": 37.5005,
"lng": 127.0390
}
},
"viewport": {
"northeast": {
"lat": 37.5015,
"lng": 127.0400
},
"southwest": {
"lat": 37.5005,
"lng": 127.0390
}
},
"place_types": ["route"],
"source": "google_places",
"retrieved_from": "database",
"last_synced_at": "2024-12-01T10:30:00+09:00",
"created_at": "2024-12-01T10:30:00+09:00",
"updated_at": "2024-12-01T10:30:00+09:00"
}
}
```

### 동작 방식

1. 데이터베이스에서 우편번호로 검색
2. 데이터가 없으면 Google Places API Geocoding API 호출
3. 조회한 정보를 데이터베이스에 저장
4. 결과 반환

---

## 💻 사용 예시

### cURL

```bash
# 우편번호로 검색
curl "http://localhost/api/v1/zipcode?zipcode=06042&country=KR"
```

### JavaScript (Fetch API)

```javascript
// 우편번호로 검색
async function searchByZipcode(zipcode, country = 'KR') {
const response = await fetch(
`/api/v1/zipcode?zipcode=${encodeURIComponent(zipcode)}&country=${country}`
);
const data = await response.json();

if (data.success) {
console.log('검색 결과:', data.data);
return data.data;
} else {
console.error('오류:', data.message);
return null;
}
}

// 사용 예시
searchByZipcode('06042', 'KR');
```

### PHP (Guzzle HTTP)

```php
use GuzzleHttp\Client;

$client = new Client(['base_uri' => 'http://localhost']);

// 우편번호로 검색
$response = $client->get('/api/v1/zipcode', [
'query' => [
'zipcode' => '06042',
'country' => 'KR'
]
]);
$data = json_decode($response->getBody(), true);
```

### Python (Requests)

```python
import requests

base_url = 'http://localhost/api/v1/zipcode'

# 우편번호로 검색
response = requests.get(f'{base_url}', params={
'zipcode': '06042',
'country': 'KR'
})
data = response.json()
```

---

---

## 🌍 국가별 우편번호 체계 및 조회 방식

### 한국 (KR)

**우편번호 형식**:
- 5자리 숫자 (예: `06042`)
- 패턴: `^[0-9]{5}$`

**행정구역 구조**:
```
시/도 (Level 1)
└─ 시군구 (Level 2)
└─ 읍면동 (Level 3)
└─ 상세주소 (Level 4)
```

**예시**:
- 우편번호: `06042`
- 주소: `서울특별시 강남구 역삼동 테헤란로`
- 구조: `서울특별시` → `강남구` → `역삼동` → `테헤란로`

**조회 방식**:
```bash
# 우편번호로 검색
GET /api/v1/zipcode?zipcode=06042&country=KR

# 주소로 검색 (계층적 검색)
GET /api/v1/zipcode/search?search=서울특별시 강남구 테헤란로&country=KR
```

**특화 필드**:
- Level 3: `sigungu_code` (시군구 코드), `region_code` (행정구역 코드)
- Level 4: `eupmyeon_type` (읍/면/동), `beopjeong_dong_code` (법정동 코드)

---

### 일본 (JP)

**우편번호 형식**:
- 7자리 숫자 (예: `150-0001`)
- 패턴: `^[0-9]{3}-[0-9]{4}$`
- 하이픈(`-`) 포함

**행정구역 구조**:
```
도도부현 (都道府県, Level 1)
└─ 시정촌 (市町村, Level 2)
└─ 구/정 (区/町, Level 3)
```

**예시**:
- 우편번호: `150-0001`
- 주소: `東京都渋谷区神宮前`
- 구조: `東京都` → `渋谷区` → `神宮前`

**조회 방식**:
```bash
# 우편번호로 검색 (하이픈 포함)
GET /api/v1/zipcode?zipcode=150-0001&country=JP

# 주소로 검색 (현지 언어 지원)
GET /api/v1/zipcode/search?search=東京都渋谷区&country=JP
```

**특화 필드**:
- Level 1: `jis_code` (JIS 코드), `prefecture_code` (도도부현 코드)
- Level 2: `jis_code`, `city_code` (시정촌 코드)
- Level 3: `ward_code` (구 코드), `town_code` (정 코드)

**주의사항**:
- 우편번호에 하이픈(`-`)을 포함해야 합니다
- 주소 검색 시 현지 언어(일본어) 사용 가능

---

### 미국 (US)

**우편번호 형식**:
- ZIP Code: 5자리 숫자 (예: `90210`)
- ZIP+4: 5자리 + 하이픈 + 4자리 (예: `90210-1234`)
- 패턴: `^[0-9]{5}(-[0-9]{4})?$`

**행정구역 구조**:
```
State (주, Level 1)
└─ County (카운티, Level 2)
└─ City (시, Level 3)
```

**예시**:
- 우편번호: `90210` 또는 `90210-1234`
- 주소: `Beverly Hills, CA 90210`
- 구조: `California` → `Los Angeles County` → `Beverly Hills`

**조회 방식**:
```bash
# ZIP Code로 검색 (5자리)
GET /api/v1/zipcode?zipcode=90210&country=US

# ZIP+4로 검색 (9자리)
GET /api/v1/zipcode?zipcode=90210-1234&country=US

# 주소로 검색
GET /api/v1/zipcode/search?search=Beverly Hills CA&country=US
```

**특화 필드**:
- Level 1: `fips_state_code` (FIPS 주 코드), `state_abbr` (주 약자, 예: CA, NY)
- Level 2: `fips_county_code` (FIPS 카운티 코드)

**주의사항**:
- ZIP+4 형식 사용 시 하이픈 포함
- 주 약자(State Abbreviation) 사용 가능 (예: CA, NY, TX)

---

### 중국 (CN)

**우편번호 형식**:
- 6자리 숫자 (예: `100000`)
- 패턴: `^[0-9]{6}$`

**행정구역 구조**:
```
성/시 (省/市, Level 1)
└─ 시/구 (市/区, Level 2)
└─ 구/현 (区/县, Level 3)
```

**예시**:
- 우편번호: `100000`
- 주소: `北京市朝阳区`
- 구조: `北京市` → `朝阳区` → `구/현`

**조회 방식**:
```bash
# 우편번호로 검색
GET /api/v1/zipcode?zipcode=100000&country=CN

# 주소로 검색 (현지 언어 지원)
GET /api/v1/zipcode/search?search=北京市朝阳区&country=CN
```

**특화 필드**:
- Level 1: `province_code` (성 코드), `admin_code` (행정 코드)
- Level 2: `city_code` (시 코드), `district_code` (구 코드)
- Level 3: `county_code` (현 코드)

**주의사항**:
- 주소 검색 시 현지 언어(중국어) 사용 가능
- 행정구역 코드는 국가 표준 코드 사용

---

## 📊 국가별 우편번호 체계 비교

| 국가 | 우편번호 형식 | 패턴 | 최대 레벨 | 예시 |
|------|--------------|------|----------|------|
| 한국 (KR) | 5자리 숫자 | `^[0-9]{5}$` | 4단계 | `06042` |
| 일본 (JP) | 7자리 (하이픈 포함) | `^[0-9]{3}-[0-9]{4}$` | 3단계 | `150-0001` |
| 미국 (US) | ZIP Code (5자리 또는 ZIP+4) | `^[0-9]{5}(-[0-9]{4})?$` | 3단계 | `90210` 또는 `90210-1234` |
| 중국 (CN) | 6자리 숫자 | `^[0-9]{6}$` | 3단계 | `100000` |

---

## 🔍 국가별 조회 방식 상세

### 1. 우편번호 직접 조회

모든 국가에서 동일한 방식으로 우편번호를 직접 조회할 수 있습니다:

```bash
GET /api/v1/zipcode?zipcode={zipcode}&country={country}
```

**국가별 예시**:
```bash
# 한국
GET /api/v1/zipcode?zipcode=06042&country=KR

# 일본 (하이픈 포함)
GET /api/v1/zipcode?zipcode=150-0001&country=JP

# 미국 (ZIP Code)
GET /api/v1/zipcode?zipcode=90210&country=US

# 미국 (ZIP+4)
GET /api/v1/zipcode?zipcode=90210-1234&country=US

# 중국
GET /api/v1/zipcode?zipcode=100000&country=CN
```

### 2. 주소 검색 (계층적 검색)

한국은 계층적 주소 검색을 지원합니다:

```bash
GET /api/v1/zipcode/search?search={주소}&country={country}
```

**검색어 토큰 개수에 따른 동작**:
- **토큰 0개**: 지역 목록 (zip_regions) 반환
- **토큰 1개**: 시/도별 시군구 그룹화 목록 반환
- **토큰 2개**: 시/도와 시군구별 도로명 그룹화 목록 반환
- **토큰 3개 이상**: 상세 우편번호 검색 결과 반환

**예시**:
```bash
# 시/도 목록
GET /api/v1/zipcode/search?country=KR

# 시/도별 시군구 목록
GET /api/v1/zipcode/search?search=서울특별시&country=KR

# 시/도와 시군구별 도로명 목록
GET /api/v1/zipcode/search?search=서울특별시 강남구&country=KR

# 상세 주소 검색
GET /api/v1/zipcode/search?search=서울특별시 강남구 테헤란로&country=KR
```

### 3. 행정구역 계층 조회

각 국가의 행정구역 계층을 조회할 수 있습니다:

**한국 (KR)**:
```bash
# 시/도 목록
GET /zipcode/country/kr

# 시/도별 시군구 목록
GET /zipcode/country/kr/region/{region_id}

# 시군구별 읍면동 목록
GET /zipcode/country/kr/region/{region_id}/level3/{level3_id}
```

**일본 (JP)**:
```bash
# 도도부현 목록
GET /zipcode/country/jp

# 도도부현별 시정촌 목록
GET /zipcode/country/jp/region/{region_id}

# 시정촌별 구/정 목록
GET /zipcode/country/jp/region/{region_id}/level3/{level3_id}
```

---

## 💡 국가별 우편번호 사용 팁

### 한국 (KR)
- ✅ 5자리 숫자만 입력하면 됩니다
- ✅ 주소 검색 시 계층적 검색 활용 가능
- ✅ 시/도 → 시군구 → 읍면동 순서로 검색하면 정확도 향상

### 일본 (JP)
- ⚠️ 우편번호 입력 시 하이픈(`-`)을 포함해야 합니다
- ✅ 현지 언어(일본어)로 주소 검색 가능
- ✅ 도도부현 → 시정촌 → 구/정 순서로 검색

### 미국 (US)
- ✅ ZIP Code (5자리) 또는 ZIP+4 (9자리) 모두 지원
- ✅ ZIP+4 사용 시 하이픈 포함
- ✅ 주 약자(State Abbreviation) 사용 가능 (예: CA, NY)

### 중국 (CN)
- ✅ 6자리 숫자만 입력하면 됩니다
- ✅ 현지 언어(중국어)로 주소 검색 가능
- ✅ 성/시 → 시/구 → 구/현 순서로 검색

---

## 📝 참고사항

- 국가 코드를 지정하면 검색 정확도가 향상됩니다
- 우편번호 형식은 국가마다 다를 수 있습니다
- 데이터베이스에 캐싱된 데이터는 빠르게 응답됩니다
- 국가별 특화 필드는 `metadata` JSON 필드에 저장됩니다
- 각 국가의 행정구역 구조는 `zip_countries.zipcode_schema`에서 확인할 수 있습니다