본문 바로가기
개발활용툴

이미지 서비스 제공 - Cloudinary(클라우디너리) 활용하기

by 즐거운코딩 2023. 9. 26.
반응형

웹서비스 제공에 있어서 이미지 관리는 중요한 부분중에 하나입니다. 별도의 저장 및 관리 영역이 필요한데 일반 기업형으로는 별도 Storage서버를 통해 관리하지만 클라우드 기반 서비스 또는 개인 프로젝트의 경우 AWS 등 클라우드에서 제공하는 솔루션을 사용하게 됩니다.

 

이번에 소개하는 Cloudinary는 이러한 저장의 고민 뿐만아니라 웹, 모바일 등 다양한 매체를 위한 기능을 제공하고 있어 개인 프로젝트를 진행하는데 무료로 사용이 가능합니다. 

 

1.  Cloudinary 소개

cloudianry는 이미지, 동영상의 업로드, 저장, 관리, 변환(사이즈, 자르기 등), URL 기반 자동 변환, 최적화 등 다양한 기능을 제공하고 있습니다.

개발 편의성을 위해 여러 플랫폼의 호환용 sdk 를 지원합니다.

(React, Node.js, Angular, PHP, Python, Vue.js, Javascript, Kotlin, iOS, Android, Java, Ruby, Flutter, React Native)

https://cloudinary.com/

 

Image and Video Upload, Storage, Optimization and CDN

Streamline media management and improve user experience by automatically delivering images and videos, enhanced and optimized for every user.

cloudinary.com

 

2. 가입 및 비용

  • 회원 가입 : 이메일, 구글, 깃허브
  • 사용료 ('23년9월 기준)

cloudinary price

무료만 이용해도 월 25크레딧 이용 가능 (1크레딧 : 1000번 파일변환 가능)

 

  • Cloudinary 가입시 다음과 같은 사용을 위한 중요 정보가 제공된다
    • Cloud Name
    • API Key
    • API Secret

Node.js 에서 사용하기

  • 설치 : $npm i cloudinary
  • 사용방법
    • file upload
cloudinary.v2.uploader.upload("https://upload.wikimedia.org/wikipedia/commons/a/ae/Olympic_flag.jpg",
  { public_id: "olympic_flag" }, 
  function(error, result) {console.log(result); });
  • transform & customizing
// Transform 
const url = cloudinary.url("olympic_flag", {
  width: 100,
  height: 150,
  crop: 'fill'
});
  • Optimize & deliver
    (URL Endpoint / Optimization / Public Id)
https://res.cloudinary.com/freshpm/image/upload/c_scale,w_500/f_auto/q_auto/samples/bike.jpg

 

Dashboard 에서 사용현황 확인

 

3. 실 사용 예제

프로젝트에서 cloudianry 폴더를 만들고 다음과 같이 index.js 파일을 만듭니다.

const cloudinary = require("cloudinary").v2;
const { CloudinaryStorage } = require("multer-storage-cloudinary");

cloudinary.config({
  cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
  api_key: process.env.CLOUDINARY_KEY,
  api_secret: process.env.CLOUDINARY_SECRET,
});

const storage = new CloudinaryStorage({
  cloudinary,
  params: {
    folder: "PeterCamp",
    allowedFormats: ["jpeg", "png", "jpg"],
  },
});

module.exports = {
  cloudinary,
  storage,
};

cloud_name, api_key, api_secret 는 .env file에 별도 관리하고 불러서 사용합니다.

storage의 params로 cloudinary내 프로젝트 폴더를 지정하고, 파일 포맷도 지정 가능합니다.

 

라우트 설정에서 아래와 같이 cloudinary 사용등록합니다.

const { storage } = require("../cloudinary");
const upload = multer({ storage });
router
  .route("/")
  .get(catchAsync(campgrounds.index))
  .post(
    isLoggedIn,
    upload.array("image"),
    validateCampground,
    catchAsync(campgrounds.createCampground)
  );

upload.array로 여러 개 이미지 등록 가능 하도록 합니다.

아래와 같이 html 에서 이미지 업로드 할 때 input 으로 multiple 지정(여러 개 파일) 하고 id를 "image" 로 설정합니다.

      <div class="mb-3">
        <div class="input-group mb-3">
          <input
            type="file"
            class="form-control"
            id="image"
            name="image"
            multiple
          />
          <label class="input-group-text" for="image">Upload</label>
        </div>

라우터에서 호출하는 createCampground 는 아래와 같이 설정합니다.

module.exports.createCampground = async (req, res) => {
  if (!req.body.campground)
    throw new ExpressError("Invalid Campground Data", 400);
  const campground = new Campground(req.body.campground);
  campground.geometry = geoData.body.features[0].geometry;
  campground.images = req.files.map((f) => ({
    url: f.path,
    filename: f.filename,
  }));
  campground.author = req.user._id;
  console.log(campground);
  await campground.save();
  req.flash("success", "Successfully made a new campground!");
  res.redirect(`/campgrounds/${campground._id}`);
};

cloudinary에서 받은 url과 filename 을 DB에 저장하기 위해 사전에 아래와 같이 Schema를 변경합니다.

const ImageSchema = new Schema({
  url: String,
  filename: String,
});

ImageSchema.virtual("thumbnail").get(function () {
  return this.url.replace("/upload", "/upload/w_200");
});

const CampgroundSchema = new Schema({
  title: String,
  images: [ImageSchema],
  price: Number,
  description: String,
  location: String,
  author: {
    type: Schema.Types.ObjectId,
    ref: "User",
  },
  reviews: [
    {
      type: Schema.Types.ObjectId,
      ref: "Review",
    },
  ],
});

여러 개 이미지 파일 등록이 가능하기 때문에 보기 편의성과 향후 사용성을 고려하여 ImageSchema로 분리하여 등록하고 CampgraoundSchema에 images 항목에 반영합니다.

반응형