무엇을 공부했나요?
이번 시간에는 Two scoops of Django 24장 ‘장고성능 향상시키기’ 와 25장 ‘Asynchronous Task Queues’을 공부하였습니다. 24장은 안영님이 요약하였고 25장의 내용은 제가, 심화는 연태님이 준비하셨습니다.
성능향상시키기
성능을 향상시키는 여러가지 방법에 대하여서 배웠습니다. 하나의 소프트웨어 제품에는 그것을 이루는 여러가지 계층이 존재하는데요, 그 각각의 성능을 개선하는 방법을 살펴보았습니다.
- Query: 중복 쿼리를 줄인다,인덱스로 최적화한다, slow query를 제거한다
- Database: 로그나 일시적 데이터 포함하지 않기, 각 database(psql 혹은 mysql) 환경 세팅에 주의하기
- Cache: 캐시를 이용할 곳을 잘 정하기, cache invalidation의 시점
- HTML, CSS, Javascript 같은 static file: 압축, 최소화 하기
- 업스트림 캐시나 CDN 사용
성능 향상 시키기와 관련된 챕터에서 항상 빠지지 않고 등장하는 말이 있습니다. ‘서툰 최적화는 해가 될 수 있다.’ 물론 규모가 큰 서비스를 운영하는 회사에서 일을 하다보면 최적화에 신경써야 하고, 새로운 기능을 추가할 때에도 혹은 기존의 기능을 변경할 때에도 규모의 관점에서 항상 사고해야합니다.
그러나 작은 스타트업에서 새로 서비스를 시작한다거나 혹은 개인적으로 서비스를 만들어 운영하다보면 이와 같은 고민들이 무의미할 때가 많습니다. 물론 장인과 같은 마음으로 개발을 하다보면 자신이 만든 제품이 좀 더 완벽하고 멋있길 바랍니다. 그래서 필요하지도 않은 최적화를 시도하거나 큰 규모에서는 제대로 동작하지 않을거라며 지레 겁먹고 개발하기를 주저하는 경우도 있습니다. 제가 그랬었는데요. 그래서 최소한의 기능을 하는 프로덕트조차 만들지 못했었습니다. 지금 생각하면 바보같은 생각이었죠. 단 한명의 사용자도 없는 상태에서 최적화를 고민하고 있었으니까요.
최적화는 당연히 비용적인 측면이나 서비스의 안정적인 측면에서 매우 중요하지만, 생각보다 그 행복한 고민을 하게되는 시점은 꽤 늦게 찾아오니 위의 내용들을 잊지는 마시고 꼭 나중에 그런 시점을 맞이하시길 바랍니다.
비동기 작업 큐를 써야할 때
책에서는 여러가지 상황들을 나열해가며 비동기 작업을 써야할 때와 그렇지 않아야 할 때를 설명해주었습니다. 일반적으로 결과를 처리하는데 시간이 오래걸리는 작업에는 Task queue를 사용하는 것이 좋지만, 결과를 사용자가 즉시 확인하거나 사용해야되는 작업에는 사용하지 않는 것이 좋다고 합니다. 비동기 태스크 큐의 용도와 특징을 생각해보면 당연하다는 생각이 들 것입니다.
몇가지 주의할 점
- 멱등성을 유지할 수 있도록 작성하라!
- 재시도의 가능성이 항상 있기 때문입니다.
- 중요한 데이터를 보관하지 마라!
- retry 메커니즘이 있지만 실패할 가능성이 있습니다. 예를들어 보내야 할 메시지가 있다면 작업 내용에만 메시지가 있는 것이 아니라, 메시지는 Database에 보관해두고 작업큐에서는 해당 메시지를 꺼내와서 보내는 방식으로 하는 것이 좋습니다.
- 공짜가 아니다.
- 눈에 보이지 않게 동작하지만 태스크도 컴퓨팅 파워를 소모하는 작업입니다. 비효율적으로 작성하면 언젠가 반드시 문제가 되어 병목으로 작용할 것입니다.
심화
이번 심화에서는 연태님이 직접 번역하신 글 3개와, 외부 블로그 글 1개를 소개해주셨습니다.
우선 Understanding Postgres Performance 번역에서는 postgres에서 성능 개선을 위해 알면 좋은 팁들을 소개해주셨습니다. 캐시 및 히트율 이해하기 라든지, 인덱스 사용법 이해하기 등의 내용을 8percent 내부의 데이터베이스에 직접 조회해보시면서 내용에 포함 및 설명해주셨었는데, 확실히 스터디를 통해서 얻게 되는 지식이 회사의 제품에 긍정적인 영향들을 많이 끼쳐가는 것을 보면서 (우리 회사는 아니지만 고객이자 스터디원으로서) 기분이 좋았습니다. 더불어 개인적으로 운영하고 있는 서비스에도 postgresql을 사용중인데, 배운 내용을 한번 적용해봐야겠다는 생각도 하였습니다.
두번째로 소개해주신 번역글은 Don’t keep important data in your Celery queue 이었습니다. 셀러리를 이용하면서 알면 좋을 팁을 소개해주셨는데요, 특히 기억에 남았던 것은 이메일을 보내는 task를 처리하는 방식이었습니다. 어떤 object에 email을 보내야 될지를 판별할 수 있는 flag를 넣어 혹시 retry를 하더라도 사용자에게 이메일이 여러번 가지 않도록 하는 것이었습니다.
세번째는 Celery - Best Practices입니다. 셀러리를 활용할 계획이 있으시다면 꼭 한번 보시고 쓰는 것이 좋을 것 같습니다.
또, AMQP에 관한 블로그 글을 소개해주셨습니다. 여러가지 Message queue들이 다른 프로토콜을 가지고 플랫폼 종속적으로 존재하여서 불편함과 비효율성이 존재하였기 때문에 만들어진 것이 AMQP(Advanced Message Queing Protocol)라고 합니다. 메시지 큐에서 사용하는 용어와 내부 알고리즘에 대하여 살펴보았습니다.
어땠나요?
개인적으로 작게 운영중인 서비스에 celery를 올 겨울 도입할 예정이었는데 좋은 내용을 많이 알게 되어 좋았습니다. 최적화는 아직은 할 만큼 필요성이 없어서 아쉬웠지만, 시간이 많이 안걸리는 작업들은 꾸준히 해나가면 좋겠다는 생각이 들었습니다. Database쪽에서 몇 ms를 최적화 하는 것은 효과가 미미하지만, CDN을 이용하거나 static file을 압축하는 것들은 사용자 입장에서 체감이 많이 되는 부분이니까요.
스터디가 이제 막바지에 다다랐습니다. 사실 매 버젼의 Two scoops of Django 책을 샀지만 이 뒷쪽 챕터까지 주의깊게 읽어본 것은 처음이었습니다. 자의에 의해서 강제로 공부하게 되는 스터디의 장점(?)이랄까요. 처음에 비해서 스터디 준비도 덜 열심히 하게 되고 미리 책 읽어오기를 안지키는 경우도 종종 생기게 되었지만 남은 몇번의 스터디는 열심히 해서 꼭 보람차게 마무리 하게 되기를 바랍니다! 라고 썼지만 한달이나 지난 뒤에 쓰는 후기라 기다리셨던 많은 분들께 죄송합니다…