문자열의 인코딩은 문제가 생겼을 때에야 비로소 신경 쓰게 됩니다. 예외 트래커를 열었는데 아래와 같은 에러가 눈앞에 나타난 경험, 한 번쯤 있으시죠? Encoding::InvalidByteSequenceError: \xFE on UTF-8 아니면 분명히 theyre였던 문자열이 어느 순간 they’re처럼 깨져 보이기도 합니다. 그렇다면 인코딩이 잘못됐을 때, 대체 무엇이 어떻게 깨진 걸까요? 그리고 어떻게 고칠 수 있을까요? 인코딩이란 무엇인가? 인코딩이 문자열에 어떤 역할을 하는지 상상할 수만 있다면, 이런 종류의
지난 글에서는 대부분의 인코딩 문제를 해결할 수 있는 간단한 과정을 소개했습니다. 하지만 그중 하나, 훨씬 더 다루기 까다로운 인코딩 문제가 있습니다. 여러분도 분명 본 적이 있을 겁니다. 컬리 쿼트(구부러진 따옴표)가 ’로 바뀌거나, 엠대시(—)가 —로 변하는 현상이죠. 이걸 처음 보면 내가 미쳤나? 싶을 정도입니다. 분명 잘 동작해야 하는데 말이죠! 물론 깨진 문자와 올바른 문자를 일일이 짝지어 거대한 치환 테이블을 만드는 방법도 있습니다: [{broken: –, fixed: —} {broken: —,
CSV 파일에서 앱으로 대량의 데이터를 가져와야 한 적이 있나요? 아니면 고객 리뷰에 섞인 깨진 인코딩 문자를 수정해야 하거나, Redis에 데이터를 저장하던 방식을 바꾸면서 기존 포맷의 모든 데이터를 새 포맷으로 옮겨야 했던 경험이 있을 수도 있습니다. Avvo에서는 이런 작업들을 애드혹(ad-hoc) 태스크라고 불렀습니다. 말 그대로 딱 한 번만 실행하면 되는 작업들이죠. 그렇다면 Rails에서 이런 일회성 작업을 처리하는 가장 좋은 방법은 무엇일까요? 데이터베이스 마이그레이션 작성 데이터베이스의 구조를 변경해야 한다면 마
여러분의 코드 중 테스트되지 않는 부분은 무엇인가요? 아마도 여러분이 통제할 수 없는 복잡한 상황을 다루는 코드일 겁니다. 스레드, 명령어 실행, git, 네트워킹, 혹은 UI 같은 것들 말이죠. 앱은 복잡할 때 가장 흥미롭습니다. 동시에 가장 위험하기도 하죠. 그렇기 때문에 테스트하기 어려운 코드야말로 꼼꼼하게 테스트가 필요한 코드입니다. 하지만 현실에서는 그렇게 되지 않는 경우가 많습니다. 대신 그런 코드를 건드릴 때마다 조심스럽게 살짝만 손을 댑니다. 수동 테스트를 몇 번 해보고, 풀 리퀘스트를 보낼 때는 테스트가 없다는
지난주 RailsConf 2017에서 드디어 Rails 5.1이 출시되었습니다. 발표 소식을 쫓아오셨다면 이미 큰 변화들을 접하셨을 겁니다. 최신 JavaScript와의 향상된 통합, 암호화된 시크릿(encrypted secrets) 지원, 그리고 시스템 테스트 도입이 대표적입니다. 개인적으로 가장 반가웠던 점은 드디어 form_for와 form_tag라는 애매한 조합을 정리하고 하나로 통합한 form_with가 등장했다는 것입니다. 빨리 사용해 보고 싶네요. 하지만 제가 Rails를 사랑하는 이유는 화려한 신기능 때문만은 아닙
지난 글에서 Rails 5.1의 훌륭한 새 기능인 delegate_missing_to를 소개했습니다. delegate_missing_to를 사용하면 한 객체에서 찾을 수 없는 메서드가 다른 객체에서 대신 호출됩니다: class Player delegate_missing_to :@user def initialize(user) @user = user end def points Game.points_for_user(@user.id) end end Player.new(user).name # user.
혹시 도무지 이해가 되지 않는 Rails 주제를 만난 적이 있나요? 분명 알고 있다고 생각해서 코드를 작성했는데, 정작 완전히 다른 결과가 나온 경험이 말입니다. 아니면 사실은 잘 모르면서도 어느 정도 아는 척하며 넘어왔는데, 막상 예외 케이스를 처리하다 보면 그 시간에 전문가가 됐을 만큼 많은 시간을 허비한 적은요? 꼭 그럴 필요는 없다면 어떨까요? 그냥 제대로 아는 것. 눈앞의 문제에 대한 탄탄한 멘탈 모델을 갖추는 것. 그래야 올바른 결정을 내리고 올바른 코드를 작성할 수 있습니다. 저도 웹 개발을 처음 배울 때 세션(sess
버그 하나를 고쳤더니 열두 개의 새로운 버그가 생긴 경험이 있으신가요? 아니면 코드가 너무 이상한 방식으로 깨져서, 정말 내가 이 코드를 이해하고 있는 게 맞나 의심되는 순간이 있었을 겁니다. 그럴 때면 이제 슬슬 제대로 깊이 파고들 때가 됐구나 하는 생각이 듭니다.하지만 깊이 공부해야 한다는 것을 아는 것은 첫 번째 단계일 뿐입니다. 그렇다면 실제로 하나의 주제를 근본부터 끝까지 익히려면 어떻게 해야 할까요? 지식이 몸에 자연스럽게 배어날 만큼 학습하려면 무엇부터 시작해야 할까요?어디서부터 시작해야 할까?학습을 시작할 수 있는 방
대규모 프로젝트나 새로운 직장에 깊이 몰입하다가 어느 순간 고개를 들어 주변을 살펴보면, 길을 잃은 듯한 느낌이 들 때가 있습니다. 마치 기술 세계가 나를 지나쳐 간 것처럼요. 새로운 것을 배우지 못한 시간이 결국 빚으로 돌아온 걸까요? 그리고 그 격차는 어떻게 메울 수 있을까요? 집에서 공부할까, 아니면 회사에서 배울까? 학습 시간을 따로 내지 않았다면, 그 시간은 어디선가 만들어야 합니다. 하지만 그 시간은 대체 어디서 올까요? 개인 시간에 공부해야 할까요, 아니면 업무 중에 배워야 할까요? 사실 이건 함정 질문입니다.
Capybara와 Selenium으로 스크린샷 자동화하기지난주 AppSignal 업데이트에는 모든 화면에 적용된 새로운 인터페이스 디자인이 포함되어 있었습니다. 이는 홈페이지의 모든 스크린샷을 앱의 현재 상태에 맞게 다시 촬영해야 한다는 의미이기도 했습니다. 이 작업에 필요한 방대한 수작업을 줄이기 위해 우리는 프로세스 자동화를 결심했습니다.다행히 곧 Selenium으로 스크린샷을 촬영할 수 있다는 사실이 떠올랐습니다. 우리는 이미 기능 테스트(feature test)에서 Capybara를 통해 Selenium을 폭넓게 사용하고 있
커스텀 메트릭으로 더 깊은 인사이트 얻기AppSignal 젬(gem)에서는 이미 커스텀 인스트루멘테이션(계측) 기능을 통해 애플리케이션 성능에 대한 상세 정보를 확인할 수 있습니다. 하지만 때로는 그 외의 다른 지표도 함께 추적하고 싶어질 때가 있습니다.1.0 버전 릴리스부터는 커스텀 메트릭을 AppSignal로 직접 전송할 수 있습니다. 이를 통해 신규 계정 수부터 데이터베이스 디스크 사용량까지, 애플리케이션 내 어떤 값이든 추적할 수 있습니다. 커스텀 메트릭은 기존 코드 인스트루멘테이션을 대체하는 것이 아니라, 코드 속 특정 데
동시성 마스터하기여러 사용자가 동시에 앱을 사용하게 되고, 우리는 최대한 빠른 응답 속도를 제공하고 싶습니다. 그러려면 동시성(concurrency)을 처리할 방법이 필요합니다. 걱정하지 마세요! 대부분의 웹 서버는 기본적으로 이를 지원합니다. 하지만 규모를 확장해야 하는 시점이 오면, 동시성을 가장 효율적인 방식으로 활용하는 것이 중요해집니다.다양한 종류의 동시성 모델동시성을 처리하는 방법은 크게 세 가지입니다: 멀티 프로세스(multi-process), 멀티 스레딩(multi-threading), 그리고 이벤트 드리븐(event
개발 환경 설정 변경Mongoid 5로 업그레이드한 후 Rails 앱을 실행하면 가장 먼저 데이터베이스 설정이 올바르지 않다는 오류를 만나게 됩니다.해결 방법은 간단합니다. 설정 파일에서 sessions를 clients로 변경하기만 하면 됩니다:development: clients: default: database: appsignal_development hosts: - localhost:27017드라이버 변경 사항저희 코드베이스에서는 Mongoid 대신 moped/mongo-ruby-
때로는 표준 계측(instrumentation)만으로는 성능 문제의 근본 원인을 추적하기에 충분하지 않습니다. 이럴 때 커스텀 지표(Custom Metrics)가 빠져 있는 퍼즐 조각을 찾는 데 결정적인 역할을 합니다.AppSignal의 성능 그래프 덕분에 코드베이스의 어느 부분이 성능 문제를 일으키는지는 정확히 파악할 수 있습니다. 아래 스크린샷에서 MongoDB로 인해 심각한 성능 저하가 발생했던 것을 확인할 수 있습니다.하지만 이 그래프만으로는 여러 ReplicaSet에서 운영 중인 수많은 데이터베이스 중 어느 것이 이러한 성
코드를 실행할 때마다 우리는 메모리를 사용합니다. 하지만 Ruby처럼 편리한 언어로 프로그래밍하다 보면 마치 사용할 수 있는 메모리가 무한한 것처럼 느껴지곤 합니다. 코드를 실행하는 시스템에 실제로는 한정된 양의 메모리만 있다는 사실조차 의식하지 않고 계속 코딩할 수 있으니까요. 이번 Ruby Magic 에피소드에서는 이것이 어떻게 가능한지 그 비밀을 파헤쳐 보겠습니다.간단한 역사 이야기Ruby와 같은 스크립트 언어가 등장하기 전, 개발자들은 C와 같은 저수준(low-level) 프로그래밍 언어로만 코드를 작성해야 했습니다. 이런
지난 Ruby Magic 시리즈에서는 가비지 컬렉션(GC)이 왜 필요한지, 그리고 전반적으로 어떻게 동작하는지 살펴보았습니다. 이번 글에서는 한 단계 더 나아가, 루비(Ruby) 내부에서 GC가 실제로 어떻게 구현되어 있는지 자세히 알아보겠습니다. 다양한 루비 구현체 루비에는 여러 가지 구현체가 존재합니다. 대표적으로 MRI(Matzs Ruby Interpreter), Rubinius, JRuby 세 가지가 널리 사용됩니다. 각 구현체마다 사용하는 GC 방식이 다른데, 이 글에서는 가장 많은 루비 개발자가 사용하는 MRI를 기준으로
클라이언트는 어떻게 이런 상태에 이르게 되었을까?세부적인 내용으로 들어가기 전에, 애플리케이션이 어떻게 이런 상태에 도달하게 되는지 이해해 보자. 우리는 간단한 users 테이블에서 출발한다. 몇 주 후에는 마지막 로그인 시간을 알아야 해서 users.last_sign_in_at 컬럼을 추가한다. 그다음엔 사용자의 이름이 필요해진다. first_name과 last_name을 추가한다. 트위터 핸들은? 또 다른 컬럼이다. GitHub 프로필은? 전화번호는? 몇 달이 지나면 테이블은 감당하기 어려울 정도로 비대해진다.이 구조의 문제점은
AppSignal은 Ruby 애플리케이션을 위한 에러 트래킹 서비스를 제공합니다. 이를 위해 애플리케이션이 발생시키는 모든 예외를 수집하고, 개발자에게 실시간으로 알려줍니다. 예외 처리는 제대로 하기가 생각보다 어렵습니다. 이 글에서는 Ruby에서 예외 처리가 어떻게 동작하는지, 잘못된 처리가 어떤 문제를 일으킬 수 있는지, 그리고 예외를 어떻게 올바르게 rescue해야 하는지 설명합니다. 예외 rescue하기 Ruby에서 예외를 rescue하면 무언가 잘못되었을 때 애플리케이션이 즉시 크래시되는 것을 막을 수 있습니다. begin
웹 서버와 HTTP는 어려워 보일 수 있습니다. 브라우저는 어떻게 요청을 구성하고, 응답은 어떻게 사용자에게 전달될까요? 이번 Ruby Magic 에피소드에서는 단 30줄의 코드로 Ruby HTTP 서버를 만드는 방법을 알아봅니다. 완성된 서버는 HTTP GET 요청을 처리하며, Rack 앱을 서비스하는 데 활용할 수 있습니다.HTTP와 TCP는 어떻게 함께 작동할까TCP는 서버와 클라이언트가 데이터를 교환하는 방식을 정의하는 전송 프로토콜입니다.HTTP는 웹 서버가 HTTP 클라이언트나 웹 브라우저와 데이터를 교환하는 방식을 구체
이번 글에서는 Ruby에서 문자를 이스케이프(escape)하는 방법에 대해 알아보겠습니다. 문자를 이스케이프하는 방법, 그 작동 원리, 그리고 일부 사용 사례에서는 아예 이스케이프를 피하는 방법까지 살펴봅니다. 백슬래시 \에 대해 모든 것을 안다고 생각하신다면, 끝까지 읽어보세요. 의외의 사실을 발견하실 수도 있습니다.그럼 바로 문자열에서의 문자 이스케이프부터 시작해 보겠습니다.따옴표 이스케이프하기Ruby에서 문자열을 다루다 보면, 문자열을 정의할 때 사용한 따옴표를 문자열 내부에 그대로 넣어야 하는 경우가 있습니다. 이럴 때는 백