반응형

AWS의 S3에 이미지를 올리면 자동으로 썸네일을 만들어 주는 람다에 대해 설명합니다.

다음은 이글의 유튜브 강의입니다.

https://youtu.be/fMtNmmtlLig


홈페이지에 갤러리 기능을 만들게 되면 꼭 필요한게 이미지의 썸네일 입니다.

이미지를 업로드 할때마다 썸네일을 별도로 제작하기는 너무 귀찮은 작업이죠.

이럴때 AWS의 람다를 사용하면 썸네일을 자동으로 생성할 수 있습니다.

 

해당 내용은 AWS 공식 홈페이지에 자세하게 설명이 되어 있습니다.

https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/with-s3-tutorial.html

 

자습서: Amazon S3 트리거를 사용하여 썸네일 이미지 생성 - AWS Lambda

자습서: Amazon S3 트리거를 사용하여 썸네일 이미지 생성 이 자습서에서는 Lambda 함수를 생성하고 Amazon Simple Storage Service(Amazon S3)에 대한 트리거를 구성합니다. Amazon S3는 S3 버킷에 업로드된 각 이

docs.aws.amazon.com

해당 내용을 기반으로 썸네일 자동 생성 기능을 만들어 봅니다.

 

순서는 다음과 같습니다.

1. AWS CLI 설치

2. 버킷 생성

3. IAM 역할(Role) 생성

4. 리사이즈용 프로그램 개발(Python)

5. 프로젝트 빌드

6. 배포

7. S3 트리거 생성

8. 테스트

 

1. AWS CLI 설치

간단한 파이썬 코드를 작성할 경우에는 AWS 콘솔에서도 파이썬 라이브러리가 포함되어 있기 때문에 작업이 가능하지만,

이미지 썸네일을 만드는 경우에는 pillow라는 라이브러리를 사용해야 하므로 콘솔에서는 처리가 어렵습니다.

따라서 로컬에서 라이브러리를 다운받아 서버에 배포하는 과정이 필요합니다.

 

로컬에서 람다 패키지를 만들어 서버에 배포하기 위해서는 AWS CLI를 사용합니다.

다음 URL에 각OS별 설치 방법에 따라 설치를 합니다.

https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html

 

최신 버전의 AWS CLI 설치 또는 업데이트 - AWS Command Line Interface

이전 버전에서 업데이트하는 경우 unzip 명령을 실행하면 기존 파일을 덮어쓸지 묻는 메시지가 표시됩니다. 스크립트 자동화와 같은 경우에 이러한 프롬프트를 건너뛰려면 unzip에 대한 -u 업데이

docs.aws.amazon.com

 

2. 버킷 생성

AWS 콘솔에 로그인해서 S3 서비스에서 버킷을 만들어 줍니다. (기존 버킷을 사용해도 됨)

 

저는 다음과 같이 버킷을 생성하였습니다.

  • codegear-slider-bucket

 

다음과 같이 폴더를 2개 생성합니다.

  • images : 이미지 업로드용 폴더
  • resized-images : 썸네일 자동 생성 이미지 저장용 폴더

 

3. IAM 역할(Role) 생성

AWS 콘솔의 IAM으로 이동.

액세스 관리 - 역할(Role) 메뉴로 이동하여 "역할 만들기"를 클릭.

  • Role Name : S3_Image_Resize

권한 정책에는 다음 3가지를 추가합니다.

  • AmazonS3FullAccess (S3 Access 권한)
  • AWSLambdaBasicExecutionRole (Clowd Watch 로그 작성 권한)
  • AWSLambda_FullAccess (Lambda Access 권한)

 

4. 리사이즈용 프로그램 개발(Python)

로컬환경에서 이미지 리사이즈용 파이썬 프로젝트를 생성합니다.

lambda-s3-python 폴더를 생성하고 생성된 폴더로 이동합니다.

  • lambda_function.py로 파이썬 소스 파일을 생성합니다.

다음과 같이 코드를 생성합니다.

import boto3
import os
import sys
import uuid
from urllib.parse import unquote_plus
from PIL import Image
import PIL.Image

s3_client = boto3.client('s3')

def resize_image(image_path, resized_path):
  base_width = 300
  with Image.open(image_path) as image:
    w_percent = (base_width/float(image.size[0]))
    h_size = int((float(image.size[1])*float(w_percent)))
    image = image.resize((base_width,h_size), Image.ANTIALIAS)
    image.save(resized_path)

def lambda_handler(event, context):
  for record in event['Records']:
    bucket = record['s3']['bucket']['name']
    key = unquote_plus(record['s3']['object']['key'])
    tmpkey = key.replace('/', '')
    download_path = '/tmp/{}{}'.format(uuid.uuid4(), tmpkey)
    upload_path = '/tmp/resized-{}'.format(tmpkey)
    s3_client.download_file(bucket, key, download_path)
    resize_image(download_path, upload_path)
    s3_client.upload_file(upload_path, '{}'.format(bucket), 'resized-{}'.format(key))

pillow 파이썬 라이브러리를 package 폴더에 설치합니다.

pip install --target ./package pillow

template.yaml 파일을 루트폴더에 생성합니다.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  CreateThumbnail:
    Type: AWS::Serverless::Function
    Properties:
      Handler: lambda_function.lambda_handler
      Runtime: python3.9
      Timeout: 10
      Policies: AWSLambdaExecute
      Events:
        CreateThumbnailEvent:
          Type: S3
          Properties:
            Bucket: !Ref SrcBucket
            Events: s3:ObjectCreated:*

  SrcBucket:
    Type: AWS::S3::Bucket

requirements.txt 파일을 루트폴더에 생성합니다.

Pillow == 9.2.0

 

5. 프로젝트 빌드

다음 명령어로 배포용 패키지를 빌드 합니다.

sam build --use-container

 

6. 배포

서버에 람다 함수를 배포합니다.

sam deploy --guided

 

 

7. S3 트리거 생성

AWS의 Lambda 서비스로 이동.

생성된 Lambda 함수를 클릭 후 함수명 클릭.

함수 개요에서 "트리거 추가"를 클릭합니다.

트리거 구성 아래의 소스 선택에 "S3"를 입력한 후 나타나는 S3를 선택합니다.

버킷을 선택하고, 접두어에는 버킷의 폴더명을, 체크박스를 체크하고 추가를 선택합니다.

아래와 같이 트리거가 추가 된걸 볼 수 있습니다.

8. 테스트

버킷의 images 폴더에 이미지를 업로드 합니다.

resized-images 폴더에 아래와 같이 이미지가 생성된것 볼 수 있습니다.

이미지를 다운받아 속성을 보면 크기가 "300 X 168 픽셀"로 만들어졌음을 볼 수 있습니다.

 

이상으로 AWS의 람다 기능을 이용해서 S3에 업로드된 이미지의 썸네일을 자동으로 만들어 보았습니다.

반응형
반응형

이 글은 NestJS 프로젝트에서 OpenAI의 API를 이용하는 방법에 대해 설명합니다.

 

다음은 이 글의 유튜브 강의 입니다.

https://youtu.be/2DRxtCwjFtE

순서

- OpenAI API Key 생성

- Nestjs 프로젝트 생성

- OpenAI 패키지 설치

- 프로그램 개발

- 테스트

 

OpenAI API 키 생성하기

- OpenAI 사이트에서 회원 가입을 합니다.

https://platform.openai.com/

 

OpenAI API

An API for accessing new AI models developed by OpenAI

platform.openai.com

- 우측 상단의 계정 아이콘을 클릭하고, 메뉴에서 View API Key를 선택합니다.

- "+ Create new Secret key"를 클릭하여 새로운 키를 생성합니다.

- API 사용법은 사이트 상단의 "API Reference" 메뉴에 자세히 나와 있으니 참고하시기 바랍니다.

https://platform.openai.com/docs/api-reference/introduction

 

OpenAI API

An API for accessing new AI models developed by OpenAI

platform.openai.com

 

NestJS 프로젝트 생성

- 아래와 같이 프로젝트를 생성합니다.

nest new 프로젝트명

- Editor에서 프로젝트 열기를 하고 프로젝트를 선택합니다.

 

OpenAI 패키지 설치

Nestjs에서 OpenAI API를 사용하기 위해서는 "openai" 패키지를 설치해야합니다.

- 아래와 같이 패키지를 설치합니다.

npm install openai

 

프로그램 개발

app.service.ts를 다음과 같이 작성합니다.

- 아래와 같이 패키지를 import 하고 openai를 선언합니다.

import { Configuration, OpenAIApi } from "openai";
const configuration = new Configuration({
    organization: "org-xxxxxxxxxxxxxxxxxxxxxxxxxxx",
    apiKey: "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxx",
});
const openai = new OpenAIApi(configuration);

- getHello()를 아래와 같이 작성합니다.

async getHello() {
    const response = await openai.createCompletion({
      model: "text-davinci-003",
      prompt: ""나는 인공지능 AI Chatbot이야. 질문을 하면 내가 답변을 해줄께. 만약 모른다면 \"모름\"이라고 할께.\n\nQ: 한국인의 기대 수명은 얼마야?\nA:",
      temperature: 0,
      max_tokens: 100,
      top_p: 1,
      frequency_penalty: 0.0,
      presence_penalty: 0.0,
      stop: ["\n"],
    });
    return { result: response.data.choices[0].text };
  }

- 여기선 model로 text-davinci-003을 사용하였습니다.

- 모델의 종류를 보시려면 다음과 같이 api를 호출하면 됩니다.

const response = await openai.listModels();
return { result: response.data };

- 주로 많이 사용하는 모델은 gpt-3.5-turbo, text-davinch-003 입니다.

테스트

- 브라우저에서 다음 주소를 입력합니다.

http://localhost:3000/

아래와 같이 결과가 나옵니다.

 

 

반응형
반응형

1. 딥러닝이 가져온 AI의 변화

ChatGPT가 쏘아올린 AI의 열기가 뜨겁습니다.

과거에도 AI에 대한 관심이 높아졌던 시기가 여러번 있었습니다. 하지만 이러한 관심은 독감처럼 잠시 유행하다 지나가 버리곤 했습니다. 사람들이 갖고 있는 AI에 대한 기대치가 너무 높았던 것 일까요? 번번히 AI는 그것에 못미치는 성과를 보여주며 실망을 안겨주었습니다.
그러던 중 "딥마인드"라는 영국의 AI 회사에서 개발한 "알파고"가 등장 하였습니다. 알파고는 "이세돌"이라는 바둑계의 젊은 영웅을 4:1로 무찌르면서 엄청난 이슈가 되었습니다. 알파고는 딥러닝이라는 새로운 알고리즘으로 무장하고 인간 바둑계의 무림을 평정한 것이었죠. 그러나 사람들은 바둑이라는 한정된 카테고리이기 때문에 가능할 것이라고 생각 했습니다. 아직까지도 AI가 사람처럼 생각하고 상황에 적절한 답을 주는 것은 어려웠기 때문이었습니다.
그러나 최근 등장한 ChatGPT는 달랐습니다.
이 서비스가 보여주는 답변은 놀라움 그 자체였습니다. 일상의 대화에서 부터 시작해 다양한 분야의 깊이 있는 질문에도 양질의 답변을 내놓습니다. 심지어 철학적인 질문에도 답변을 내어 놓습니다.
ChatGPT에게 "삶의 의미는 무엇일까?"라는 질문을 한번 해보았습니다.
ChatGPT가 내놓은 삶의 의미에 대한 답변
초기 AI는 Rule 기반의 프로그램이었습니다. 하지만 사람이 모든 Rule을 만들수 없다는 한계가 있습니다. 이를 극복하기 위해 사람의 뇌를 흉내낸 인공 신경망이 나오게 되고, 이제 컴퓨터가 스스로 학습을 할 수 있는 환경이 만들어지게 되었습니다.
거기에 하드웨어의 발달, GPU와 같은 고속 컴퓨팅 기술의 발전이 더해짐으로 인해 AI의 처리 속도가 빨라지게 되었습니다.
ChatGPT는 초거대 언어 모델의 AI 챗봇입니다. 이는 최신 딥러닝 기술과 고속 컴퓨팅, 그리고 거대 자본을 등에 업고 탄생한 것입니다. 이제 AI는 단순한 유행이 아닌 새로운 시대의 혁명이 될 수 있는 여건이 마련된 것입니다.
 

2. AI의 발전이 가져올 개발자 세계의 변화

이런 AI의 발전이 개발자의 삶에는 어떠한 영향을 미칠까요?
이미 프로그래밍 분야에서도 AI를 이용한 기술의 발전이 있었고 대중화 되기 시작했습니다.
ChatGPT에게도 아래와 같이 코드를 요청할 수 있습니다.

ChatGPT가 만든 코드

Github의 Copilot을 이용하면 내가 작성하고 있는 코드의 맥락을 이해하고 다음 코드를 자동으로 추천해줍니다.
(copilot은 월1만원의 유료서비스입니다) 개발자는 추천 코드가 맞다면 tab키를 눌러 코드를 완성할 수 있고, 다른 추천 코드를 요청할 수도 있습니다. 이런 서비스를 이용하게되면 개발자가 실제로 코딩하는 양이 획기적으로 줄어들게 됩니다.
아래는 Copilot이 코드를 추천해 주는 모습입니다.
Copilot의 코드 추천 기능
이 두가지 서비스(ChatGPT, Copilot) 모두 OpenAI에서 개발한 서비스입니다.
이렇게 개발이 자동화 되면 우리는 좀 더 고차원적인 일을 할 수 있게 됩니다. 대신 우리는 AI에게 일을 시킬수 있는 능력이 필요합니다. 당연히 일을 잘 시키기 위해서는 AI를 잘 이해하는 High Performer가 되어야겠죠.
결국 미래에는 AI를 잘 이해하고 사용하는 개발자가 살아 남을 수 밖에 없을 것입니다.
우리가 학자들처럼 AI의 모든 논문을 이해하고 연구할 필요는 없습니다. 새로운 이론과 기술이 나오고 약간의 시간이 지나면 대중화되는 단계가 오게 됩니다. 우리는 이걸 잘 이용할 수 있으면 되는 것입니다.
2010년경 모바일로 전환되는 시기에 기회가 왔던것 처럼, 어쩌면 지금이 AI로 전환하는 최적의 시기이고 개발자에게는 또다른 기회가 될 것입니다.

이런 기회를 놓치지 않으시길 바랍니다.

반응형
반응형

다음은 이 글의 동영상 강좌입니다.

https://youtu.be/Dr4OXDLGsmI

Nestjs 프로젝트를 Docker화 하면 Application을 손쉽게 배포할 수 있습니다.

 

Docker가 설치된 서버에 docker로 빌드된 이미지만 업로드 하고 실행하면 됩니다.

github actions, aws pipeline등을 사용하면 모든 배포 단계를 자동화 할 수 있습니다.

이런 자동화를 통해 프로젝트의 생산성을 획기적으로 높일 수 있고,
개발자를 배포의 늪에서 해방 시켜 업무의 만족도를 높일 수 있습니다.

 

사전 설치 프로그램

우선 다음 프로그램을 설치합니다.

  • Nodejs
  • Docker
  • Nestjs를 사용하기 위해 nest cli를 설치합니다.
npm i -g @nestjs/cli

 

프로젝트 생성 및 실행

Nestjs 프로젝트를 생성합니다.

nest new nest-docker

 

프로젝트를 실행합니다.

npm start

 

Dockerfile / .dockerignore 파일 작성

프로젝트 root 폴더에 "Dockerfile" 파일을 생성합니다.

  • docker image 빌드시 사용하는 설계도입니다.
FROM node:18
RUN mkdir -p /var/app
WORKDIR /var/app
COPY . .
RUN npm install
RUN npm run build
EXPOSE 3000
CMD [ "node", "dist/main.js" ]

프로젝트 root 폴더에 ".dockerignore" 파일을 생성합니다.

  • container에 불필요한 파일들이 복제되는 것을 막기 위한 용도입니다.
.git
*Dockerfile*
node_modules

 

Docker 이미지 생성

다음 명령으로 docker 이미지를 생성합니다.

docker build . -t nest-docker

 

Docker 실행

다음 명령으로 docker를 실행합니다.

docker container run -d -p 3000:3000 nest-docker

 

브라우저에서 확인해보기

브라우저에서 다음 url을 입력하여 확인합니다.

http://localhost:3000

다음과 같이 결과를 확인할 수 있습니다.

 

반응형
반응형

다음은 이 글의 동영상 강좌입니다.

https://youtu.be/yjhIxpR_-gE

연재 마지막 순서로 첫화면에 이미지 슬라이드를 같이 개발합니다.

 

우선 관리자에서 이미지를 5개 정도 업로드합니다.

이미지 슬라이드는 Bootstrap-vue의 Carousel 컴퍼넌트를 사용합니다. 

https://bootstrap-vue.org/docs/components/carousel

 

BootstrapVue

Quickly integrate Bootstrap v4 components with Vue.js

bootstrap-vue.org

Carousel 소스를 복사하여 다음과 같이 수정합니다.

pages/index.vue

<template>
  <div>
    <b-carousel
      id="carousel-1"
      v-model="slide"
      :interval="4000"
      controls
      indicators
      background="#ababab"
      img-width="1024"
      img-height="480"
      style="text-shadow: 1px 1px 2px #333;"
      @sliding-start="onSlideStart"
      @sliding-end="onSlideEnd"
    >
      <!-- Text slides with image -->
      <div v-for="slider in sliders" v-bind:key="slider.id">
        <b-carousel-slide
          caption="First slide"
          text="Nulla vitae elit libero, a pharetra augue mollis interdum."
          :img-src="slider.imageUrl"
        ></b-carousel-slide>
      </div>
      
    </b-carousel>

    <p class="mt-4">
      Slide #: {{ slide }}<br>
      Sliding: {{ sliding }}
    </p>
  </div>
</template>
<script>
export default {
  name: 'IndexPage',
  data() {
    return {
      sliders: '',
      slide: 0,
      sliding: null
    }
  },
  computed: {
    accessToken() {
      return this.$store.state.accessToken;
    }
  },
  mounted() {
    this.getSliders();
  },
  methods: {
    async getSliders(){
      const options = {
          headers: {
              Authorization: `Bearer ${this.accessToken}`
          }
      }
      const path = '/slider';
      await this.$axios.get(
        path,
        options
      ).then(response=> {
        this.sliders = response.data;
        console.log(this.sliders);
      }).catch(error => {
        console.log(error);
      })
    },
    onSlideStart(slide) {
      this.sliding = true
    },
    onSlideEnd(slide) {
      this.sliding = false
    }
  }
}
</script>

서버를 실행하면 다음과 같이 화면이 스크롤 됩니다.

이렇게 해서 이미지 슬라이드가 완성되었습니다.

 

Vue와 Nestjs를 공부하시는 분들에게 도움이 되었으면 좋겠습니다.

 

수고하셨습니다^^

반응형

+ Recent posts