[중요] File Storage 사용자 가이드 문서 지원 종료 (Deprecated) 안내


  • 네이버 클라우드 플랫폼 서비스 정책상 장기적으로 File Storage는 서비스 및 유지보수 지원을 중지할 계획입니다.

    • 현재 이용중인 서비스에는 문제가 없도록 유지할 계획이지만, 부가 기능 및 연동 상품 이용 개선에 대해서는 제약이 있을 수 있습니다.
  • 편리한 기능 제공과, 상품간 원활한 인터페이스 및 연동을 위해서 Object Storage로 전환하는 것을 고객분들께 권고드립니다.

    • 단기적으로 Object Storage로 전환이 어려우시더라도 중장기적으로 Object Storage로의 전환에 대해 긍정적으로 검토 부탁드립니다.
    • Object Storage로 전환하실 때 필요하신 데이터 이관 등은 저희가 최대한 지원해드리도록 하겠습니다.

File Storage에서 Object Storage로의 마이그레이션에 대해서는 고객지원으로 문의하여 주시기 바랍니다.

개요

File Storage란

네이버 클라우드 플랫폼 File Storage는 사용자가 언제 어디서나 원하는 데이터를 저장하고 탐색할 수 있도록 파일 저장 공간을 제공하는 서비스입니다. 다음과 같은 용도로 사용할 수 있습니다.

  • 파일 단위의 데이터 저장, 공유, 배포: 콘텐츠를 저장하고 다른 사용자에게 공유하거나 배포할 수 있습니다.
  • 대용량 저장소: 대용량의 데이터 저장소로 활용할 수 있습니다.
  • 데이터 백업 및 장기 보관: 중요한 데이터를 백업하거나 장기 보관할 수 있습니다.

기능 및 특징

네이버 클라우드 플랫폼 File Storage는 다음과 같은 특징이 있습니다.

  • 컨테이너라고 불리는 대용량의 파일 저장 공간을 제공합니다.
  • 사용자 인터페이스로 네이버 클라우드 플랫폼 콘솔 외에도 CLI(command line interface), REST API, Java API를 제공합니다.
  • 특정 파일에 대한 읽기 권한을 PUBLIC으로 설정하면 URL을 아는 누구나 일반 브라우저에서 해당 파일에 접근할 수 있습니다.
  • 저장된 개체 파일에 URL로 직접 접근할 수 있습니다.
  • 데이터 저장 시 3개의 복제본을 유지하므로 데이터 내구성이 높습니다.
  • 실시간으로 자주 쓰는(write) 데이터보다는 한 번 저장한 후에 자주 읽는(read) 데이터 타입이 적합합니다.
  • CLI와 운영체제의 작업 스케줄러 기능을 이용하여 서버 백업을 자동화할 수 있습니다.

※ 참고 : 컨테이너 생성, 권한 관리, 삭제 등의 컨테이너 관리 기능은 네이버 클라우드 플랫폼 콘솔에서만 사용할 수 있습니다.

File Storage 사용 방법

네이버 클라우드 플랫폼 File Storage 서비스를 사용하려면 상품 소개 페이지에서 상품 신청하기를 눌러 서비스 사용 신청을 합니다. 네이버 클라우드 플랫폼 File Storage를 쉽고 편리하게 사용할 수 있도록 네이버 클라우드 플랫폼 콘솔을 비롯해 네이버 클라우드 플랫폼 File Storage CLI와 REST API, 자바 라이브러리를 제공합니다.

네이버 클라우드 플랫폼 콘솔 사용하기

상품 신청을 하고 나면 네이버 클라우드 플랫폼 콘솔 페이지로 이동합니다. 네이버 클라우드 플랫폼 콘솔을 이용해 컨테이너를 생성하고 파일 및 폴더를 관리할 수 있습니다. 자세한 사용 방법은 "네이버 클라우드 플랫폼 콘솔 사용하기"를 참고합니다.

네이버 클라우드 플랫폼 File Storage CLI 사용하기

또 다른 사용자 인터페이스로 네이버 클라우드 플랫폼 File Storage CLI를 제공합니다. 네이버 클라우드 플랫폼 File Storage CLI를 이용해 폴더 생성/삭제, 파일 업로드/다운로드, 목록 조회 등을 수행할 수 있으며, 운영체제의 작업 스케줄러와 함께 사용해서 서버 데이터의 주기적인 백업 작업을 자동화할 수도 있습니다. 자세한 사용 방법은 "네이버 클라우드 플랫폼 File Storage CLI 사용하기"를 참고합니다.

네이버 클라우드 플랫폼 File Storage API 사용하기

네이버 클라우드 플랫폼 File Storage를 편리하게 사용할 수 있도록 RESTful API와 JAVA API를 제공합니다. 네이버 클라우드 플랫폼 File Storage API를 사용하려면 네이버 클라우드 플랫폼에서 발급되는 API 인증키인 access key와 secret key를 이용해 인증 과정을 거쳐야 합니다. API 인증 및 사용 방법에 대해서는 "네이버 클라우드 플랫폼 File Storage API 사용하기"를 참고합니다.

네이버 클라우드 플랫폼 콘솔 사용하기

네이버 클라우드 플랫폼 콘솔 소개

네이버 클라우드 플랫폼 콘솔은 고객이 구매한 네이버 클라우드 플랫폼 상품을 설정, 관리할 수 있는 환경을 제공하는 툴입니다. 네이버 클라우드 플랫폼 콘솔에 접근해서 화면 윗부분에 표시되는 네이버 클라우드 플랫폼 상품 중 네이버 클라우드 플랫폼 File Storage를 선택하면, 컨테이너 생성, 파일 및 폴더 관리 등 네이버 클라우드 플랫폼 File Storage 서비스의 전반적인 설정을 직접 수행할 수 있습니다.

컨테이너 관리

네이버 클라우드 플랫폼 File Storage는 컨테이너라는 대용량 파일 저장 공간을 제공합니다. 네이버 클라우드 플랫폼 File Storage 서비스를 신청한 사용자는 네이버 클라우드 플랫폼 콘솔에 접속해 컨테이너를 생성, 삭제하고, 컨테이너 권한을 관리할 수 있습니다.

컨테이너 생성

컨테이너를 생성하는 방법은 다음과 같습니다.

① 네이버 클라우드 플랫폼 웹사이트(www.ncloud.com)에 로그인한 후, 서비스 > File Storage의 [이용 신청하기]를 누릅니다.

② 네이버 클라우드 플랫폼 콘솔 화면이 나타나면 화면 왼쪽의 컨테이너 생성을 클릭합니다.

③ 컨테이너 이름을 입력하고 생성을 클릭하면 화면 왼쪽의 컨테이너 목록에 생성된 컨테이너가 추가된 것을 확인할 수 있습니다.

컨테이너 권한 관리

컨테이너와 파일에 대해 권한 부여 대상, 권한 항목을 설정해 관리할 수 있습니다.

※ 권한 설정이 되어있지 않으면 소유자만 인증을 통해 접근 가능합니다.

① 컨테이너 목록에서 을 클릭합니다.

권한 부여 대상, 권한 종류, 권한 항목을 선택하고 권한 추가를 클릭합니다. 전체 컨테이너 및 개별 파일을 PUBLIC으로 설정해 공개할 수 있습니다.

  • 권한 부여 대상 : PUBLIC
  • 권한 종류 : 허용
  • 권한 항목
    • 컨테이너 : 다운로드
    • 파일 : 다운로드

③ 추가한 권한 항목을 확인하고 설정을 클릭합니다.

④ 컨테이너를 클릭하면 설정한 권한 관리 내용을 확인할 수 있습니다.

컨테이너 삭제

컨테이너를 삭제하는 방법은 다음과 같습니다.

① 컨테이너 목록에서 삭제할 컨테이너 옆에 있는를 클릭하고 삭제 확인 창이 나타나면 예를 클릭합니다.

※ 주의 : 컨테이너를 삭제하면 해당 컨테이너에 저장된 파일도 함께 삭제되므로 주의합니다.

② 컨테이너 목록에서 해당 컨테이너가 삭제되었는지 확인합니다.

파일 및 폴더 관리

네이버 클라우드 플랫폼 콘솔에서 파일 및 폴더를 관리하는 방법을 설명합니다.

※ 참고 : 파일 및 폴더 관리는 CLI 명령어를 이용해서 할 수도 있습니다. Linux 또는 Windows에서 CLI 명령어를 이용하는 방법은 "네이버 클라우드 플랫폼 File Storage CLI 사용하기"를 참고합니다.

파일 올리기

컨테이너에 파일을 올리는 방법은 다음과 같습니다.

① 파일을 올릴 컨테이너를 선택하고 파일 올리기를 클릭합니다.

파일 추가를 클릭해 원하는 파일을 추가합니다.

전송 시작을 클릭해 파일을 업로드합니다. 파일 위치를 변경하거나 전송을 중지할 수 있습니다.

  • 파일 전송이 완료되면 해당 컨테이너 내 목록에 파일이 추가된 것을 확인할 수 있습니다.

파일 다운로드

컨테이너에 저장된 파일을 다운로드하려면, 다운로드할 파일을 선택하고 다운로드를 클릭합니다. 폴더는 다운로드할 수 없습니다.

폴더 생성

컨테이너 또는 폴더에 새 폴더를 생성할 수 있습니다. 폴더 생성 방법은 다음과 같습니다.

① 새 폴더를 생성할 컨테이너를 선택하고 새 폴더를 클릭합니다.

② 폴더명을 입력하고 생성을 클릭합니다.

  • 생성된 폴더가 목록에 추가되었는지 확인합니다.

파일, 폴더 편집

컨테이너에 저장된 파일이나 폴더를 편집할 수 있습니다.

  • 폴더는 삭제만 가능합니다. 폴더에 대한 권한 관리 기능은 없습니다.

  • 파일은 공개하기, 복사, 잘라내기, 붙여넣기, 삭제, 이름 바꾸기, 권한 관리를 할 수 있습니다.

네이버 클라우드 플랫폼 File Storage CLI 사용하기

네이버 클라우드 플랫폼 File Storage CLI 소개

네이버 클라우드 플랫폼 File Storage CLI(Command Line Interface)를 사용하면 서버 운영체제의 작업 스케줄러 기능을 이용하여 서버 백업을 자동화할 수 있습니다.

Linux에서 File Storage CLI 사용하기

File Storage CLI 다운로드 및 설정

다음과 같이 JDK 설치 여부와 JAVA_HOME 환경설정을 확인합니다.

$JAVA_HOME/bin/java -version

JDK 설치 및 JAVA_HOME 환경설정이 되어 있으면 다음과 같은 결과가 출력됩니다.

JDK가 설치되어 있지 않으면 다음과 같이 JDK를 설치하고 환경설정을 합니다.

  1. http://java.oracle.com에서 JDK를 다운로드해 설치합니다.

    예) CentOS에서 yum을 이용해서 JDK를 설치하는 경우(Ubuntu의 경우 apt-get을 이용합니다.)

    > yum install –y java
    > /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre    # yum을 이용해서 JDK를 설치했을 때 설치 경로
    
  2. JAVA_HOME을 설정합니다.

    export JAVA_HOME={JDK가 설치된 경로}
    
  3. 네이버 클라우드 플랫폼 웹사이트의 설명서(구, 사용자 가이드) > STORAGE > File Storage CLI > 파일 스토리지 CLI를 이용한 Linux 서버 백업 가이드에서 네이버 클라우드 플랫폼 파일 스토리지 CLI (Linux용)를 다운로드합니다. (https://docs.ncloud.com/download/CLI-0.9-linux-20180828183827.tar.gz)

  4. 명령어를 실행할 서버에서 다운로드한 파일의 압축을 해제하고, CLI 관련 파일(ncfscmd, ./lib/cli.jar)이 존재하는지 확인합니다. 이때, Linux에서 ncfscmd 파일 실행 권한을 부여해야 합니다(chmod 755 ncfscmd.sh).

  5. OAuth 환경설정을 합니다.

    ① 네이버 클라우드 플랫폼 웹사이트의 로그인 후 마이페이지 > API 인증키 관리에서 자신의 Access Key와 Secret Key를 확인합니다.

    ② 발급받은 Access Key와 Secret Key를 이용해서 다음과 같이 환경설정을 합니다.

     ./ncfscmd.sh  configure [Access Key] [Secret Key]
    

    ③ 파일 생성 여부를 확인합니다. 다음과 같이 출력됩니다.

     Configuration saved to ‘[/user/home/].nfscfg
    

File Storage CLI 명령어

CLI 명령어를 이용해서 File Storage 내의 폴더를 생성/삭제하고, 파일을 다운로드할 수 있습니다.

CLI 명령어의 기본 구조는 다음과 같습니다.

ncfscmd.sh [명령어] [parameter] [parameter]

"./ncfscmd.sh help" 명령을 입력하면 CLI 도움말을 볼 수 있습니다.

폴더 생성

폴더 생성 명령어는 다음과 같습니다.

ncfscmd.sh mkdir ncfs://[container]/[folder]

폴더가 생성되면 "folder [컨테이너/폴더명] be created" 형식의 결과가 출력됩니다.

폴더, 파일 삭제

폴더 또는 파일 삭제 명령어는 다음과 같습니다.

ncfscmd.sh del ncfs://[container]/[folder or file]

단, 삭제하려는 폴더 안에 파일이 있으면 해당 폴더를 삭제할 수 없습니다.

폴더 또는 파일이 삭제되면, "ncfs://[컨테이너명]/[폴더 or 파일] deleted" 형식의 결과가 출력됩니다.

파일 업로드

파일 업로드 명령어는 다음과 같습니다.

ncfscmd.sh put [localFile] ncfs://[container]/[folder]

파일이 업로드되면 "ncfs://[컨테이너명]/[파일명][전송량] of [파일크기] done execution time [전송시간]s" 형식의 결과가 출력됩니다.

※ 참고 : 업로드 가능한 단일 파일의 최대 크기는 1TB입니다.

파일 다운로드

파일 다운로드 명령어는 다음과 같습니다.

ncfscmd.sh  get ncfs://[container]/[filename] [로컬 저장 경로]

파일이 다운로드되면 "ncfs://[컨테이너명]/[파일명] -> [파일명][전송량] of [파일크기] done execution time [전송시간]s" 형식의 결과가 출력됩니다.

목록 조회

목록 조회 명령어는 다음과 같습니다.

ncfscmd.sh ls ncfs://[container]

목록 조회가 되면 “[최종수정일시][파일크기 or DIR] ncfs://[컨테이너명]/[파일 or 폴더]” 형식의 결과가 출력됩니다.

전송 중단 또는 취소된 파일의 삭제

네트워크 문제로 전송이 중단되었거나 취소된 파일은 네이버 클라우드 플랫폼 콘솔에서 여전히 업로드 중인 상태로 나타나고 재전송도 할 수 없습니다. 이때는 전송 상태로 남아있는 파일을 abort 명령으로 삭제하고 다시 전송합니다.

ncfscmd.sh abort ncfs://[container]/[file]

파일이 삭제되면 "folder [컨테이너/파일명] aborting completed" 형식의 결과가 출력됩니다.

Linux 서버 백업 자동화

네이버 클라우드 플랫폼 File Storage CLI를 이용해서 주기적으로 Linux 서버의 데이터를 네이버 클라우드 플랫폼 File Storage로 백업하는 작업을 자동화할 수 있습니다. 백업 자동화는 다음과 같은 순서로 진행합니다.

  • 스케줄러 작업 등록 : 백업 데이터를 업로드하는 절차를 스케줄러 작업으로 등록합니다.

  • 컨테이너 생성

    네이버 클라우드 플랫폼 콘솔 > File Storage에 접속해 백업에 사용할 컨테이너를 생성합니다. 컨테이너 생성 방법은 "컨테이너 생성"을 참고합니다.

  • 백업 데이터 업로드

    CLI를 이용해서 백업 데이터를 파일 스토리지로 업로드합니다. 생성한 컨테이너에 File Storage CLI 명령어로 데이터를 업로드합니다.

    1. 다음과 같이 파일을 업로드합니다. 파일당 업로드할 수 있는 최대 크기는 1TB입니다.

      ncfscmd.sh put [localFile] ncfs://[container]
      ncfscmd.sh put [localFile] ncfs://[container]/[folder]
      

      업로드 결과가 "[파일명] -> ncfs://[컨테이너명]/[파일 명][전송량] of [파일크기] done execution time [전송시간]s" 형식으로 출력됩니다.

    2. 다음과 같이 컨테이너 내 파일 목록을 조회해서 파일이 제대로 업로드됐는지 확인합니다.

      ncfscmd.sh ls ncfs://[container]
      

      조회 결과가 "[최종수정일시] [파일크기 or DIR] ncfs://[컨테이너명]/[파일 or 폴더]" 형식으로 출력됩니다.
      백업할 파일이 여러 개이면 압축해서 하나의 파일을 생성하고 미리 생성한 컨테이너에 ncfscmd.sh put 명령을 이용해서 업로드합니다.
      업로드된 파일은 ncfscmd.sh ls ncfs://[컨테이너명] 명령으로 컨테이너별로 확인할 수 있습니다.
      업로드하려는 컨테이너 또는 디렉터리에 이름이 같은 파일이 이미 있으면 put 명령을 실행하더라도 파일을 덮어쓰지 않고 업로드가 취소되므로 주의합니다.

  • 스케줄러 작업 등록

    • 백업 명령 또는 스크립트 파일을 crontab에 등록해서 주기적인 백업 작업을 자동화할 수 있습니다.
    • 백업을 위한 CLI 업로드 명령이나 스크립트 파일을 crontab에 등록합니다. 예를 들어 매일 5시에 백업을 실행해서 ex-cnt라는 컨테이너에 파일을 업로드하려면 다음과 같이 등록합니다.

      $ crontab -e
      0 5 * * *  [/파일위치/]ncfscmd.sh put  backupfile-yyyy-mm-dd-OO.tar.gz   ncfs://ex-cnt
      
    • 스케줄러 등록 후에는 작업 실행 로그 등을 통해서 스케줄 작업이 정상적으로 수행되는지 꼭 확인합니다.

※ 주의 : 업로드할 경로에 이름이 같은 파일이 있다면 파일을 덮어쓰지 않고 업로드를 취소합니다. 따라서 주기적으로 백업 데이터를 업로드할 때는 반드시 파일 이름을 다르게 지정해서 업로드해야 합니다. 항상 다른 이름으로 백업용 파일을 만드는 스크립트를 작성해서 사용하는 것을 권장합니다.

MySQL DB 백업 시나리오

다음은 Linux에서 MySQL DB를 File Storage에 주기적으로 백업한다고 가정했을 때 백업 시나리오입니다.

  1. My SQL DB 백업용 파일을 생성합니다.

    • 테이블별 백업

      /MYSQLHOME/bin/mysqldump –u[계정] –p[패스워드] -R -Q --opt [DB명] [테이블명] > [백업 파일명]
      
    • 데이터베이스별 백업

      /MYSQLHOME/bin/mysqldump –u[계정] –p[패스워드] -R -Q --opt [DB명] > [백업 파일명]
      
    • 전체 데이터 백업

      /MYSQLHOME/bin/mysqldump –u[계정] –p[패스워드] -R -Q --opt --all-databases > [백업 파일명]
      
      MySQL 백업 옵션
      -R rprocedure, function을 포함하여 백업
      -Q 테이블 칼럼에 '를 넣는 옵션
  2. 다음과 같이 File Storage CLI를 사용하기 위한 환경을 설정합니다. Access Key와 Secret Key는 네이버 클라우드 플랫폼 웹사이트의 로그인 후 마이페이지> API 인증키 관리에서 확인할 수 있습니다.

     ncfscmd.sh configure [Access Key] [Secret Key]
    
  3. File Storage CLI를 이용해서 백업 파일을 업로드합니다.

     ./ncfscmd.sh [백업 파일] ncfs://[컨테이너명]/[폴더명]
    

    해당 컨테이너에 이름이 같은 파일이 있어도 덮어쓰지 않으므로 날짜별로 폴더 이름을 만들어서 업로드합니다.
    예) ./ncfscmd.sh [백업 파일] ncfs://test/20130129

  4. 주기적으로 백업해야 한다면 상위 단계를 셸 스크립트로 작성하고 crontab에서 일일 배치로 실행하도록 등록합니다.

Windows에서 File Storage CLI 사용하기

File Storage CLI 다운로드 및 설정

File Storage CLI를 사용하려면 먼저 명령 프롬프트에서 다음과 같은 명령을 실행해 JDK 설치 여부 및 JAVA_HOME 환경 변수 설정 여부를 확인합니다.

C:\> %JAVA_HOME%\bin\java -version

JDK가 설치되어 있고 JAVA_HOME 환경 변수가 설정되어 있으면 다음과 같이 출력됩니다.

위와 같이 버전 정보가 출력되지 않고 "지정된 경로를 찾을 수 없습니다."라는 오류 메시지가 출력된다면 다음과 같이 JDK를 설치하고 JAVA_HOME 환경 변수를 설정합니다.

  • JDK 설치 및 JAVA_HOME 환경 변수 설정

    1. Internet Explorer를 관리자 권한으로 실행합니다.
    2. 도구 > 인터넷 옵션을 클릭하고 보안탭에서 사용자 지정 수준을 클릭한 후 다음과 같이 설정합니다.
      • 다운로드 > 파일 다운로드: 사용
      • 스크립팅 > Active 스크립팅: 사용
      • 스크립팅 > Java 애플릿 스크립팅: 사용
    3. Accept License Agreement를 클릭한 후 운영체제에 해당하는 링크를 클릭하여 JDK 설치 파일을 다운로드합니다.
    4. 다운로드한 파일을 실행하고 안내에 따라 JDK를 설치합니다.
    5. 컴퓨터에서 마우스 오른쪽 버튼을 클릭해 속성 > 고급 시스템 설정 > 환경 변수로 들어가서 다음과 같이 JAVA_HOME 변수를 설정합니다.


JDK를 설치하고 JAVA_HOME 환경 변수를 설정했으면 다음과 같이 File Storage CLI를 다운로드해 압축을 해제하고 OAuth 환경을 설정합니다.

  1. 네이버 클라우드 플랫폼 웹사이트의 설명서(구, 사용자 가이드) > STORAGE > File Storage CLI > 파일 스토리지 CLI를 이용한 Windows 서버 백업 가이드에서 네이버 클라우드 플랫폼 파일 스토리지 CLI(Windows용)를 다운로드합니다.
  2. 명령어를 실행할 서버에서 다운로드한 ZIP 파일을 압축 해제합니다.
  3. 명령 프롬프트에서 압축 해제한 디렉터리로 이동한 후 다음 명령을 실행하여 OAuth 환경을 설정합니다.

    ncfscmd.cmd configure {Access Key} {Secret Key}
    

    정상적으로 설정되면 다음과 같은 메시지가 출력됩니다.

    Configuration saved to ‘{/Users/home/}.nfscfg'
    

    Access Key와 Secret Key는 네이버 클라우드 플랫폼 웹사이트 로그인 후 마이페이지 > API 인증키관리에서 확인할 수 있습니다.

File Storage CLI 명령어

File Storage CLI의 기본 명령어 구조는 다음과 같습니다.

ncfscmd.cmd [명령어] [parameter] [parameter]

"ncfscmd.cmd help"를 입력하면 도움말을 볼 수 있습니다.

  • 폴더 생성

    폴더 생성 명령어는 다음과 같습니다.

    ncfscmd.cmd mkdir ncfs://[container]/[folder]
    

    폴더가 생성되면 "folder [컨테이너/폴더명] be created" 형식의 결과가 출력됩니다.

  • 폴더, 파일 삭제

    폴더 또는 파일 삭제 명령어는 다음과 같습니다.

    ncfscmd.cmd del ncfs://[container]/[folder]
    

    단, 폴더 안에 파일이 존재하면 해당 폴더를 삭제할 수 없습니다.

    Ncfscmd.cmd del ncfs://[container]/[file]
    

    폴더 또는 파일이 삭제되면 "ncfs://[컨테이너명]/[폴더 or 파일] deleted" 형식의 결과가 출력됩니다.

  • 파일 업로드

    파일 업로드 명령어는 다음과 같습니다.

    ncfscmd.cmd put [localFile] ncfs://[container]
    ncfscmd.cmd put [localFile] ncfs://[container]/[folder]
    

    파일이 업로드되면 "[파일명] -> ncfs://[컨테이너명]/[파일명][전송량] of [파일크기] done execution time [전송시간]s" 형식의 결과가 출력됩니다.

※ 참고 : 업로드 가능한 단일 파일의 최대 크기는 1TB입니다.

  • 파일 다운로드

    파일 다운로드 명령어는 다음과 같습니다.

    ncfscmd.cmd get ncfs://[container]/[filename] [로컬 저장 경로]
    

    파일이 다운로드되면 "ncfs://[컨테이너명]/[파일명] -> ./[파일명][전송량] of [파일크기] done execution time [전송시간]s" 형식의 결과가 출력됩니다.

  • 목록 조회

    목록 조회 명령어는 다음과 같습니다.

    ncfscmd.cmd ls ncfs://[container]
    

    목록 조회 결과가 "[최종수정일시] [파일크기 or DIR] ncfs://[컨테이너명]/[파일 or 폴더]" 형식으로 출력됩니다.

  • 전송 중단 또는 취소된 파일의 삭제

    네트워크 문제로 전송이 중단되었거나 취소된 파일은 네이버 클라우드 플랫폼 콘솔에서 여전히 업로드 중인 상태로 나타나고 재전송할 수도 없습니다. 이때는 전송 상태로 남아있는 파일을 abort 명령으로 삭제하고 다시 전송합니다.

    ncfscmd.cmd abort ncfs://[container]/[file]
    

    파일이 삭제되면 "folder [컨테이너/파일명] aborting completed" 형식의 결과가 출력됩니다.

Windows 서버 백업 자동화

네이버 클라우드 플랫폼 File Storage CLI를 이용해서 주기적으로 Windows 서버의 데이터를 백업하는 작업을 자동화하는 방법을 설명합니다. 백업 자동화는 다음과 같은 순서로 진행합니다.

  • 컨테이너 생성

    네이버 클라우드 플랫폼 콘솔 > File Storage에 접속해 백업에 사용할 컨테이너를 생성합니다. 컨테이너 생성 방법은 "컨테이너 생성"을 참고합니다.

  • 백업 데이터 업로드

    CLI를 이용해서 백업 데이터를 파일 스토리지에 업로드합니다. 백업 데이터를 업로드하려면 명령 프롬프트에서 File Storage CLI 디렉터리로 이동하여 다음 명령을 실행합니다. 백업할 파일이 여러 개라면 압축해서 하나의 파일을 생성하여 업로드합니다.

    ncfscmd.cmd put {업로드할 파일 이름} ncfs://{컨테이너 이름}/{업로드할 경로}
    

    업로드하려는 컨테이너 또는 디렉터리에 이름이 같은 파일이 이미 있으면 put 명령을 실행하더라도 파일을 덮어쓰지 않고 업로드가 취소되므로 주의합니다.
    정상적으로 업로드되면 다음과 같은 메시지가 출력됩니다.

    {파일 이름} -> ncfs://{컨테이너 이름}/{업로드한 경로}/{파일 이름} {전송된 데이터 크기} of {파일 크기} done execution time {전송에 걸린 시간(단위: 초)}s
    
  • 작업 스케줄러에 등록

    벡업 데이터를 업로드하는 절차를 스케줄러 작업으로 등록합니다. 스케줄러가 주기적으로 백업하고 업로드하게 하려면 스크립트를 작성하여 관리 도구 > 작업 스케줄러에 등록합니다. 등록 후에는 작업 실행 로그 등을 통해서 스케줄 작업이 정상적으로 수행되는지 반드시 확인해야 합니다.

※ 주의 : 업로드할 경로에 이름이 같은 파일이 있다면 파일을 덮어쓰지 않고 업로드를 취소합니다. 따라서 주기적으로 백업 데이터를 업로드할 때는 반드시 파일 이름을 다르게 지정해서 업로드해야 합니다. 항상 다른 이름으로 백업용 파일을 만드는 스크립트를 작성해서 사용하는 것을 권장합니다.

네이버 클라우드 플랫폼 File Storage API 사용하기

네이버 클라우드 플랫폼 File Storage API 소개

네이버 클라우드 플랫폼 File Storage API를 이용해서 네이버 클라우드 플랫폼 콘솔에서 할 수 있는 주요 작업을 대부분 수행할 수 있습니다. 사용자는 RESTful API 또는 제공되는 Java SDK를 활용해서, 고객의 서비스 시나리오에 맞추어 서비스 관리를 자동화하거나 자체 관리 도구를 개발하여 보다 유연하고 편리하게 서비스를 운영 및 관리할 수 있습니다.

네이버 클라우드 플랫폼 웹사이트의 설명서(구, 사용자 가이드) > STORAGE > File Storage에서 관련 API 레퍼런스와 Java 라이브러리 파일을 다운로드할 수 있습니다.

OAuth 인증 방식

네이버 클라우드 플랫폼 File Storage API는 표준화된 OAuth(open standard for authorization) 인증을 이용합니다. OAuth 인증 방식은 별도의 시스템이 로그인 정보를 저장하지 않도록 하고 암호화된 인증 토큰을 이용해야만 리소스에 접근할 수 있도록 허용하므로 안전합니다. 또한 다양한 플랫폼의 오픈 라이브러리(OAuth Client Library)를 사용할 수 있도록 지원합니다. 네이버 클라우드 플랫폼에서 제공하는 API는 이러한 OAuth 인증 방식의 통일된 체계를 통해 인증을 처리합니다.

일반적으로 OAuth 인증 방식은 3 party system (User, Consumer, Service Provider) 형태로 고안되어 있습니다. 이러한 방식을 3- legged 인증 방식이라고 합니다.

  • User: Service Provider에 계정을 가진 사용자
  • Consumer: User를 대신해 Service Provider에 접근하기 위해 OAuth를 사용하는 웹 서비스나 애플리케이션.
  • Service Provider: OAuth를 통해 접근을 허용하는 웹 애플리케이션

네이버 클라우드 플랫폼 File Storage API에서는 3-legged 인증 방식보다 간소화된 2-legged 인증 방식을 지원하고 있습니다. 즉, 3 party system 구조에서 Consumer가 생략되었다고 보면 됩니다. 2-legged OAuth 인증 방식의 흐름은 다음과 같습니다.

네이버 클라우드 플랫폼 File Storage API에서 사용하는 OAuth 인증은 OAuth 1.0a(http://tools.ietf.org/html/rfc5849)를 기반으로 합니다.

네이버 클라우드 플랫폼 File Storage API 인증하기

네이버 클라우드 플랫폼 File Storage API를 사용하려면 다음과 같은 과정을 거쳐야 합니다.

  • API 인증키 발급(생략 가능)
  • API URL 검증(생략 가능)
  • OAuth 인증 클라이언트 구현

API 인증키는 기본으로 하나 발급되어 있으며 API URL 검증도 편의를 위해 제공되는 부분이므로 생략할 수 있습니다.

API 인증키 발급

네이버 클라우드 플랫폼 계정을 생성하면 기본적으로 네이버 클라우드 플랫폼 File Storage API 인증키가 하나 발급됩니다. 발급된 인증키는 네이버 클라우드 플랫폼 웹사이트 로그인 후 마이페이지 > API 인증키관리에서 확인할 수 있습니다.

인증키는 계정 생성 시 자동으로 발급되는 것 외에 사용자가 하나 더 생성할 수 있어서 두 개까지 발급받을 수 있습니다. 인증키를 사용중지로 설정하거나 삭제하면 유효하지 않은 키로 인식됩니다.

API 인증키는 Access Key와 Secret Key 한 쌍으로 구성되어 있습니다. Access Key는 API를 인증할 때 파라미터로 직접 전달되며, Secret Key는 OAuth_signature 파라미터를 서명할 때 사용합니다.

API URL 검증

API URL 검증 기능은 사용자가 네이버 클라우드 플랫폼 File Storage API를 사용하기 위해 네이버 클라우드 플랫폼 웹사이트에서 얻어야 할 정보를 확인하고, API 인증키의 유효성과 API 동작 여부 및 결과를 확인할 수 있게 해줍니다.

OAuth 인증 시 OAuth 파라미터를 전달하는 방식에는 2가지가 있습니다. HTTP 호출 시 GET 방식으로 URL 자체에 OAuth 인증에 필요한 파라미터를 붙여서 전달하는 방식과, HTTP 헤더에 넣어서 보내는 방식입니다.

API URL 검증 시 다음과 같이 동작 대상 URL(예: 컨테이너명/파일명)을 생성합니다.

API URL (GET)
http://restapi.fs.Naver Cloud 플랫폼.com{URL}?
&oauth_consumer_key={Access Key}
&oauth_timestamp={timestamp}
&oauth_signature={oauth signature}
&oauth_nonce={nonce 값}
&oauth_signature_method=HMAC-SHA1
&oauth_version=1.0

실제 API 사용 시 인증 Access Key와 인증 Secret Key를 사용해 인증 파라미터('oauth_'를 prefix로 사용하는 파라미터)를 생성하여 request에 추가합니다.

  • 인증 Access Key 선택. 예) xoiOTgN2sgjDb5oRzp8q
  • 인증 Secret Key(인증 Access Key 선택에 따라 자동으로 선택됨)
    예) SMSyGbEi7ucZpPnRGlomftWRNENz0TV1mMOI7MiA

서비스 서버에 적용되는 URL과 파라미터 관련 내용은 다음 절에서 설명합니다.

OAuth 인증 클라이언트 구현

네이버 클라우드 플랫폼 File Storage API를 사용하려면 아래 표에 명시된 URL과 필수 파라미터를 생성해서 요청해야 합니다.

API URL 구성 및 파라미터 정보
구분필수 여부설명
호출 URLY호출 대상 기능 URL. 형식은 http://restapi.fs.ncloud.com/{기능요청URL}?{파라미터}입니다. 예) http://restapi.fs.Naver Cloud 플랫폼.com/{test}?list...
인증 파라미터YOAuth 인증을 위한 파라미터이며, 이 정보들은 헤더에 구성할 수 있습니다. - oauth_consumer_key: 네이버 클라우드 플랫폼 웹사이트의 로그인 후 마이페이지 > API 인증키 관리에서 생성한 Access Key 값. 예) oauth_consumer_key=xoiOTgN2sgjDb5oRzp8q - oauth_signature_method: OAuth 서명 방식. 고정값으로 HMAC-SHA1를 사용합니다. 예) oauth_signature_method=HMAC-SHA1 - oauth_version: OAuth 버전. 고정값으로 1.0을 사용합니다. 예) oauth_version=1.0 - oauth_timestamp: timestamp 값. 오픈 라이브러리를 사용할 수 있으며, 사용 예제는 "오픈 라이브러리를 이용한 인증 파라미터 생성" 절을 참고합니다. 예) oauth_timestamp=1335419436 - oauth_nonce: 재전송 공격(replay attack)에 대한 예방으로 재사용 방지를 위한 일회성 파라미터다. 오픈 라이브러리를 사용할 수 있으며, 사용 예제는"오픈 라이브러리를 이용한 인증 파라미터 생성" 절을 참고합니다. 예) oauth_nonce=W4SkWT - oauth_signature: 네이버 클라우드 플랫폼 웹사이트의 로그인 후 마이페이지 > API 인증키 관리에서 생성한 Secret Key를 사용한 서명이다(일회성). oauth_consumer_key와 쌍을 이룬 Secret Key여야 합니다. 오픈 라이브러리를 사용할 수 있으며, 사용 예제는"오픈 라이브러리를 이용한 인증 파라미터 생성" 절을 참고합니다. 예) oauth_signature=qVsXa0Pf913BIhv55f06ont3aIE%3D
오픈 라이브러리를 이용한 인증 파라미터 생성

네이버 클라우드 플랫폼 File Storage API는 표준 OAuth를 지원하므로 다양한 오픈 클라이언트 라이브러리를 사용하여 인증 파라미터를 생성할 수 있습니다. 생성된 인증 파라미터는 앞 절의 URL 예시처럼 HTTP Request에 파라미터로 추가하거나 헤더에 추가하여 사용할 수 있습니다.

다음은 signpost-core 라이브러리를 이용해 인증 파라미터를 생성하는 방법을 설명합니다. 이 라이브러리를 사용하면 헤더에 인증 파라미터가 포함돼 전달됩니다.

※ 참고 : signpost-core 라이브러리 사용법은 http://code.google.com/p/oauth-signpost/wiki/GettingStarte를 참고합니다.

  1. signpost-core 라이브러리를 직접 다운로드하거나, maven을 사용한다면 pom.xml에 아래와 같이 설정합니다.

    <dependency>
    <groupId>oauth.signpost</groupId>
    <artifactId>signpost-core</artifactId>
    <version>1.2</version>
    <scope>compile</scope>
    </dependency>
    
  2. 다음의 예제 코드를 참고하여 OAuth 인증 파라미터를 포함한 HTTP 요청을 생성합니다.

    • 예제 코드에서 사용자가 값을 변경해야 할 부분은 아래와 같습니다.
    • String accessKey = "xoiOTgN2sgjDb5oRzp8q";
    • String secretKey = "SMSyGbEi7ucZpPnRGlomftWRNENz0TV1mMOI7MiA";
    • String requestURI = "http://localhost:8080/oauth/getResource";

      public void testOauthRequestMethod() throws IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {
         String accessKey = "xoiOTgN2sgjDb5oRzp8q";
         String secretKey = "SMSyGbEi7ucZpPnRGlomftWRNENz0TV1mMOI7MiA";
         String requestURI = "http://localhost:8080/oauth/getResource";
      
         Map<String, Object> requestParameters = new HashMap<String, Object>();
      
         StringBuffer queryString = new StringBuffer();
         int index= 1;
         int requestParamSize = requestParameters.size();
         for (String key : requestParameters.keySet()) {
                 if (index == 1) {
                         queryString.append("?");
                 }
                 queryString.append(key);
                 queryString.append('=');
                 queryString.append(URLEncoder.encode((String)requestParameters.get(key), "UTF-8"));
                 if (index!= requestParamSize) {
                         queryString.append("&");
                         index ++;
                 }
         }
      
         OAuthConsumer consumer = new DefaultOAuthConsumer(accessKey, secretKey);
         URL url = new URL(requestURI + queryString.toString());
         HttpURLConnection con = (HttpURLConnection)url.openConnection();
      
         //헤더값을 설정합니다.
         con.setRequestMethod("GET");
         con.setConnectTimeout(500000);
      con.setUseCaches(false);
         con.setDefaultUseCaches(false);
      
         //sign the request
         consumer.sign(con);
      
         //send the request
         con.connect();
      
         int responseCode = con.getResponseCode();
      
         if (responseCode == HttpURLConnection.HTTP_OK) {
                 BufferedReader resultReader = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));
                 StringBuffer requestResult = new StringBuffer();
                 String readString = null;
                 while ((readString = resultReader.readLine()) != null) {
                         requestResult.append(readString);
                 }
                 System.out.println("requestResult=>" + requestResult.toString());
         }
      }
      
서명 생성

서명(signature)을 생성하는 방법을 예제와 함께 설명합니다.

  1. baseString을 생성합니다.

    1. 요청 파라미터에 baseString 생성에 필요한 파라미터를 추가합니다.
    2. 요청 파라미터와 value값을 알파벳 순서로 정렬합니다.

      • String consumerKey = "consumer-k1";
      • String consumerSecret = "consumer-secret1";
      • String requestUrl = "http://localhost:8080/oauth/getResource";
      • String requestMethod = "GET";
      • requestParameters.put("test_param1", Arrays.asList("a"));
      • requestParameters.put("test_param2", Arrays.asList("b2", "b1"));
      • requestParameters.put("test_param3", Arrays.asList("한글"));

        String consumerKey =    "consumer-k1";
        String consumerSecret    = "consumer-secret1";
        String requestUrl =    "http://localhost:8080/oauth/getResource";
        String requestMethod =    "GET";
        Map<String, List<String>> requestParameters = new HashMap<String, List<String>>();
        requestParameters.put("test_param1", Arrays.asList("a"));
        requestParameters.put("test_param2", Arrays.asList("b2", "b1"));
        requestParameters.put("test_param3", Arrays.asList("한글"));
        /**
        * signature base string을 만들기 위한 significateParameter 설정
        *    @param requestParameters
        *    @param consumerKey
        *    @return
        */
        private SortedMap<String, SortedSet<String>> getSignificateParametersForSiganturBaseString(Map<String, List<String>> requestParameters, String consumerKey) {
        SortedMap<String, SortedSet<String>> significateParameters = convertTypeToSortedMap(requestParameters);
        
        SortedSet<String> consumerKeySet = new TreeSet<String>(); consumerKeySet.add(consumerKey); significateParameters.put("oauth_consumer_key", consumerKeySet);
        
        SortedSet<String> nonceSet = new TreeSet<String>(); nonceSet.add(generateNonce()); significateParameters.put("oauth_nonce", nonceSet);
        
        SortedSet<String> signatureMethodSet = new TreeSet<String>(); signatureMethodSet.add("HMAC-SHA1"); significateParameters.put("oauth_signature_method", signatureMethodSet);
        
        SortedSet<String> timestampSet = new TreeSet<String>(); timestampSet.add(generateTimestamp());
        significateParameters.put("oauth_timestamp", timestampSet);
        
        SortedSet<String> versionSet = new TreeSet<String>();
        versionSet.add("1.0"); significateParameters.put("oauth_version", versionSet);
        
        logger.debug("significateParameters=>" + significateParameters);
        
        return significateParameters;
        }
        
        /**
        *    @param requestParameters
        *    @param significateParameters
        */
        private SortedMap<String, SortedSet<String>> convertTypeToSortedMap(Map<String, List<String>> requestParameters) {
        SortedMap<String, SortedSet<String>> significateParameters = new TreeMap<String, SortedSet<String>>();
        Iterator<String> parameterNames = requestParameters.keySet().iterator(); while (parameterNames.hasNext()) {
        String parameterName = (String)parameterNames.next();
        List<String> parameterValues = requestParameters.get(parameterName); if (parameterValues == null) {
        parameterValues = new ArrayList<String>();
        }
        
        for (String parameterValue : parameterValues) {
        if (parameterValue == null) { parameterValue = "";
        }
        
        SortedSet<String> significantValues = significateParameters.get(parameterName);
        if (significantValues == null) {
        significantValues = new TreeSet<String>(); significateParameters.put(parameterName, significantValues);
        }
        significantValues.add(parameterValue);
        }
        }
        return significateParameters;
        }
        
        private String generateTimestamp() {
        
        return Long.toString(System.currentTimeMillis() / 1000L);
        }
        
        private String generateNonce() {
        return Long.toString((new Random()).nextLong());
        }
        
      • baseString = RequestMethod + '&' + oauthEncode(requestUrl) + '&' + oauthEncode(queryString)
      /**
      *    base string 생성
      *    @param requestMethod
      *    @param requestUrl
      *    @param significantParameters
      *    @return
      */
      private String makeSignatureBaseString(String requestMethod, String requestUrl, SortedMap<String, SortedSet<String>> significantParameters) {
      StringBuilder queryString = getRequestQueryString(significantParameters);
      
      requestUrl = normalizeUrl(requestUrl);
      requestUrl = OAuthCodec.oauthEncode(requestUrl);
      
      return new StringBuilder(requestMethod.toUpperCase()).append('&').append(requestUrl).append('&').append(OAuthCodec.oauth Encode(queryString.toString())).toString();
      }
      
      /**
      *    query string 생성
      *    @param significantParameters
      *    @return
      */
      private StringBuilder getRequestQueryString(SortedMap<String, SortedSet<String>> significantParameters) { StringBuilder queryString = new StringBuilder();
      Iterator<Map.Entry<String, SortedSet<String>>> paramIt = significantParameters.entrySet().iterator(); while (paramIt.hasNext()) {
      Map.Entry<String, SortedSet<String>> sortedParameter = paramIt.next(); Iterator<String> valueIt = sortedParameter.getValue().iterator();
      while (valueIt.hasNext()) {
      String parameterValue = valueIt.next();
      
      queryString.append(OAuthCodec.oauthEncode(sortedParameter.getKey())).append('=').append(OAuthCodec.oauthEn
      code(parameterValue));
      if (paramIt.hasNext() || valueIt.hasNext()) {
       queryString.append('&');
       }
      }
      }
      return queryString;
      }
      
      /**
      *    @param url
      *    @return
      */
      private String normalizeUrl(String url) {
      try {
      URL requestURL = new URL(url);
      StringBuilder normalized = new
      StringBuilder(requestURL.getProtocol().toLowerCase()).append("://").append(requestURL.getHost().toLowerCase());
      if ((requestURL.getPort() >= 0) && (requestURL.getPort() != requestURL.getDefaultPort())) {
      normalized.append(":").append(requestURL.getPort());
      }
      normalized.append(requestURL.getPath());
      return normalized.toString();
      } catch (MalformedURLException e) {
       throw new IllegalStateException("Illegal URL for calculating the OAuth signature.", e);
      }
      }
      
      class OAuthCodec extends URLCodec {
      
      private OAuthCodec() {
      }
      
      public static String oauthEncode(String value) {
      if (value == null)
      return "";
      try {
      return new String(URLCodec.encodeUrl(SAFE_CHARACTERS, value.getBytes("UTF-8")), "US-ASCII");
      } catch (UnsupportedEncodingException e) { throw new RuntimeException(e);
      }
      }
      
      public static String oauthDecode(String value) throws DecoderException {
      if (value == null)
       return "";
      try {
        return new String(URLCodec.decodeUrl(value.getBytes("US-ASCII")), "UTF-8");
      } catch (UnsupportedEncodingException e) { throw new RuntimeException(e);
      }
      }
      protected static final BitSet SAFE_CHARACTERS;
      
      static {
       SAFE_CHARACTERS = (BitSet)URLCodec.WWW_FORM_URL.clone();
       SAFE_CHARACTERS.clear(42);
       SAFE_CHARACTERS.clear(32);
       SAFE_CHARACTERS.set(126);
      }
      }
      
  2. secret key와 위에서 생성한 baseString을 가지고 HMAC SHA-1 해시 알고리즘을 이용해 서명(signature)을 생성합니다.

    /**
    *    base string과 consumer secret key를 가지고 signature 생성
    *    @param signatureBaseString
    *    @param consumerSecret
    *    @return
    *    @throws NoSuchAlgorithmException
    *    @throws UnsupportedEncodingException
    *    @throws InvalidKeyException
    */
       private String sign(String signatureBaseString, String consumerSecret) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
          Mac mac = Mac.getInstance("HmacSHA1");
      SecretKeySpec spec = new SecretKeySpec(new String(consumerSecret + "&").getBytes("UTF-8"), "HmacSHA1");
    
      mac.init(spec);
      byte text[] = signatureBaseString.getBytes("UTF-8");
      byte signatureBytes[] = mac.doFinal(text);
      signatureBytes = Base64.encodeBase64(signatureBytes);
      String signature = new String(signatureBytes, "UTF-8");
      logger.debug("signature==>" + signature);
      return signature;
    }
    
  3. queryString 방식이나 Authorization Header 방식으로 요청 URL을 생성합니다.

    • queryString 방식을 이용한 요청 URL 생성 예제

      /**
      *    request URL 생성
      *    @param requestParameters
      *    @param signature
      *    @return
      *@throws UnsupportedEncodingException
      */
       private String makeRequestUrl(String requestUrl, SortedMap<String, SortedSet<String>> significantParameters, String signature) throws UnsupportedEncodingException {
          StringBuilder queryString = getRequestQueryString(significantParameters);
          queryString.append('&').append("oauth_signature").append("=").append
      (URLEncoder.encode(signature,"UTF-8"));
          return new StringBuffer(requestUrl).append("?").append(queryString.toString()).toString();
       }
      
    • Authorization Header 방식을 이용한 URL 생성 예제

      /**
      *    @param significantParameters
      *    @param signature
      *    @return
      *    @throws UnsupportedEncodingException
      */
         private String makeAuthorizationHeader(SortedMap<String, SortedSet<String>> significantParameters, String signature) throws UnsupportedEncodingException {
           StringBuilder authorizationHeaderString = new StringBuilder();
      
           Iterator<Map.Entry<String, SortedSet<String>>> paramIt = significantParameters.entrySet().iterator();
      
           while (paramIt.hasNext()) {
              Map.Entry<String, SortedSet<String>> sortedParameter = paramIt.next();
              int valueSize = sortedParameter.getValue().size();
              Iterator<String> valueIt = sortedParameter.getValue().iterator();
      
              if ("oauth_consumer_key".equals(sortedParameter.getKey())) {
                 if (valueSize != 1) {
                    throw new IllegalArgumentException("oauth_consumer_key is empty or one more value.");
                 }
      
      authorizationHeaderString.append("oauth_consumer_key").append('=').append('\"').append(valueIt.next()).append('\ "');
                 authorizationHeaderString.append(", ");
                  }
      
                 if ("oauth_nonce".equals(sortedParameter.getKey())) {
                    if (valueSize != 1) {
                       throw new IllegalArgumentException("oauth_nonce is empty or one more value.");
                 }
      
      authorizationHeaderString.append("oauth_nonce").append('=').append('\"').append(valueIt.next()).append('\"');
                 authorizationHeaderString.append(", ");
           }
      
                 if ("oauth_signature_method".equals(sortedParameter.getKey())) {
                   if (valueSize != 1) {
                       throw new IllegalArgumentException("oauth_signature_method is empty or one more value.");
                 }
      
      authorizationHeaderString.append("oauth_signature_method").append('=').append('\"').append(valueIt.next()).appen
      d('\"');
                       authorizationHeaderString.append(", ");
                 }
      
                 if ("oauth_timestamp".equals(sortedParameter.getKey())) {
                    if (valueSize != 1) {
                       throw new IllegalArgumentException("oauth_timestamp is empty or one more value.");
                 }
      
      authorizationHeaderString.append("oauth_timestamp").append('=').append('\"').append(valueIt.next()).append('\"');
                       authorizationHeaderString.append(", ");
                 }
      
                 if ("oauth_version".equals(sortedParameter.getKey())) {
      
                    if (valueSize != 1) {
                       throw new IllegalArgumentException("oauth_version is empty or one more value.");
                 }
      
      authorizationHeaderString.append("oauth_version").append('=').append('\"').append(valueIt.next()).append('\"');
                 authorizationHeaderString.append(", ");
               }
           }
      
           return new StringBuffer().append("OAuth ").append(authorizationHeaderString.toString()).append("oauth_signature").append('=').append('\"').append(URLEnc oder.encode(signature, "UTF-8")).append('\"').toString();
           }
      
    • queryString 방식 요청 로그

      2013-05-14 19:08:31 INFO(ResourceController :126) Request queryString : oauth_consumer_key=consumer- k1&oauth_nonce=-569464277982872277&oauth_signature_method=HMAC- SHA1&oauth_timestamp=1368526111&oauth_version=1.0&test_param1=a&test_param2=b1&test_param2=b 2&test_param3=%ED%95%9C%EA%B8%80&oauth_signature=9j8i7MGdC6sn9lx25JVuBSSR2%2BY%3D

      2013-05-14 19:08:31 INFO(ResourceController :122) Request method : GET
      2013-05-14 19:08:31 INFO(ResourceController :123) Request contextPath :
      2013-05-14 19:08:31 INFO(ResourceController :124) Request pathInfo : null
      2013-05-14 19:08:31 INFO(ResourceController :125) Request pathTranslated : null
      2013-05-14 19:08:31 INFO(ResourceController :126) Request queryString : oauth_consumer_key=consumer- k1&oauth_nonce=-569464277982872277&oauth_signature_method=HMAC- SHA1&oauth_timestamp=1368526111&oauth_version=1.0&test_param1=a&test_param2=b1&test_param2=b 2&test_param3=%ED%95%9C%EA%B8%80&oauth_signature=9j8i7MGdC6sn9lx25JVuBSSR2%2BY%3D
      2013-05-14 19:08:31 INFO(ResourceController :127) Request requestURI : /oauth/getResource
      2013-05-14 19:08:31 INFO(ResourceController :128) Request requestURL : http://localhost:8080/oauth/getResource
      2013-05-14 19:08:31 INFO(ResourceController :129) Request servletPath : /oauth/getResource
      2013-05-14 19:08:31 INFO(ResourceController :134) Request header cache-control : no-cache
      2013-05-14 19:08:31 INFO(ResourceController :134) Request header pragma : no-cache
      2013-05-14 19:08:31 INFO(ResourceController :134) Request header user-agent : Java/1.6.0_32
      2013-05-14 19:08:31 INFO(ResourceController :134) Request header host : localhost:8080
      2013-05-14 19:08:31 INFO(ResourceController :134) Request header accept : text/html, image/gif, image/jpeg, ; q=.2, */; q=.2
      2013-05-14 19:08:31 INFO(ResourceController :134) Request header connection : keep-alive
      2013-05-14 19:08:31 INFO(ResourceController :145) Request parameter test_param3 : 한글
      2013-05-14 19:08:31 INFO(ResourceController :145) Request parameter test_param2 : b1
      2013-05-14 19:08:31 INFO(ResourceController :145) Request parameter test_param2 : b2
      2013-05-14 19:08:31 INFO(ResourceController :145) Request parameter test_param1 : a
      2013-05-14 19:08:31 INFO(ResourceController :145) Request parameter oauth_signature : 9j8i7MGdC6sn9lx25JVuBSSR2+Y=
      2013-05-14 19:08:31 INFO(ResourceController :145) Request parameter oauth_version : 1.0
      2013-05-14 19:08:31 INFO(ResourceController :145) Request parameter oauth_nonce : -569464277982872277
      2013-05-14 19:08:31 INFO(ResourceController :145) Request parameter oauth_signature_method : HMAC-SHA1
      2013-05-14 19:08:31 INFO(ResourceController :145) Request parameter oauth_consumer_key : consumer-k1
      2013-05-14 19:08:31 INFO(ResourceController :145) Request parameter oauth_timestamp : 1368526111
      
    • Authorization Header 방식 요청 로그

      2013-05-14 19:11:20 INFO(ResourceController :134) Request header authorization : OAuth oauth_consumer_key="consumer-k1", oauth_nonce="5764238330992867426", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1368526280", oauth_version="1.0", oauth_signature="gBypNLwwuv4C2%2FQzUNmpgV%2B0Fic%3D"

      2013-05-14 19:11:20 INFO(ResourceController :122) Request method : GET
      2013-05-14 19:11:20 INFO(ResourceController :123) Request contextPath :
      2013-05-14 19:11:20 INFO(ResourceController :124) Request pathInfo : null
      2013-05-14 19:11:20 INFO(ResourceController :125) Request pathTranslated : null
      2013-05-14 19:11:20 INFO(ResourceController :126) Request queryString : test_param1=a&test_param2=b1&test_param2=b2&test_param3=%ED%95%9C%EA%B8%80 2013-05-14 19:11:20 INFO(ResourceController :127) Request requestURI : /oauth/getResource
      2013-05-14 19:11:20 INFO(ResourceController :128) Request requestURL : http://localhost:8080/oauth/getResource
      2013-05-14 19:11:20 INFO(ResourceController :129) Request servletPath : /oauth/getResource
      2013-05-14 19:11:20 INFO(ResourceController :134) Request header authorization : OAuth oauth_consumer_key="consumer-k1",  oauth_nonce="5764238330992867426", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1368526280", oauth_version="1.0", oauth_signature="gBypNLwwuv4C2%2FQzUNmpgV%2B0Fic%3D"
      2013-05-14 19:11:20 INFO(ResourceController :134) Request header cache-control : no-cache
      2013-05-14 19:11:20 INFO(ResourceController :134) Request header pragma : no-cache
      2013-05-14 19:11:20 INFO(ResourceController :134) Request header user-agent : Java/1.6.0_32
      2013-05-14 19:11:20 INFO(ResourceController :134) Request header host : localhost:8080
      2013-05-14 19:11:20 INFO(ResourceController :134) Request header accept : text/html, image/gif, image/jpeg, ; q=.2, */; q=.2
      2013-05-14 19:11:20 INFO(ResourceController :134) Request header connection : keep-alive
      2013-05-14 19:11:20 INFO(ResourceController :145) Request parameter test_param3 : 한글
      2013-05-14 19:11:20 INFO(ResourceController :145) Request parameter test_param2 : b1
      2013-05-14 19:11:20 INFO(ResourceController :145) Request parameter test_param2 : b2
      2013-05-14 19:11:20 INFO(ResourceController :145) Request parameter test_param1 : a
      

네이버 클라우드 플랫폼 File Storage REST API 사용하기

네이버 클라우드 플랫폼 File Storage REST API는 네이버 클라우드 플랫폼 File Storage에 존재하는 컨테이너, 폴더, 파일을 외부에서 제어할 수 있게 해주는 외부 인터페이스입니다. 네이버 클라우드 플랫폼 File Storage REST API를 이용해서 컨테이터 조회, 폴더 생성 및 삭제, 파일 업로드, 다운로드, 삭제, 권한 변경 및 목록 조회를 할 수 있습니다.

자세한 내용은 "네이버 클라우드 플랫폼 File Storage REST API 레퍼런스"를 참고합니다.

네이버 클라우드 플랫폼 File Storage JAVA API 사용하기

JAVA로 개발하는 경우 REST API를 사용하는 것보다 쉽고 빠르게 개발할 수 있도록 JAVA SDK를 제공합니다. 이 SDK에서 제공하는 기능을 사용하면 OAuth 인증에 대한 처리를 할 필요 없이 네이버 클라우드 플랫폼 File Storage에 필요한 기능을 바로 사용할 수 있습니다.

사전 준비 사항

네이버 클라우드 플랫폼 File Storage 자바 라이브러리에는 컨테이너에 대한 생성, 삭제 및 인증 키 관련된 기능이 포함되어 있지 않습니다. 사용자는 네이버 클라우드 플랫폼 웹사이트에 접속해서 컨테이너 및 인증키를 생성해야 합니다.

  • 컨테이너 생성
    네이버 클라우드 플랫폼 File Storage 서비스에 가입한 후 네이버 클라우드 플랫폼 콘솔에 접속해서 컨테이너를 생성합니다. 자세한 생성 방법은 "컨테이너 생성"을 참고합니다.
  • 인증키 생성
    네이버 클라우드 플랫폼 서비스 계정 생성 시 발급되는 API 인증키를 이용하거나 추가로 생성할 수 있습니다. 인증키는 access key와 secrete key로 분리되어 있으며, 네이버 클라우드 플랫폼 File Storage 자바 라이브러리를 사용하려면 두 키값을 모두 알고 있어야 합니다. 발급된 인증키는 네이버 클라우드 플랫폼 웹사이트 로그인 후 마이페이지 > API 인증키 관리에서 확인할 수 있습니다.

자바 라이브러리

네이버 클라우드 플랫폼 File Storage 자바 라이브러리는 다음과 같이 구성됩니다.

  • doc: Javadoc 파일(네이버 클라우드 플랫폼 File Storage Java API 레퍼런스)
  • lib: 네이버 클라우드 플랫폼 File Storage 라이브러리 및 의존 관계에 있는 라이브러리

네이버 클라우드 플랫폼 File Storage는 다음과 같은 외부 라이브러리에 대한 의존성이 있습니다.

프로그램 작성

네이버 클라우드 플랫폼 File Storage 프로그램의 기본 작성 방법은 다음과 같습니다.

  • 모듈 리소스 초기화 및 제거
    네이버 클라우드 플랫폼 File Storage Java API는 HTTP connection 관리 기능을 초기화하는 것으로 시작합니다.

      import com.ncloud.filestorage.FSRestClient;
      import com.ncloud.filestorage.model.*;
      … FSRestClient.initialize();
    
    • FSRestClient는 com.ncloud.filestorage.model.FSClient 인터페이스를 구현한 클래스로서, 네이버 클라우드 플랫폼 File Storage 기능을 사용하는 데 있어서 핵심이 되는 클래스입니다. 나머지 클래스는 FSClient 인터페이스를 구현하는 보조 역할을 합니다.
    • FSRestClient.initialize() static method는 웹 서버와의 연결을 위해 사용할 연결 관리자(connection pool manager)를 초기화합니다. 모듈을 초기화하지 않고 API를 사용하면 FSClientException이 발생합니다. 모듈을 더 이상 사용할 필요가 없으면 FSRestClient.destroy() static method를 호출합니다.
  • 서버 접속
    접속할 REST 서버에 대한 연결 정보 및 인증키(access key, secrete key)를 이용해 FSRestCleint 객체를 생성합니다. 해당 클래스는 thread safe하며, 모듈의 connection pool 기능을 사용합니다.

      FSRestClient client;
      client = new FSRestClient(<호스트명>, <포트 번호>, <access key>, <secrete key>);
    
  • 업로드 예제
    서버 접속까지 완료되었으면 FSRestClient에서 정의된 메서드를 호출해서 네이버 클라우드 플랫폼 File Storage에서 제공하는 서비스를 사용할 수 있습니다. 다음은 파일 업로드 예제입니다.

      import com.ncloud.filestorage.FSRestClient; import com.Naver Cloud 플랫폼.filestorage.model.*;
      ….
    
      File file = new File(<업로드대상 파일 경로>);
      // 업로드 대상 파일이 존재하는지 여부 체크
      if (null == file || false == file.isFile()){
          return false;
      }
    
      //모듈 초기화
      FSRestClient.initialize();
      // 호스트, 포트는 File STorage REST 서버에 대한 접속 정보
      // API 키는 미리 알고 있어야 합니다.
      FSRestClient client = new FSRestClient(<호스트명>, <포트 번호>, <access key>, <secrete key>);
    
      try {
      // 컨테이너 이름은 구매한 이름을 사용해야 합니다.
      FSResourceID rid = new FSResourceID("<컨테이너 이름>/test.txt");
    
      //간단한 string을 만들어 java.io.InputStream 객체를 만든다
      String content = "This is test";
      InputStream ins = new ByteArrayInputStream(content.getBytes());
    
      //저장할 파일 내용과 content-type을 지정합니다.
      FSUploadSourceInfo info = new FSUploadSourceInfo(ins, "text/plain",
      content.getBytes().length, null);
      //파일을 업로드한다
      FSUploadFileResult result = client.uploadFile(rid, info);
      } catch (FSClientException e) {
      // 클라이언트 단에서 발생한 exception
      } catch (FSServiceException e) {
      // 서비스 단에서 발생한 exception
      }
    
      //더 이상 사용하지 않는 경우 초기화 시 생성한 resource를 제거합니다.
      FSRestClient.destroy();
    
  • 대용량 파일 업로드 예제
    파일 스토리지의 업로드 대상 파일이 2GB보다 큰 경우, 라지 파일 업로드 기능으로 업로드할 수 있습니다.
    다음은 라지 파일 업로드 예제입니다.

import com.ncloud.filestorage.FSRestClient;
import com.ncloud.filestorage.model.*;
….

//모듈 초기화
FSRestClient.initialize();

// 호스트, 포트는 파일스토리지 REST 서버에 대한 접속 정보
// API 키는 미리 알고 있어야 합니다.
FSRestClient client = new FSRestClient(<호스트명>, <포트 번호>, <accessKey>, <secretKey>);

// fileMimeType : 업로드 대상 파일의 content-type을 설정합니다.
// mime 참조 : https://ko.wikipedia.org/wiki/MIME#Content-Type
FSLargeFileInitiateRequest request = new FSLargeFileInitiateRequest(fileMimeType, null);

// 컨테이너 이름은 구매한 이름을 사용해야 한다, 파일명을 업로드할 파일명으로 설정합니다.
FSResourceID rid = new FSResourceID(<컨테이너 이름>+"/"+<파일명>);

try{
    // 라지 파일 업로드를 위한 초기화를 합니다.
    client.largeFileInitiate(rid, request);
    long SEPARATE_FILE_SIZE_2G = 2147483647;

    LinkedList<FSPartCompletionInfo> partCompletionInfos = new LinkedList<FSPartCompletionInfo>();
    long partFileSize = 0;
    int separateCount = 1;
    boolean existFilePart = true;

    // 파일을 2G 단위로 짤라서 부분 파일로 업로드합니다. 단 파일사이즈가 2G 이상인 경우
    while( existFilePart ){
        partFileSize = SEPARATE_FILE_SIZE_2G * separateCount;
        if(file.length() < partFileSize){
            existFilePart = false;
            String temp = Long.toString(file.length() - (SEPARATE_FILE_SIZE_2G * (separateCount -1)));
            lastSize = Integer.parseInt(temp);
        }
        // 파일을 짤라서 부분파일로 업로드합니다.
        eTag = partUpload(rid, separateCount, lastSize, client);
        partCompletionInfos.add(new FSPartCompletionInfo(separateCount, eTag));
        separateCount++;
    }

    // 전체 업로드가 완료되면 라지 파일 업로드 작업 완료를 호출합니다.
    if( partCompletionInfos.size() > 0){
        client.largeFileComplete(rid, null, partCompletionInfos);
    }
}catch (Exception e) {
    // 업로드가 실패하면 라지 파일과 관련된 파일을 삭제합니다.
    client.largeFileAbort(rid, null);
}

// 더 이상 사용하지 않는 경우 초기화 시 생성한 resource를 제거합니다.
FSRestClient.destroy();



private String partUpload(FSResourceID rid, int partNum, int lastPartSize, FSRestClient client) throws Exception {
        FSUploadPartResult uploadResult;
        BufferedInputStream ins = null;
        long readByteSize = lastPartSize == 0 ? SEPARATE_FILE_SIZE_2G  : lastPartSize;
        try {
            // 업로드 대상 파일 경로를 설정합니다.
            ins = new BufferedInputStream(new FileInputStream(<file>));
            long startOff = 0;
            if( 1 < partNum ){
                startOff = SEPARATE_FILE_SIZE_2G * (partNum - 1);
            }

            // 전체 파일 중 파일을 일부분만 추출하기 위해서 이전에 업로드 했던 내용은 skip 합니다.
            ins.skip(startOff);

            // 전체 파일 중 일부분을 추출해서 업로드합니다.
            FSPartUploadSourceInfo srcInfo = new FSPartUploadSourceInfo(partNum, readByteSize, ins);
            uploadResult = client.largeFileUploadPart(rid, null, srcInfo);
        } catch (Exception e) {
            throw e;
        } finally {
            if( ins != null)
                ins.close();
            ins.close();
        }
        return uploadResult.getETag();
    }
  • 다운로드 예제
    다음은 파일 다운로드 예제입니다.

      byte[] readBuffer = new byte[1024];
      BufferedInputStream bis = null;
      BufferedOutputStream bos = null;
    
      try {
          //모듈 초기화
          FSRestClient.initialize();
          // 호스트, 포트는 파일스토리지 REST 서버에 대한 접속 정보 
          // API 키는 미리 알고 있어야 한다
          FSRestClient client = new FSRestClient(<호스트명>, <포트 번호>, <access key>, <secrete key>);
    
          // 컨테이너 이름은 구매한 이름을 사용해야 한다
          FSResourceID rid = new FSResourceID("<컨테이너 이름>/test.txt");
          // 파일 저장위치와 파일명을 추가합니다.
          String filePath = "C:\\test.txt";
          bos = new BufferedOutputStream(new FileOutputStream(filePath));
          FSFileDownload fileDownload = client.download(rid, null);
          BufferedInputStream bis = new BufferedInputStream(fileDownload.getInputStream());
    
          int readSize = 0;
          while ((readSize = bis.read(readBuffer, 0, 1024)) != -1) {
              bos.write(readBuffer, 0, readSize);
          }
      } catch (Exception e) {
          throw new Exception(e);
      } finally {
          if (null != bis)
              bis.close();
    
          if (null != bos)
              bos.close();
      }
    

    네이버 클라우드 플랫폼 File Storage Java API에 관한 자세한 설명은 "네이버 클라우드 플랫폼 File Storage JAVA API 레퍼런스"를 참고합니다.

연관 정보 바로가기

아래 가이드에서 연관 정보를 확인할 수 있습니다.

""에 대한 건이 검색되었습니다.

    ""에 대한 검색 결과가 없습니다.

    처리중...