Linux나 Mac을 사용한다면 터미널을 열 때마다 이미 쉘(shell) 애플리케이션을 사용하고 있는 것입니다. 쉘은 시스템에서 명령어를 실행할 수 있도록 도와주는 인터페이스입니다. 쉘은 환경 변수를 관리하며, 명령어 히스토리와 자동 완성 같은 유용한 기능도 제공합니다. 사물의 내부 동작 원리를 깊이 파악하고 싶어 하는 분이라면 이 글이 딱 맞을 것입니다! 쉘은 어떻게 동작할까? 직접 쉘 애플리케이션을 만들어 보기 위해, 먼저 쉘이 실제로 무엇인지 생각해 봅시다. 먼저 프롬프트가 나타납니다. 보통 현재 사용자와 현재 디렉터리 같은
Ruby 2.4에서는 Fixnum과 Bignum이 하나의 클래스(Integer)로 통합되었습니다. 그래서 지금이야말로 Ruby의 다양한 숫자 타입을 다시 한번 짚어볼 좋은 기회라고 생각합니다! 이번 포스트에서 바로 그 내용을 다뤄보겠습니다 🙂 Ruby 숫자 타입 개요 먼저 Ruby의 모든 숫자 관련 클래스들이 어떤 계층 구조를 이루고 있는지 살펴보겠습니다: Numeric Integer Fixnum Bignum Float Complex Rational BigDecimal (Standard Libra
루비를 이용해 웹 서버를 직접 구축해 본 경험이 있으신가요? 사실 우리에게는 이미 훌륭한 웹 서버들이 많이 있습니다: Puma Thin Unicorn 하지만 간단한 웹 서버가 어떻게 동작하는지 그 원리를 제대로 이해하고 싶다면, 직접 한번 만들어 보는 것만큼 좋은 학습 방법은 없습니다. 이 글에서는 그 과정을 단계별로 차근차근 살펴보겠습니다. 1단계: 새로운 연결 대기(Listening) 그럼 어디서부터 시작해야 할까요? 가장 먼저 해야 할 일은 TCP 80번 포트에서 새로운 연결을 수신(listen)하는 것입니다. 네트워크 프
Ruby 애플리케이션에서 지금 무슨 일이 일어나고 있는지 궁금하신 적 있으신가요? 화려한 GUI 도구는 없지만, 다행히 ObjectSpace 모듈이 있습니다! ObjectSpace를 사용하면 애플리케이션의 현재 상태에 대한 정보를 얻을 수 있습니다. 지금부터 그 작동 방식을 함께 살펴보겠습니다. 객체 개수 세기 ObjectSpace를 활용하면 프로그램에서 현재 살아있는(live) 객체들이 무엇인지 파악할 수 있습니다. 살아있는 객체란 무엇일까? 객체를 가리키는 참조(reference)가 하나라도 존재하는 한, 그 객체는 살아있습니다
Minitest란 무엇인가? Minitest는 Ruby 테스팅 라이브러리로, TDD(Test-Driven Development) 스타일로 코드에 대한 테스트를 작성할 수 있게 해주는 도구입니다. Rails의 기본 테스팅 프레임워크이며, Rails 창시자 DHH(David Heinemeier Hansson)가 가장 선호하는 도구이기도 합니다. 주요 대안인 RSpec에 비해 문법이 단순하고 코드량이 적다는 이유로 Minitest를 선호하는 개발자들도 많습니다. 아래 그림에서 그 차이를 확인할 수 있습니다: 다만 이 글은 어느 쪽을 선
왜 굳이 포트 스캐너를 직접 작성해야 할까요? 포트 스캐너를 작성하는 것은 TCP 프로토콜의 기본 원리를 배우는 훌륭한 방법입니다. TCP는 HTTP, SSH를 비롯한 대부분의 인터넷 프로토콜이 사용하는 전송 계층(transport layer)입니다. 또한 Ruby로 네트워크 프로그래밍이 어떻게 동작하는지 깊이 이해할 수 있는 좋은 연습 과제이기도 합니다. 그럼 포트가 무엇인지부터 차근차근 살펴보겠습니다! 포트란 무엇일까? 포트라고 하면 무엇을 떠올려야 할까요? 운영체제(OS) 수준에서 포트는 사실 특정 프로세스와 연결된 하나의 파
Ruby는 매년 크리스마스에 새 버전을 출시하는 전통이 있습니다. 이번 글에서는 Ruby 2.4에서 가장 흥미로운 변경 사항들을 소개해 드리겠습니다. 최신 소식을 놓치지 마세요! 🙂 1. 키워드 인수를 지원하는 Float#round 애플리케이션에서 부동소수점(float)을 다룬다면 반올림 시 floor나 ceil을 사용하고 계셨기를 바랍니다. Ruby 2.4에서 Float#round 메서드의 기본 동작이 변경되었기 때문입니다. 예시: # Ruby 2.3 (2.5).round 3 # Ruby 2.4 (2.5).round 2 새
Ruby에는 TracePoint 클래스를 통해 접근할 수 있는 내장 트레이싱(추적) 시스템이 있습니다. 이를 활용하면 메서드 호출, 새 스레드 생성, 예외 발생 등 다양한 이벤트를 추적할 수 있습니다. 이 기능은 언제 유용할까요? 특정 메서드의 실행 과정을 추적하고 싶을 때 특히 유용합니다. 어떤 메서드들이 호출되는지, 반환값은 무엇인지 한눈에 파악할 수 있기 때문입니다. 그럼 몇 가지 예제를 살펴보겠습니다! 메서드 호출 추적하기 대부분의 경우 TracePoint로 애플리케이션 코드를 추적하고 싶지, puts나 size 같은 내장
이 글에서는 Ruby의 pack과 unpack 메서드를 활용하는 방법을 배워보겠습니다. 그런데 왜 굳이 이 메서드들이 필요할까요? 텍스트를 다루는 일은 이진(binary) 데이터를 다루는 일보다 훨씬 쉽기 때문입니다. 텍스트라면 다음과 같은 도구들을 자유롭게 사용할 수 있습니다. 정규표현식(regular expressions) scan, match 같은 메서드 gsub 하지만 이진 데이터를 다루려면 약간의 추가 작업이 필요합니다. 바로 이 지점에서 Array#pack과 String#unpack 메서드가 빛을 발합니다. 먼저 간단
제가 가장 좋아하는 자료구조 중 하나는 바로 해시 테이블입니다. 단순하면서도 강력하기 때문인데요. 키-값(key-value) 쌍을 효율적으로 저장할 수 있는 방법이기 때문에 여러분도 이미 여러 번 사용해 보셨을 겁니다. 그런데 해시 테이블의 구현에는 공부해 볼 가치가 충분한 흥미로운 컴퓨터 과학 개념들이 숨어 있습니다. 바로 지금부터 그 내부 원리를 하나씩 파헤쳐 보겠습니다! 버킷(Bucket)과 해시 함수 해시 테이블의 기본 아이디어는 키로 색인된 데이터를 효율적으로, 즉 O(1) 시간에 검색할 수 있게 하는 것입니다. 간단히
동등성(equality)이란 두 대상이 같다는 것을 의미합니다. Ruby에서는 객체와 그 값을 비교하여 두 객체가 같은지 판단할 수 있습니다. 그렇다면 질문은 이것입니다. Ruby에서 두 객체는 어떻게 비교할까요? 답은 간단합니다. 1 == 1 # true 아마 이미 익숙하게 사용하고 계실 겁니다. 하지만 ==가 단순한 문법이 아니라 하나의 메서드라는 사실을 알고 계셨나요? 이것의 의미는 상당히 큽니다. 자신만의 클래스에서 이 메서드를 직접 구현하면 클래스를 훨씬 더 강력하게 만들 수 있습니다. 지금부터 그 방법을 자세히 알아
컴퓨터 과학(CS) 전공자가 아니라면 뭔가 놓치고 있다는 느낌이 들 수 있습니다... 또는 CS가 너무 추상적이라 실용성이 없다고 생각할 수도 있고... Ruby가 이미 어려운 작업을 모두 대신 처리해준다고 믿을 수도 있죠. 어느 쪽이든... 해시, 스택, 큐 같은 자료구조의 기본 개념을 이해하는 것은 분명 큰 도움이 됩니다. 이 글에서 다룰 내용: Ruby에서 스택을 활용하는 방법을 알아봅니다. 지금 바로 실전에 적용할 수 있는 실용적인 컴퓨터 과학 개념입니다! Ruby에서 스택 이해하기 Ruby에서 스택(stack)이란 무엇일
Ruby의 내부 동작 원리가 궁금하신가요? 그렇다면 아주 흥미로운 시간이 될 것입니다. 왜냐하면… 이번 글에서는 Ruby 객체가 메모리에 어떻게 배치되는지 함께 살펴보고, 내부 데이터 구조를 조작해서 재미있는 작업들을 수행하는 방법까지 알아보겠습니다. 안전벨트를 매고 Ruby 인터프리터의 깊은 곳으로 떠나는 여정을 시작해 볼까요? 배열(Array)의 메모리 레이아웃 배열을 생성하면 Ruby는 이를 뒷받침하기 위해 시스템 메모리와 약간의 메타데이터를 할당해야 합니다. 메타데이터에는 다음이 포함됩니다: 배열 크기(요소 개수) 배열 용
OOP(객체 지향 프로그래밍)의 진정한 힘을 제대로 활용하고 계신가요, 아니면 그저 지나치고 있으신가요? 객체의 타입에 따라 분기 처리를 하고 있다면 중요한 OOP 기능인 다형성(polymorphism)을 놓치고 있는 것입니다. 타입 분기는 보통 case 문 안에서 이루어지는데, 이는 객체 지향 설계에 적합하지 않습니다. 이 글에서는 case 문을 제거하여 더 나은 코드를 작성하는 방법을 알아보겠습니다. 타입 검사하기 다형성을 활용하지 않는 예제부터 살펴보겠습니다. 가위바위보 게임을 구현한다고 가정해 봅시다. 하나의 Game 클래스
IO 객체(파일, 소켓 등)처럼 동작하지만, 문자열처럼 자유롭게 제어할 수 있는 객체를 찾고 계신가요? 그렇다면 StringIO가 바로 그 답입니다. 지금부터 실용적인 예제와 함께 반드시 알아두어야 할 주의사항까지 살펴보겠습니다. 기본 사용 예제 StringIO 객체는 다음과 같이 생성합니다. io = StringIO.new(abc) 생성된 객체에는 gets, read, each_line 같은 메서드를 사용해 데이터를 읽을 수 있습니다. 가장 유용하게 쓰이는 메서드들을 표로 정리했습니다. 메서드 설명 gets 입력을
이 글은 고전적인 컴퓨터 과학 개념을 Ruby로 실제 문제 해결에 적용하는 방법을 다루는 실전 컴퓨터 과학(Practical Computer Science) 시리즈의 연속 편입니다. 오늘은 그래프 이론(Graph Theory)에 대해 이야기해 보겠습니다. 이진 트리(binary tree)라는 자료구조를 들어보셨을 겁니다. 이진 트리는 다음과 같은 모습을 하고 있죠. 사실 이진 트리는 그래프의 특수한 형태 중 하나입니다. 즉, 그래프가 얼마나 폭넓게 활용되는지 짐작할 수 있는 부분이죠. 먼저 그래프 이론의 기본 개념을 살펴본 뒤,
Ruby에서 관련된 데이터를 묶어서 다루고 싶을 때, 꼭 클래스를 새로 정의해야 할까요? 이럴 때 유용하게 쓸 수 있는 것이 바로 Struct와 OpenStruct입니다. 이 글에서는 두 클래스의 사용법, 장단점, 그리고 실무에서 알아야 할 주의사항까지 자세히 살펴보겠습니다. Ruby의 Struct란 무엇인가? Struct는 Ruby에 내장된 클래스로, 값 객체(value object)를 생성하는 새로운 클래스를 만들 때 사용합니다. 값 객체란 서로 연관된 속성들을 하나로 묶어 저장하는 객체를 말합니다. 예를 들어, 좌표 x와 y
Rails나 Ruby에는 마법이 너무 많다는 말을 들어본 적이 있을 것입니다. 혹시 스스로 그렇게 말해본 적도 있을지 모르죠. 그런 생각은 대체 어디서 비롯된 걸까요? 정확히 Rails의 마법이란 무엇일까요? 그리고 그 마법을 걷어내려면 어떻게 해야 할까요? 저의 생각은 이렇습니다: 어떤 것이 마법처럼 느껴진다면, 그것은 당신이 모르는 무언가가 있기 때문입니다. 즉, 빠진 정보가 있는 것이죠. 이것은 마술과 같습니다. 속임수의 원리를 알면 더 이상 마법은 존재하지 않습니다. 소프트웨어 개발에서 속임수를 아는 것은 곧 사물이 실
메타프로그래밍(Metaprogramming)은 매우 멋져 들리는 단어지만, 과연 실제로 좋은 선택일까요? 물론 상황에 따라 유용할 수 있습니다. 하지만 많은 개발자들이 메타프로그래밍을 사용할 때 따르는 숨겨진 비용을 인식하지 못한 채 사용합니다. 먼저 서로 같은 이해를 바탕으로 논의하기 위해, 메타프로그래밍이 정확히 무엇인지부터 짚어보겠습니다. 메타프로그래밍이란 무엇인가? 여기서는 다음 중 하나에 해당하는 기법을 모두 메타프로그래밍으로 정의합니다. 코드 구조 자체를 변경하는 방법 — 예: define_method 문자열을 실제 루
Ruby에서 상수란 무엇일까요? 상수는 항상 대문자로 시작하는 변수의 한 종류입니다. 메타프로그래밍을 사용하지 않는 한, 메서드 외부에서만 정의할 수 있습니다. 상수는 원래 변경되지 않아야 하는 값을 담기 위해 사용되지만, 흥미롭게도 Ruby는 상수 변경 자체를 막지는 않습니다. 상수는 다음과 같이 생겼습니다: FRUIT = orange 그렇다면 지금부터, 상수는 매우 중요한 주제이므로 이 글에서 하나씩 자세히 살펴보겠습니다! 상수 정의 방법 상수를 선언하는 데에는 특별한 기호나 복잡한 문법이 필요하지 않습니다. 단지 첫 글자를