image

aws-sdk (S3 가져오기)

태그
DevJavascript
상세설명aws-sdk (S3 가져오기)
작성일자2024.04.21

개인 블로그에 있는 내용 중 project 페이지에서 사용될 이미지는 AWS S3에 저장 후 페이지로 가져오는 방법을 선택해 해당 방법에 대해 정리해보았다.

AWS SDK 사용법

S3 서비스만 필요함으로 @aws-sdk/client-s3를 설치했다.

개별 서비스 클래스를 바로 import 하면 메모리를 절약할 수 있다는 장점이 있다.

npm

https://www.npmjs.com/package/@aws-sdk/client-s3

// 개별 서비스
npm i @aws-sdk/client-s3

const { S3Client } = require("@aws-sdk/client-s3");

AWS Credentials : aws region 및 자격증명 설정

AWS 서비스와 연동하기 위해선 자격증명(Credentials)인 accessKeyId와 secretAccessKey가 필요하다. 해당 키들은 .env에 저장 후 불러온다.

관련글 : https://minsunblog.com/blog/6f019894-87f0-4944-a0b5-fb251a085586

//aws s3 image
  const credentials = {
    accessKeyId: AWS_KEY,
    secretAccessKey: AWS_SECRET_KEY,
  };

  const s3Client = new S3Client({
    region: AWS_REG,
    credentials: credentials,
  });

객체 목록 : ListObjectsV2Command()

ListObjectsV2Command() 를 통해 S3에 저장된 폴더 내 객체 목록을 가져오는 요청 설정하고 S3클라이언트를 사용하여 폴더 내 객체 목록을 가져온다.

import { AWS_KEY, AWS_REG, AWS_SECRET_KEY } from "libs/config";
const { S3Client, ListObjectsV2Command } = require("@aws-sdk/client-s3");

export default function Project({ projects }: ProjectistObject) {
	//...
	const bucketName = "s3.personalblog";
	const folderPrefixImages = "images/";
	const [awsImages, setAwsImages] = useState<string[] | null>(null);
	
	const getObjectsInFolder = async () => {  
		try {
		   // 폴더 내 객체 목록을 가져오는 요청 설정
		   const commandInput = {
		      Bucket: bucketName,
		      Prefix: folderPrefixImages,
		   };
		   const command = new ListObjectsV2Command(commandInput);

		   // S3 클라이언트를 사용하여 폴더 내 객체 목록을 가져옴
		   const data = await s3Client.send(command);

		    let objectlists = [];
		    for (let object of data.Contents) {
		        // 폴더 객체인 경우 리스트에 추가하지 않음
		      if (!object.Key.endsWith("/")) {
	          objectlists.push(object.Key);
		       }
		     }

		      return objectlists;
		    } catch (error) {
		      console.error(error);
		    }
		};
		return (
		<></>
		)
}

getObjectsInFolder() 이 함수를 페이지 진입 시 실행 하도록 useEffect를 통해 setAwsImages에 저장한다.

useEffect(() => {
    const fetchObjects = async () => {
      try {
        const res = await getObjectsInFolder();
        if (res) {
          const removeFolder = res.map((r: string) => r.split("/")[1]);
          setAwsImages(removeFolder);
        }
      } catch (error) {
        console.error("Error fetching objects:", error);
      }
    };

    fetchObjects();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

해당 파일 명을 cloudfrontBaseUrl에 이어서 붙이면 S3에 저장된 이미지가 나온다.

 {
   awsImages?.map((imagePath: any) => (
      <Image
         src={`${cloudfrontBaseUrl}/images/${imagePath}`}
         alt="image"
         width={300}
         height={300}
         priority
         placeholder="blur"
         blurDataURL={blurDataURL}
         key={imagePath}
     />
))}

전체 코드

아래 코드에서는 aws 이미지들을 <Post /> 컴포넌트로 보내고 있다.

import { AWS_KEY, AWS_REG, AWS_SECRET_KEY } from "libs/config";
const { S3Client, ListObjectsV2Command } = require("@aws-sdk/client-s3");

export default function Project({ projects }: ProjectistObject) {
	//...
	
	//aws s3 image
  const credentials = {
    accessKeyId: AWS_KEY,
    secretAccessKey: AWS_SECRET_KEY,
  };

  const s3Client = new S3Client({
    region: AWS_REG,
    credentials: credentials,
  });

  const bucketName = "s3.personalblog";
  const folderPrefixImages = "images/";
  const [awsImages, setAwsImages] = useState<string[] | null>(null);
  const getObjectsInFolder = async () => {
    try {
      // 폴더 내 객체 목록을 가져오는 요청 설정
      const commandInput = {
        Bucket: bucketName,
        Prefix: folderPrefixImages,
      };
      const command = new ListObjectsV2Command(commandInput);

      // S3 클라이언트를 사용하여 폴더 내 객체 목록을 가져옴
      const data = await s3Client.send(command);

      let objectlists = [];
      for (let object of data.Contents) {
        // 폴더 객체인 경우 리스트에 추가하지 않음
        if (!object.Key.endsWith("/")) {
          objectlists.push(object.Key);
        }
      }

      return objectlists;
    } catch (error) {
      console.error(error);
    }
  };

  useEffect(() => {
    const fetchObjects = async () => {
      try {
        const res = await getObjectsInFolder();
        if (res) {
          const removeFolder = res.map((r: string) => r.split("/")[1]);
          setAwsImages(removeFolder);
        }
      } catch (error) {
        console.error("Error fetching objects:", error);
      }
    };

    fetchObjects();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  
  return (
    <>
      <Seo
        title={`MinSun's Blog | Projects`}
        url={BASE_URL + "/project"}
        desc={"진행했던 프로젝트들을 기록합니다."}
      />
      {mounted && (
        <div className="laptop-max-width">
          <Title
            title={"Projects"}
            subMent={"진행했던 프로젝트들을 기록합니다."}
          />
          <div className="post-content-area">
           {/* .... */}
           
            <div
              className={cls(
                viewStyle === "gallery"
                  ? "page-gallery-style grid-rows-3"
                  : "page-list-style",
                "w-full min-h-[912px] lg:min-h-[904px]"
              )}
            >
              {useSortedData(
                filteredList.map((item: ListResults) => (
                  <Post
                    key={item.id}
                    item={item}
                    viewStyle={viewStyle}
                    tagCategory={tagCategory}
                    awsImages={awsImages}
                  />
                )),
                sortedContent
              ).slice(indexOfFirst, indexOfLast)}
            </div>
          </div>
          {/* .... */}
        </div>
      )}
    </>
  );
 }
}

참고

https://inpa.tistory.com/entry/AWS-SDK-👨🏻‍💻-Nodejs-연동-및-SDK-기본-사용법

https://inpa.tistory.com/entry/AWS-SDK-👨🏻‍💻-Node-S3-메소드-예제-정리