포스트

남은 전역일을 세어주는 정적 이미지 서버 개발기

남은 전역일을 세어주는 정적 이미지 서버 개발기

군대에 정말 오래 있었다.
그러다보니 남은 복무일수를 세는 행위에 큰 의미부여를 하지않았는데…
결국 그 날이 얼마 남지 않게 됐다. ^^
심심한 말년 병장은 전역일을 위한 이벤트를 꾸리게 된다…

0. 개발 동기

어떻게하면 ‘전역’이라는 이벤트를 가장 가시적으로 표현할 수 있을까 고민했다.
개발자라면 깃헙(?) 프로필과 같이 노출이 잘 되는 곳에 노출시키는 것이 가장 이상적이라 판단했고 실제로 깃헙에서는 마크다운에 어떤 방식으로 다양한 컨텐츠를 노출시키는지를 확인해보았다.

1. 서비스 디자인 설계

1) Github Markdown에서 다양한 컨텐츠를 표시하는 방식

깃헙이미지

  • ..? 무슨 복잡한 html이나 javascript 따위의 snippet이 아닌 단순한 이미지였던 것이다.

개인적인 경험에 비춰볼 때 이미지는 매일매일 바뀌어야하는 동적인 컨텐츠를 처리하기에 적합하지 않는다고 생각했었다.

  • 하지만 이미지라고 동적인 컨텐츠를 처리할 수 없는 것도 아니었다.

이미지 자체는 동적이지 않지만 별도로 이미지를 호스팅하는 서버에서 동적으로 이미지를 제공한다면(?) 충분히 동적인 컨텐츠를 제공할 수 있다는 결론에 이르렀다.

2) Heroku

하지만 와타시는 작은 서버를 장만할 돈도 없는 불쌍한 군인인지라
무료 클라우드 서비스를 찾게 되었고 구글신님께서 일침하신 ‘헤로쿠’라는 귀인을 영접하게 되었다.

3) Python(Flask, Pillow)

Heroku에서 선택할 수 있는 workload는 Node.JS, Ruby, Java, PHP(이걸 아직도 쓰네…), Python, Go, Scala, Clojure가 있었지만
간단하게 한 두 시간만에 무지성으로 만들기 위해 그나마 익숙한 Python을 선택했다.

파이썬으로 작성된 웹 프레임워크로는 flask, django 등이 제공되고 있지만 가장 간단하게 만들기 위해 Flask를 선택했다.

무엇보다 이미지를 서버에서 생성해야하는 입장에서 볼 때 다른 언어보다 이미지 생성 라이브러리가 다양한 Python을 사용하는 것이 매우 편리하다고 판단했다.
그리고 이는 실제로 Piilow(PIL, Python Image Library) 이라는 이미지 편집 라이브러리를 선정하는데 매우 편리한 디자인 선택이었다.

2. 유즈케이스 분석

가장 간단한 유즈케이스는 다음과 같다.
(실제로는 Github에서 사용하는 프록시 캐싱서버가 중간에 존재한다.)

1
2
3
4
5
6
7
8
9
10
11
 ┌──────┐     ┌──────┐
 │Client│  ↔  │Server│
 └──────┘     └──────┘
1. Client → Server
  (Request: yyyy/mm/dd)

2. Server에서 이미지 생성
  (yyyy-mm-dd.jpg)

3. Client ← Server
  (Response: yyyy-mm-dd.jpg)
  1. 클라이언트가 yyyy년 mm월 dd일이 전역일인 이미지에 해당하는 리소스 요청
  2. 서버에서 해당되는 이미지 리소스 생성
  3. 생성된 이미지 리소스 제공

3. 개발 도중 발생한 문제점 및 해결책

하지만 저렇게 간단하면 개발은 참 쉬울 것이다…

A) Heroku 사용시 Port 설정 문제 -> 환경변수 가져오기

Heroku는 보안상의 이유로 유저가 올린 App 이 아무 포트나 막 사용하지 못하게 막아두었다.
따라서 환경변수에서 해당 앱이 사용할 수 있는 포트 정보를 가져와야하는 이슈가 있었다.

B) 느린 이미지 로딩 -> 캐싱

캐싱적용안된이미지

  • 매번 요청할 때 마다 이미지를 생성한다면 매번 3.5kB 데이터를 heroku 서버로부터 가져와야할 것이다.

캐싱적용된다른이미지

  • 또한 거의 457ms(약 0.5초)의 시간이 걸리는 것으로 보아 다른 이미지 컨텐츠에 비해 과도하게 로딩이 느린 것을 확인할 수 있다.

  • 이렇듯 이미지를 요청할 때마다 매번 생성하게 된다면 이를 로딩하는 속도가 과도하게 느려질 수 있다. (캐싱이 필요하다!)

C) 캐싱 정책 관리

캐싱을 하기위해 http 캐싱 정책에 대해 알아보았다.
그리고 해당 서비스에 필요한 캐싱 정책은 다음과 같이 정리할 수 있다.

  • 이미지가 매일마다 바뀌면 됨
    • 캐시 유효 기간(Expire값)은 다음날 전까지 설정
  • 이미 만들어둔 이미지가 있다면 그 이미지를 사용하면 되도록 설정
    • 이미지 존재 여부로 만들어둔 이미지 호스팅(Last Modified 값을 통해 304 Not Modified 헤더를 제공하는 것이 가능)
  • 이미지가 바뀌기 전까진 동일한 이미지를 재탕해도 무방함
    • 이미지 응답 헤더에 etag를 제공해 브라우저에서 변경여부를 파악할 수 있도록 처리함

그 결과… 캐싱적용된이미지
브라우저 메모리 캐시에서 1ms에 로딩되는 전역일 카운터 이미지를 확인 할 수 있었다.

4. 향후 개선 사항

사실 조금 더 동적으로 이미지를 만들기 위해서는 jpg가 아닌 svg+xml 형태로 이미지를 제공하는 것이 더 좋다.
애니메이션을 넣을 수도 있고 이미지를 늘리거나 줄여도 손상되지 않는 벡터 이미지인 점에서 더 확장성 있는 결과물을 얻을 수 있기 때문이다.

5. 정리

전역이 얼마 안 남은 시점에서 할 짓이 없는 잉여어디까지 미칠 수 있는지를 잘 보여준 프로젝트라 할 수 있을 것 같다. 아마 두 번 다시 이런 일을 할 흑우가 없길 바라는 점에서 이 글을 마친다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

인기 태그