대용량 테이블에서 오래된 데이터를 한꺼번에 삭제하면 데이터베이스 성능이 크게 저하될 수 있습니다. 이를 피하기 위해 저희는 기본 PostgreSQL 데이터베이스에서 파티션 테이블을 사용해 만료된 데이터를 효율적으로 제거하고 있습니다.PostgreSQL 10 이전 버전에는 파티션 테이블에 대한 네이티브 지원이 없었기 때문에, 저희는 pg_partman 확장을 사용해 파티셔닝을 구현했습니다. 이 확장은 PostgreSQL의 테이블 상속을 활용해 파티션 대상 테이블의 자식 테이블을 생성하고, 트리거를 통해 부모 테이블이 아닌 자식 테이블
예전에는 이 코드의 Big-O 표기법이 뭐예요?라는 질문만 들어도 소름이 돋았습니다. 학교에서 배운 기억은 나지만, 수학(제가 가장 약했던 과목)과 관련된 내용이라 아예 머릿속에서 지워버렸거든요. 하지만 커리어를 쌓아가면서 어느새 저는 이런 상황에 자주 직면하게 되었습니다: 성능 차트를 분석할 때 느린 쿼리의 원인을 찾을 때 트래픽이 늘어나면 이 코드가 버틸 수 있을까요?라는 질문을 받을 때 드디어 Big-O를 다시 배우기로 마음먹었을 때, 그 개념이 생각보다 단순하다는 사실에 놀랐습니다. 이 글에서 제가 배운 내용을 공유
객체지향 프로그래밍(OOP)에서는 한 객체가 제 기능을 하기 위해 다른 객체에 의존하는 경우가 매우 흔합니다. 예를 들어, 재무 보고서를 생성하는 간단한 클래스를 만든다고 가정해 봅시다. class FinanceReport def net_income FinanceApi.gross_income - FinanceApi.total_costs end end 이 코드에서 FinanceReport는 외부 결제 시스템으로부터 정보를 가져오는 FinanceApi에 의존하고 있다고 말할 수 있습니다. 그런데 나중에 다른 API를
코드를 디버깅할 때 puts 문을 여기저기 넣어보고 언젠가 원하는 값이 출력되겠지 하며 기다려 본 적이 있으신가요? 코드 중간에 puts 잘 작동한다!라고 넣고 터미널에서 실행했는데 아무것도 출력되지 않아 당황한 경험이 있을 겁니다.루비 개발자들이 쓰는 강력한 디버깅 도구에 대해 들어는 봤지만 막상 써보기엔 겁이 나서, 그냥 코드를 텍스트 에디터에 마구 던져 넣고 무엇이라도 걸리기를 바라는 스파게티 방식의 디버깅에 의존하고 있다면 주목하세요. 문제는 이런 방식으로는 해결책을 보장받을 수 없다는 점입니다.디버깅은 개발자 인생 내내 계
Rails 앱을 평생 개발하면서도 비트 연산자를 한 번도 사용할 일이 없을 수 있습니다. 프로그래밍을 막 시작한 초보자라면 비트 연산(bitwise)이라는 단어 자체가 낯설게 느껴질 수도 있죠. 하지만 효율성이 중요하고 리소스가 제한적인 시스템에 관심을 갖는 순간, 비트 연산은 필수적인 지식이 됩니다. 네트워크 프로토콜, 암호화, 유닉스 파일 권한, 임베디드 시스템 등에서 비트 연산이 광범위하게 활용되기 때문입니다. 뿐만 아니라 컴퓨터가 두 숫자를 더하는 과정 같은 저수준 동작을 진정으로 이해하려면 비트 연산에 대한 이해가 반드
아직 아이는 없지만, 언젠가 자녀를 갖게 된다면 꼭 두 가지를 가르치고 싶습니다. 개인 금융 관리 머신러닝 기술적 특이점(singularity)이 곧 도래할 것이라고 믿든 믿지 않든, 오늘날 세상이 데이터 위에서 돌아간다는 사실은 부정할 수 없습니다. 데이터가 어떻게 지식으로 변환되는지 이해하는 것은 이 시대에 성장하는 모든 사람에게 필수적이며, 특히 개발자에게는 그 중요성이 더욱 큽니다. 이 글은 풀스택 루비(Ruby) 개발자에게 머신러닝(ML)을 쉽게 다가갈 수 있도록 돕기 위한 시리즈의 첫 번째 글입니다. 여러분이 활용할
루비에서 커맨드 라인 인자가 ARGV라는 전역 배열에 담긴다는 것은 이미 많이 알려진 사실입니다. 그런데 왜 하필 ARGV라는 이름일까요? 이 이름에는 흥미로운 역사가 숨어 있으며, 루비의 뿌리가 C 언어에 깊이 닿아 있다는 사실을 잘 보여줍니다. Argument Vector(인자 벡터) ARGV는 argument vector(인자 벡터)의 약자입니다. 여기서 벡터(vector)는 다소 옛스러운 표현으로, 1차원 배열을 의미합니다. C 언어에서 모든 프로그램은 main() 함수를 가지며, 일반적으로 다음과 같은 형태를 띱니다.
요즘 거의 모든 웹 개발은 프레임워크를 기반으로 이루어집니다. Rails, Sinatra, Lotus 중 무엇을 사용하든, 쿠키나 기타 헤더가 nginx나 Apache에서 애플리케이션 서버를 거쳐 여러분의 앱까지 어떻게 전달되는지 신경 쓸 필요가 없습니다. 그냥 알아서 전달되니까요.하지만 이 여정을 조금 더 깊이 들여다볼 가치가 충분합니다. 헤더의 이야기 속에는 웹의 역사에 관한 흥미로운 정보가 많이 숨어 있기 때문입니다.HTTP 헤더란 무엇일까?웹 브라우저가 요청(request)을 보낼 때마다 HTTP 헤더라고 불리는 데이터들을
간단한 유틸리티 스크립트를 하나 만들어 보는 것도 재미있지만, 때로는 진짜 명령줄 애플리케이션(Command-line Application)이 필요합니다. 인자를 받아들이고, 유닉스의 입출력·에러 보고 관례를 자연스럽게 따르는 앱 말입니다. 다행히 Ruby는 이런 명령줄 앱을 비교적 쉽게 만들 수 있는 모든 빌딩 블록을 제공합니다. 이 글에서는 흔한 gem Y로 X 하는 법 스타일을 넘어, 훌륭한 명령줄 앱을 구성하는 요소들을 폭넓게 살펴보겠습니다. 입력: 환경 변수(Environment Variables) 환경 변수는 한동안 유지
웹소켓(Websocket)은 요즘 많은 주목을 받고 있습니다. 미래의 기술이라고 불리기도 하고, Rails 5의 ActionCable 덕분에 그 어느 때보다 쉽게 사용할 수 있다는 이야기도 들려옵니다. 하지만 웹소켓은 정확히 무엇이며, 어떻게 동작하는 걸까요? 이 글에서는 Ruby를 사용해 아주 간단한 웹소켓 서버를 처음부터 직접 만들어 보면서 이 질문에 답해 보겠습니다. 작업을 마치면 브라우저와 서버 사이의 양방향 통신(bi-directional communication)을 성공적으로 구현하게 될 것입니다. 이 글의 코드는 학습용
Honeybadger에서는 모든 서버의 APT 패키지 업데이트를 놓치지 않고 관리하기 위해 apticron을 사용해 왔습니다. 처음에는 apticron 알림 메일을 제 받은편지함으로 받도록 설정했지만, 어느 순간부터는 이 메일들을 팀의 Slack 알림 채널로 받아보는 편이 낫겠다고 생각하게 되었습니다. Slack에는 이메일을 수신해 채널에 게시해 주는 유용한 이메일 앱이 있어 한번 사용해 보았습니다. 실제로 잘 작동했지만, 이메일이 파일 형태로 표시되는 점과 메일 헤더 등 불필요한 잡음이 많다는 점이 마음에 들지 않아, 좀 더 만족
Honeybadger 팀이 또 하나의 이정표를 지났습니다. 드디어 영업 페이지가 메인 Rails 애플리케이션에서 분리된 것입니다. 몇 년 전부터 위시리스트에 올려두었던 작업이었지만, 우선순위가 밀려 쉽게 손대지 못하고 있었죠. 이 마이그레이션 작업 중에 특정 리다이렉트 링크를 만들기 위해 URI.join을 사용하게 되었습니다. 그런데 곧바로 문제에 부딪혔습니다. URI.join이 제가 기대한 방식으로 동작하지 않았던 것입니다. 저는 이 메서드가 여러 경로 조각을 받아 자연스럽게 이어 붙여 하나의 URL을 만들어 줄 것이라 생각했습니
고백하자면, Honeybadger에서 일한 4년 동안 제 개발 환경은 크게 변하지 않았습니다. 하지만 그동안 Honeybadger는 상당히 정교해졌고, 정상 동작을 위해 약 10개의 서비스에 의존하게 되었습니다. 그래서 우리는 로컬 개발 환경에 Docker를 도입하기 시작했습니다. 모든 개발자가 Postgres, Cassandra, Memcached 등을 일일이 설치하는 대신, docker-compose로 미리 만들어진 환경을 손쉽게 띄울 수 있습니다. 정말 훌륭한 방식입니다. 그러다 자연스럽게 이런 궁금증이 생겼습니다. 과연
애플리케이션을 EC2에 배포할 때는 오토스케일링 그룹(Autoscaling Group)을 사용하는 것이 좋습니다. 오토스케일링 그룹을 활용하면 수요에 따라 인스턴스를 자동으로 늘리거나 줄일 수 있고, 장애가 발생한 인스턴스를 복구하는 것도 사람의 개입 없이 처리할 수 있습니다. 다만 이 방식이 제대로 작동하려면, 새로 부팅된 모든 인스턴스가 부팅이 끝나는 즉시 실제 트래픽을 처리할 수 있는 상태여야 합니다. 새 서버에 접속해 몇 가지 설정을 손보거나 Capistrano로 초기 배포를 진행한 뒤에야 서비스를 시작하는 방식에 익숙하다면
저는 컴퓨터 공학 학위가 없습니다. 루비(Rubyist) 개발자 중에는 저처럼 학위가 없는 사람이 많죠. 그래서 한동안 Big-O 표기법을 배우는 것을 피해 다녔습니다. 너무 고등 수학 같아 보였거든요. O(N^2)이라니, 말이 안 되잖아요. 대신 저는 이런 경험 법칙들을 익혔습니다: Hash에서 특정 항목을 찾는 것이 Array에서 찾는 것보다 빠르다 중첩 루프는 피하라 뷰(View)에서 목록을 생성할 때 의도치 않은 DB 쿼리가 발생하지 않도록 주의하라 이런 규칙들도 좋지만, 왜 그렇게 작동하는지 이해하지 못하면 실수를
왜 루비 컨퍼런스에서는 더 이상 루비 자체에 대한 이야기를 하지 않을까요? 최근 로키 마운틴 루비 2016(Rocky Mountain Ruby 2016) 후원을 통해 우리는 커뮤니티의 다양성이 점점 확대되고 있음을 확인했습니다. 이번 컨퍼런스에 파견된 인물은 개발자가 아니었기에, 발표 내용의 기술적 깊이가 걱정되기도 했습니다. 하지만 발표를 직접 지켜본 결과, 가장 베테랑인 루비스트들조차 직장에서 성공하기 위해서는 기술 외적인 역량을 적극적으로 강조하고 있다는 사실을 알게 되었습니다. 만약 이러한 변화를 안타깝게 여기는 개발자라
얼마 전 저는 Ruby 기본 문법은 알지만 예외(exception)가 정확히 무엇인지, 왜 유용한지 잘 모르는 초보자를 위한 Ruby 예외 입문 자료를 찾아보았습니다. 마땅한 자료를 찾기 어려워서 직접 작성해 보기로 했습니다. 이 글이 도움이 되기를 바랍니다. 혹시 이해하기 어려운 부분이 있다면 @StarrHorne으로 트윗을 보내주세요. :) 예외(Exception)란 무엇일까요? 예외는 Ruby가 예상치 못한 상황에 대처하는 방식입니다. 코드를 작성하다 오타를 내서 프로그램이 SyntaxError나 NoMethodError
Rails의 ActiveRecord를 처음 본 순간이 아직도 기억납니다. 그게 바로 2005년, PHP 앱을 만들면서 SQL 쿼리를 손으로 직접 작성하던 시절이었죠. 그런데 ActiveRecord를 접하고 나서 데이터베이스를 다루는 일은 지루한 노동에서 어쩌면 재미있기까지 한 즐거운 작업으로 완전히 바뀌어 버렸습니다. ...그러다 곧 성능 문제를 눈치채기 시작했습니다. ActiveRecord 자체가 느린 것은 아니었습니다. 단지 저는 실제로 실행되는 쿼리에 더 이상 주의를 기울이지 않게 되었을 뿐입니다. 그리고 알고 보니, Rail
Ruby에서 예외 처리를 다뤄본 개발자라면 rescue에 특정 예외 클래스를 지정해 원하는 예외만 잡을 수 있다는 것을 알고 있을 겁니다. begin raise ArgumentError rescue ArgumentError # `ArgumentError`를 잡습니다 end 또한 부모 클래스를 rescue하면 그 자식 클래스들까지 모두 함께 잡히는 것도 익숙할 것입니다. begin raise ArgumentError rescue StandardError # `ArgumentError`는 `StandardError`를
젊은 프로젝트를 진행하다 보면 나중에 확장을 쉽게 만들거나 어렵게 만드는 결정을 끊임없이 내리게 됩니다. 때로는 기술 부채(technical debt)를 일부러 안고 가는 것이 좋습니다. 그래야 더 빨리 출시할 수 있으니까요. 하지만 다른 경우에는 대안이 있다는 사실조차 몰랐기 때문에 어쩔 수 없이 기술 부채를 떠안게 되기도 합니다. Honeybadger에서도 우리 스스로 삶을 불필요하게 힘들게 만든 일들이 있었습니다. 몇 가지 핵심 포인트만 미리 알았더라면 확장 과정이 훨씬 덜 고통스러웠을 것입니다. UUID 사용하기 기본 키(p