GAN을 활용하여 2D/3D 이미지를 생성하는 웹

정지원·2021년 2월 10일
2

인턴이야기

목록 보기
2/2

2021 Silicon Valley Online Internship

부트캠프에 가까운 인턴십

얼마 전, 5주(2021.01.04 ~ 2021.02.05) 간의 부트캠프같은 인턴십을 마쳤다. SW사업단에서 주관하는 5기 글로벌SW인재트랙이라는 프로그램의 일환으로, 작년까지만 해도 퍼듀대학에 가서 프로젝트를 진행하는 프로그램이었는데 올해는 망할 코로나 때문에 온라인 프로그램으로 대체되었다. (지금 생각해보니 이 프로그램이 더 도움이 된 것 같다 👍)

React, UI/UX, Data Science, Big Data, Machine Learning 등 실리콘밸리에 있는 기업에서 재직 중이신 멘토님들의 강연을 통해 다양한 분야의 트렌드를 배우며 시야가 넓어지는 느낌을 받았다. 특히, 질문하면 피드백을 빠르게 주시는 점이 가장 좋았다. 멘토님을 꽤 많이 괴롭혔던 것 같지만, 좀 더 공부하고 참여했더라면 얻어가는 것이 훨씬 더 많았을 것 같은 아쉬움도 남는다.😋

GAN을 활용하여 2D/3D 이미지를 생성하는 웹

우리 팀의 주제는 GAN을 활용하여 2D/3D 이미지를 생성하는 웹이었다. 이미지를 업로드하고 원하는 화풍을 선택하면 미리 훈련된 모델을 통해 선택한 화풍으로 이미지를 변환하여 결과를 보여주는 방식이다.

나는 팀의 리더이자 백엔드 개발자로서 참여하였으며, 개발 환경 구성부터 아키텍처 설계, 모델 서빙 등 프로젝트의 전반적인 부분을 담당하였고 새롭게 알게된 기술을 적용해보기 위해 노력하였다. 모델 서버를 여러 개의 컨테이너로 두고 메세지 큐(RabbitMQ)를 통해 작업을 분배하거나, 사용자 경험을 고려하여 인메모리 방식의 데이터베이스(Redis)를 캐시로 사용하는 등 기술적인 부분에 집중하여 설계하였고 프로그램이 끝난 지금은 팀의 레포를 포크해서 개인적으로 좀 더 다듬고 배포까지 해볼 생각이다.

아래는 사용했던 몇 가지 기술 스택을 선택한 근거이다.

  • Postgres: 해시로 변환한 파일 이름과 스타일만 저장하면 되었기 때문에 오픈소스이며 팀원들에게 익숙한 RDBMS로 선택했다. 사실 지금 생각해보면 key value 형태의 Redis와 같이 사용하기 때문에 NoSQL DB로 선택하면 더 편할 수도 있었을 것 같기도 하다.
  • Redis: 빠른 속도를 위해 인메모리 DB를 찾았고, Redis와 Memcached 중 Redis는 value에 Set 자료구조를 지원한다. 혹시 모를 중복 이미지 저장를 신경쓰지 않아도 되고, add와 exist가 O(1)이기 때문에 선택했다.
  • RabbitMQ: Redis, ActiveMQ, RabbitMQ를 고민했는데 Redis는 메시지의 Dilivery Guarantee를 지원하지 않아서 제외하였고, ActiveMQ는 예제가 잘 나와있지는 않은 것 같아 새로운 기술을 학습하고 적용하기엔 RabbitMQ가 맞다고 생각했다.

블로커놈들..

정말 많은 이슈들이 있었는데 그 중 기억에 남은 것들을 정리해본다.

  1. react
    • 상황: 메인 화면에서 서버로 이미지를 업로드하고(요청) 이미지 파일의 해시값으로 된 파일명(응답)을 받아서 결과 화면으로 넘어가야 한다.
    • 문제: 메인 화면에서 응답이 오기 전 결과 화면으로 넘어가서 결과 화면에서 이미지를 불러오지 못한다.
    • 해결: react-router-dom의 <Link>로 이동했었는데 응답을 받은 후 넘어가도 됐지만, 페이지가 두 개밖에 안 되고 편하게 하려고 props로 이미지를 넘겨주고 결과 화면에서 이미지를 업로드하는 요청과 결과를 받아오는 요청을 모두 보냈다.
  2. Logger 모듈화
    • 상황: Flask 서버에서 여러 blueprint와 모듈에서 로깅을 하고싶다.
    • 한 곳에서 선언하고 각 모듈에서 가져다 쓰고 싶었지만 대부분의 예제에는 모듈이 하나였고, 선언한 곳에서 import로 가져올 때 app을 찾지 못하거나 로거가 caller 모듈을 제대로 인식하지 못한다.
    • logs 모듈에서 logger를 미리 정의하고 나중에 app을 등록했다. 솔직히 이렇게 하는게 맞는진 모르겠다.. 피드백 주시면 (많이) 감사합니다☺️

logs/__init__.py

from .log import Logger
logger = Logger()

logs/log.py

import json
from logging.config import dictConfig
    
class Logger:
  def __init__(self, app=None, **kwargs):
    if app is not None:
      self.init_app(app, **kwargs)

  def init_app(self, app):
    config = json.load(open("./logs/logger.json"))
    dictConfig(config)
  1. 다중 container의 volume 공유
    • 상황: API서버와 모델서버, 클라이언트가 모두 업로드된 이미지와 결과 이미지의 저장소로 같은 volume을 공유한다.
    • 문제: 이미지를 저장하는 컨테이너에서 저장되는 것을 확인까지 했지만 다른 컨테이너에서 바로 찾지 못한다.
    • 해결: 단순히 1~2초 정도 늦게 찾도록 한다. (임시 방편으로 했지만 해결하는 방법을 모르겠다..😭)
  2. 컨테이너 시작할 때 쉘 스크립트로 실행
    • 상황: API 서버와 모델 서버는 모두 시작할 때 특정 쉘 스크립트를 실행한다.
    • 문제: 쉘스크립트를 실행 못한다.
    • 해결: 권한을 준다. (docker-compose.yml에서 ./modelserver/start-dev.sh:/app/start-dev.sh:ro처럼 뒤에 :ro를 붙여준다.)

아키텍처

시퀀스 모델

결과 예시

일단은 여기까지..

0개의 댓글