Post

Google Drive를 객체 스토리지로 사용하기

Google Drive를 객체 스토리지로 사용하기

이번 글에서는 Google Drive를 웹서비스의 객체 스토리지로 사용하는 방법에 대해 알아볼 것이다.

구글 드라이브를 객체 스토리지로 사용하기 위해서는 당연하겠지만 먼저 구글 드라이브가 필요하다. 그리고 구글 드라이브 API를 이용해서 어플리케이션이 구글 드라이브에 요청을 보낼 수 있도록 세팅을 해야 한다.

1. Upload

1.1 구글 드라이브 API 설정

어플리케이션을 통해 구글 드라이브에 파일을 업로드하려면 구글 드라이브 API를 활용해야 한다. 이를 위해 다음 단계들을 수행해야 한다.

  1. Google Cloud Console에서 프로젝트 생성
  2. Google Drive API 활성화
  3. OAuth 2.0 자격 증명 생성 (서비스 계정)
  4. 서비스 계정에 필요한 권한 추가
  5. credentials.json 다운로드 및 프로젝트에 추가

Google Cloud Console에 접속해서 검색창에 ‘프로젝트 만들기’를 검색하자.

프로젝트_생성.png

그리고 프로젝트를 생성한다. 그냥 프로젝트 이름과 조직을 설정하면 된다.

사용자_인증_정보.png

그 다음 사진에서 보이는 -이 세로로 세줄 그어져 있는 걸 클릭해서, ‘API 및 서비스’ > ‘사용자 인증 정보’ 탭으로 이동한다.

oauth_클라이언트_id_만들기.png

그 다음 ‘OAuth 클라이언트 ID 만들기’ 탭으로 이동한다.

동의_화면_구성.png

그럼 먼저 동의 화면을 구성해야 한다고 안내받게 된다. 그래서 ‘동의 화면 구성’ 버튼을 누르면

인증_플랫폼_구성.png

인증 플랫폼을 먼저 구성하도록 안내해준다. 그 안내에 따라서 인증 플랫폼을 구성해 만들어준다.

인증_플랫폼_구성2.png

그 후에 앱 정보에서 앱 이름은 헷갈리지 않게 되도록 프로젝트 이름과 동일하게 설정하고 지원 이메일에는 자신의 이메일을 입력하거나, 별도의 지원 이메일을 입력한다.
개발자 연락처 정보에는 개발자 이메일을 입력한다.

유저타입.png

이제 다시 OAuth 동의 화면을 구성한다. 여기에서는 ‘외부’를 선택한다.

앱정보.png

앞에서 입력했듯이 동일하게 기입해준다. 나머지는 꼭 입력해야하는 게 없다. 필요하다면 추가하도록 하자.

oauth_클라이언트_id_만들기2.png 그 다음 ‘OAuth 클라이언트 ID를 만들기’ 로 돌아와서 진행한다. 우리는 스프링 서버가 사용할 클라이언트 ID를 만들 것이기 때문에 웹 애플리케이션을 골라준다.

oauth_클라이언트_id_만들기3.png

그 후에 본인 서버의 URI를 ‘승인된 JavaScript 원본’에 추가하고, 서버가 Google에서 인증을 받은 후 리다이렉션 될 URI를 ‘승인된 리디렉션 URI’ 에 추가한 후 저장한다.

생성된 OAuth 2.0 클라이언트 ID를 다운받는다. ‘사용자 인증 정보’ 탭에서 생성한 ID의 작업 컬럼에서 다운로드 버튼을 누르고 ‘JSON 다운로드’ 를 클릭하면 된다.

여기까지 수행했다면 이제 쉽다. 고생많았다.

이제 Google Drive API를 검색해 사용 설정을 한다.

google_drive_api_사용.png

사용 버튼을 누르면 된다.

1.2 서버 코드 작성

구글 드라이브 설정이 끝났으므로, 이제 클라이언트 → 서버 → 구글 드라이브 로 객체가 업로드 될 수 있게 개발해야 한다.

이 예시에서는 서버가 스프링 서버라는 것을 전제로 한다.
의존성 부터 추가하자.

1
2
3
4
5
6
7
// Google Drive
implementation 'com.google.apis:google-api-services-drive:v3-rev20250210-2.0.0'
implementation 'com.google.api-client:google-api-client:1.33.0' // api client
implementation 'com.google.auth:google-auth-library-oauth2-http:1.19.0' // Google Authentication
implementation 'com.google.http-client:google-http-client-gson:1.43.3' // JSON Factory
implementation 'com.google.http-client:google-http-client:1.43.3' // HTTP Client (NetHttpTransport 관련)
implementation 'com.google.api-client:google-api-client-gson:2.2.0' // Google API Client Core
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Slf4j
@Service
public class GoogleDriveService {
    public final Drive driveService;
    private static final String APPLICATION_NAME = ""; // 변경 필요
    private static final GsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
    private static final List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE_FILE);
    private static final String CREDENTIALS_FILE_PATH = ""; // 변경 필요

    public GoogleDriveService() throws IOException {
        driveService = getDriveService();
    }

    private static Drive getDriveService() throws IOException {
        InputStream in = new FileInputStream(CREDENTIALS_FILE_PATH);
        GoogleCredentials credentials = GoogleCredentials.fromStream(in).createScoped(SCOPES);

        return new Drive.Builder(new NetHttpTransport(), JSON_FACTORY, new HttpCredentialsAdapter(credentials))
                .setApplicationName(APPLICATION_NAME)
                .build();
    }
}

업로드를 하는 역할을 맡을 객체를 만든다. 필자는 이렇게 만들었다.

여기에서 DriverScopes는 Google Drive API를 통해 수행할 수 있는 작업 권한의 범위를 지정한다. 필요하지 않은 권한까지 포함하는 것은 운영 이슈로 이어질 수 있기 때문에 본인의 케이스에 맞는 범위를 선택하는 것을 권장한다.

google_drive_api_scope.png Google Drive API 공식 문서 발췌

위의 표의 ‘사용’ 열에 기재된 표현에 대한 자세한 민감도는 다음과 같다. 이 또한 공식 문서에서 발췌했다.

  • 권장 / 민감하지 않음: 이 범위는 가장 작은 승인 액세스 범위를 제공하며 기본 앱 인증만 필요하다. 이 요구사항에 관한 자세한 내용은 인증 요구사항을 참고하자.
  • 권장 / 민감한 정보: 이러한 범위는 사용자가 앱에 대해 승인한 특정 Google 사용자 데이터에 대한 액세스 권한을 제공한다. 추가 앱 인증을 거쳐야 합니다. 이 요구사항에 대한 자세한 내용은 민감한 정보 및 제한된 범위 요구사항을 참고하자.
  • 제한됨: 이러한 범위는 Google 사용자 데이터에 대한 광범위한 액세스 권한을 제공하며 제한된 범위 확인 절차를 거쳐야 한다. 이러한 요구사항에 대한 자세한 내용은 Google API 서비스 사용자 데이터 정책특정 API 범위의 추가 요구사항을 참고하자. 제한된 범위의 데이터를 서버에 저장하거나 전송하는 경우 보안 평가를 거쳐야 한다.

이렇게 생성한 Drive 객체를 이용해 파일을 업로드 할 수 있다. 아래의 예제는 폴더를 생성한 후 그 곳에 업로드하는 코드이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class GoogleDriveService {
    
    public String makeFolder(Drive driverService, String folderName) throws IOException {
        String query = "mimeType='application/vnd.google-apps.folder' and name='" + folderName;
        List<File> files = driverService.files().list().setQ(query).setSpaces("drive").execute().getFiles();
        
        if (!files.isEmpty()) {
            return files.get(0).getId();
        }

        File fileMetadata = new File();
        fileMetadata.setName(folderName);
        fileMetadata.setMimeType("application/vnd.google-apps.folder");
        if (parentFolderId != null) {
            fileMetadata.setParents(Collections.singletonList(parentFolderId));
        }

        File folder = driveService.files().create(fileMetadata).setFields("id").execute();
        return folder.getId();
    }
    
    public String uploadFile(java.io.File uploadFile, String seller, String buyer, String orderDate, String folderId) throws IOException {
        folderId = makeFolder(driveService, forderName);

        File fileMetadata = new File();
        fileMetadata.setName(uploadFile.getName());
        fileMetadata.setParents(Collections.singletonList(folderId));

        AbstractInputStreamContent mediaContent = new FileContent("application/octet-stream", uploadFile);
        File uploadedFile = driveService.files().create(fileMetadata, mediaContent)
                .setFields("id, parents")
                .execute();
        return uploadedFile.getId();
    }
}

2. Download

다운로드 기능은 구글 드라이브의 객체들이 가지고 있는 고유한 ID값을 이용해 구현할 수 있다. 서버에서 객체 스토리지를 사용하는 시나리오에서는 사용자가 업로드한 객체들만 다운로드하는 논리로 사용되는 경우가 많기 때문에, 1.2 절의 예시 코드에서 처럼 업로드 시 ID값을 얻어두었다가, 이를 이용하여 해당 객체를 식별하게 끔 개발하면 된다.

예시 코드는 다음 주에 추가하겠다.

This post is licensed under CC BY 4.0 by the author.