# AWS S3 버킷

AWS S3에서 이미지 데이터 저장을 다루고 Roboflow에 업로드할 때, 일반적으로 두 가지 옵션이 있습니다: 서명된 URL을 사용하거나, 이미지를 수동으로 로컬에 다운로드한 다음(AWS CLI를 통해) 로컬에서 업로드하는 방법입니다. 이 방법들 중 어떤 것을 선택할지는 데이터 처리 및 관리에 대한 구체적인 필요에 따라 달라집니다.

* **Signed URLs**: 이 방법은 이미지를 로컬 컴퓨터로 다운로드하는 데 수반되는 추가 단계와 시간 소모를 피하고 싶을 때 특히 유리합니다. 서명된 URL을 사용하면 이미지를 로컬에 저장할 필요 없이 S3에서 Roboflow API로 이미지 데이터를 직접 업로드할 수 있습니다. 그 결과 처리 속도는 더 빨라지고 로컬 시스템의 부하도 줄어듭니다.
* **CLI Locally**: 어떤 경우에는 먼저 이미지를 로컬 환경으로 다운로드하는 편을 선호할 수도 있습니다. 예를 들어 Roboflow에 업로드하기 전에 이미지를 전처리하거나 직접 확인해야 한다면, 로컬 사본이 있는 것이 유리합니다.

적절한 방법을 선택하는 것은 데이터 전송 속도, 전처리 필요성, 이미지의 수동 검수 여부와 같은 특정 사용 사례 요구사항에 따라 달라집니다.

### AWS CLI 설정

스크립트를 사용하기 전에, 필요한 인증 자격 증명으로 AWS CLI를 설정했는지 확인하세요. 이렇게 하면 원하는 S3 버킷에 접근하고 관리할 수 있습니다.

* [AWS CLI 버전 2 설치하기](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html)

#### AWS CLI 구성하기

1. AWS CLI를 설치한 후 터미널 또는 명령 프롬프트를 여세요.
2. 다음 명령을 실행하세요:

   ```bash
   aws configure
   ```
3. AWS 자격 증명을 입력하라는 메시지가 표시됩니다:

   ```
   AWS Access Key ID [None]: YOUR_ACCESS_KEY
   AWS Secret Access Key [None]: YOUR_SECRET_ACCESS_KEY
   Default region name [None]: YOUR_PREFERRED_REGION (예: us-west-1)
   Default output format [None]: json
   ```

### 옵션 1: Signed URL을 통해 업로드:

Python의 boto3를 사용하여 S3 버킷에 있는 이미지에 대한 서명된 URL을 생성할 수 있습니다.

```python
def generate_presigned_url(bucket_name: str, object_name: str, region: str = 'us-east-2') -> str:
    """S3 객체에 대한 presigned URL을 생성합니다."""
    s3 = boto3.client('s3', region_name=region, config=Config(signature_version='s3v4'))
    url = s3.generate_presigned_url('get_object',
                                    Params={'Bucket': bucket_name, 'Key': object_name},
                                    ExpiresIn=3600)
    return url
```

위 코드 조각에서는 S3 버킷 이름, S3 버킷 내 이미지의 객체 이름, 그리고 AWS 리전이 필요합니다. 이미지의 서명된 URL이 생성되어 반환됩니다.

이를 바탕으로, S3 버킷에 있는 사용 가능한 모든 객체를 가져온 다음 API를 통해 Roboflow에 업로드하는 완전한 솔루션을 만들 수 있습니다. 이 솔루션의 개요는 아래에서 확인할 수 있습니다:

```python
import boto3
import requests
import urllib.parse
from botocore.config import Config

# ************* 다음 변수를 설정하세요 *************
S3_BUCKET_NAME = "YOUR_S3_BUCKET_NAME"
ROBOFLOW_API_KEY = "YOUR_ROBOFLOW_API_KEY"
ROBOFLOW_PROJECT_NAME = "YOUR_ROBOFLOW_PROJECT_NAME"
# ***********************************************

def generate_presigned_url(bucket_name: str, object_name: str, region: str = 'us-east-2') -> str:
    """S3 객체에 대한 presigned URL을 생성합니다."""
    s3 = boto3.client('s3', region_name=region, config=Config(signature_version='s3v4'))
    url = s3.generate_presigned_url('get_object',
                                    Params={'Bucket': bucket_name, 'Key': object_name},
                                    ExpiresIn=3600)
    return url

def get_s3_objects(bucket_name: str) -> list:
    """주어진 S3 버킷의 객체 키 목록을 가져옵니다."""
    s3 = boto3.client('s3')
    objects = []
    response = s3.list_objects_v2(Bucket=bucket_name)
    for obj in response['Contents']:
        objects.append(obj['Key'])
    return objects

def upload_to_roboflow(api_key: str, project_name: str, presigned_url: str, img_name='', split="train"):
    """이미지를 Roboflow에 업로드합니다."""
    API_URL = "https://api.roboflow.com"
    if img_name == '':
        img_name = presigned_url.split("/")[-1]

    upload_url = "".join([
        API_URL + "/dataset/" + project_name + "/upload",
        "?api_key=" + api_key,
        "&name=" + img_name,
        "&split=" + split,
        "&image=" + urllib.parse.quote_plus(presigned_url),
    ])
    response = requests.post(upload_url)

    # 응답 코드 확인
    if response.status_code == 200:
        print(f"{img_name}을(를) {project_name}에 성공적으로 업로드했습니다")
        return True
    else:
        print(f"{img_name} 업로드에 실패했습니다. 오류: {response.content.decode('utf-8')}")
        return False

if __name__ == "__main__":
    # 사용 가능한 이미지 목록 가져오기
    available_images = get_s3_objects(S3_BUCKET_NAME)
    
    # 선택 사항: 여기서 이미지를 필터링
    # 예: available_images = [img for img in available_images if "some_condition"]
    
    # 이미지를 Roboflow에 업로드
    for image in available_images:
        presigned_url = generate_presigned_url(S3_BUCKET_NAME, image)
        upload_to_roboflow(ROBOFLOW_API_KEY, ROBOFLOW_PROJECT_NAME, presigned_url)

```

### 옵션 2: AWS에서 데이터를 로컬로 다운로드하기

AWS에서 데이터를 업로드하려면 먼저 `awscli` [명령줄 도구](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).를 설치하세요. 이 도구를 사용하면 명령줄에서 AWS 계정과 상호작용할 수 있습니다. 명령줄 도구를 설치한 후 다음 명령을 실행하세요:

```bash
aws s3 sync s3://mybucket/folder_path .
```

다음을 `mybucket` 버킷 이름과 `folder_path` 를 원하는 폴더 또는 내보내려는 파일 이름으로 바꾸세요. 이 명령은 AWS의 자산을 현재 작업 디렉터리(로 다운로드합니다 (`.`).

### Roboflow에 데이터 업로드

이제 데이터를 다운로드했으므로, 다음을 사용하여 Roboflow에 업로드할 수 있습니다. [업로드 웹 인터페이스](https://docs.roboflow.com/roboflow/roboflow-ko/datasets/adding-data/..#upload-data-with-the-web-interface) 또는 [Roboflow CLI](https://app.gitbook.com/s/e5GEiPeDoFksvZv1vH3A/command-line-interface/upload-a-dataset).

### 도 참고하세요

* [Roboflow 프로젝트 ID 가져오기](https://docs.roboflow.com/api-reference/workspace-and-project-ids)
