이미지 파일 및 설정 파일 삭제, 새로운 CLI 및 문서 추가
This commit is contained in:
66
README.md
66
README.md
@@ -0,0 +1,66 @@
|
|||||||
|
다음은 실무 중심의 Ruby 책을 위한 목차 초안이다.
|
||||||
|
|
||||||
|
### 1. **Ruby 개요**
|
||||||
|
- Ruby의 특징과 철학
|
||||||
|
- Ruby의 실무 활용 분야
|
||||||
|
- 개발 환경 설정 (Windows, macOS, Linux)
|
||||||
|
- IRB와 Pry를 활용한 인터랙티브 개발
|
||||||
|
|
||||||
|
### 2. **기본 문법과 데이터 타입**
|
||||||
|
- 변수와 상수
|
||||||
|
- 숫자, 문자열, 심볼
|
||||||
|
- 배열과 해시
|
||||||
|
- 조건문과 반복문
|
||||||
|
|
||||||
|
### 3. **메서드와 블록**
|
||||||
|
- 메서드 정의와 호출
|
||||||
|
- 기본값과 가변 인자
|
||||||
|
- 블록, Proc, Lambda 차이점과 활용
|
||||||
|
|
||||||
|
### 4. **객체지향 프로그래밍(OOP) in Ruby**
|
||||||
|
- 클래스와 인스턴스
|
||||||
|
- 상속과 믹스인
|
||||||
|
- 모듈을 활용한 코드 재사용
|
||||||
|
- 메타프로그래밍 기초
|
||||||
|
|
||||||
|
### 5. **파일 처리와 입출력**
|
||||||
|
- 파일 읽기/쓰기
|
||||||
|
- CSV, JSON, YAML 다루기
|
||||||
|
- 네트워크 요청 및 API 호출
|
||||||
|
|
||||||
|
### 6. **예외 처리와 디버깅**
|
||||||
|
- 예외의 개념과 처리 방법
|
||||||
|
- 주요 예외 클래스와 커스텀 예외
|
||||||
|
- 디버깅 기법 (pry, byebug 활용)
|
||||||
|
|
||||||
|
### 7. **Ruby와 데이터베이스**
|
||||||
|
- SQLite, PostgreSQL, MySQL 연동
|
||||||
|
- ActiveRecord와 ORM 개념
|
||||||
|
- 데이터 마이그레이션과 모델링
|
||||||
|
|
||||||
|
### 8. **테스트와 품질 관리**
|
||||||
|
- RSpec을 활용한 테스트 작성
|
||||||
|
- Minitest와 비교
|
||||||
|
- 테스트 주도 개발(TDD) 실습
|
||||||
|
|
||||||
|
### 9. **Ruby를 활용한 웹 개발**
|
||||||
|
- Sinatra를 활용한 간단한 웹 애플리케이션
|
||||||
|
- Rails 기본 개념과 실습
|
||||||
|
- REST API 설계 및 구현
|
||||||
|
|
||||||
|
### 10. **배포 및 운영**
|
||||||
|
- Bundler와 Gem 관리
|
||||||
|
- Docker를 활용한 Ruby 애플리케이션 배포
|
||||||
|
- CI/CD와 자동화
|
||||||
|
|
||||||
|
### 11. **고급 주제: 성능 최적화 및 메타프로그래밍**
|
||||||
|
- Ruby의 GC 이해하기
|
||||||
|
- 메모리 최적화 및 성능 튜닝
|
||||||
|
- 동적 메서드와 DSL 설계
|
||||||
|
|
||||||
|
### 12. **실전 프로젝트: 실무에서 Ruby 활용하기**
|
||||||
|
- CLI 툴 만들기
|
||||||
|
- 간단한 웹 크롤러 개발
|
||||||
|
- API 서버 구축
|
||||||
|
|
||||||
|
이 목차는 실무에 초점을 맞추고 있으며, 현업에서 Ruby를 활용하는 개발자들에게 도움이 되도록 구성했다. 추가하고 싶은 내용이 있으면 말해줘!
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE categories
|
|
||||||
SYSTEM "https://resources.jetbrains.com/writerside/1.0/categories.dtd">
|
|
||||||
<categories>
|
|
||||||
<category id="wrs" name="Writerside documentation" order="1"/>
|
|
||||||
</categories>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<buildprofiles xsi:noNamespaceSchemaLocation="https://resources.jetbrains.com/writerside/1.0/build-profiles.xsd"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
|
||||||
|
|
||||||
<variables></variables>
|
|
||||||
<build-profile instance="r">
|
|
||||||
<variables>
|
|
||||||
<noindex-content>true</noindex-content>
|
|
||||||
</variables>
|
|
||||||
</build-profile>
|
|
||||||
|
|
||||||
</buildprofiles>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 125 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 67 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 341 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 119 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 306 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 274 KiB |
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE instance-profile
|
|
||||||
SYSTEM "https://resources.jetbrains.com/writerside/1.0/product-profile.dtd">
|
|
||||||
|
|
||||||
<instance-profile id="r"
|
|
||||||
name="Ruby"
|
|
||||||
start-page="starter-topic.md">
|
|
||||||
|
|
||||||
<toc-element topic="starter-topic.md"/>
|
|
||||||
<toc-element topic="CheetSheet.md"/>
|
|
||||||
<toc-element topic="rails-CheetSheet.md"/>
|
|
||||||
</instance-profile>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Ruby
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo apt install ruby --classic
|
|
||||||
sudo apt install ruby-full
|
|
||||||
sudo apt install build-essentials
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
ruby -v
|
|
||||||
```
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE vars SYSTEM "https://resources.jetbrains.com/writerside/1.0/vars.dtd">
|
|
||||||
<vars>
|
|
||||||
<var name="product" value="Writerside"/>
|
|
||||||
</vars>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE ihp SYSTEM "https://resources.jetbrains.com/writerside/1.0/ihp.dtd">
|
|
||||||
|
|
||||||
<ihp version="2.0">
|
|
||||||
<topics dir="topics" web-path="topics"/>
|
|
||||||
<images dir="images" web-path="images"/>
|
|
||||||
<instance src="r.tree"/>
|
|
||||||
</ihp>
|
|
||||||
13
app.sh
Executable file
13
app.sh
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#! /usr/bin/env bash
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
gitup)
|
||||||
|
echo "Pushing to git"
|
||||||
|
git add -A
|
||||||
|
git commit -m $(date "+%Y-%m-%dT%H:%M:%S")
|
||||||
|
git push origin
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Launching editor"
|
||||||
|
code .
|
||||||
|
esac
|
||||||
105
docs/01_Ruby.md
Normal file
105
docs/01_Ruby.md
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
# **Ruby 프로그래밍 언어 소개 및 리눅스 개발 환경 설정 방법**
|
||||||
|
|
||||||
|
## **1. Ruby란 무엇인가?**
|
||||||
|
|
||||||
|
Ruby는 간결하고 우아한 문법을 가진 동적 프로그래밍 언어이다. 1995년 일본의 마츠모토 유키히로(일명 Matz)에 의해 개발되었으며, 객체지향 프로그래밍(OOP)을 기본으로 설계되었다. Ruby는 가독성이 뛰어나며, 생산성을 극대화할 수 있는 언어로 평가받는다.
|
||||||
|
|
||||||
|
### **Ruby의 주요 특징**
|
||||||
|
- **순수 객체지향 언어**: 모든 것이 객체이며, 메서드를 호출하는 방식으로 동작한다.
|
||||||
|
- **동적 타입 및 유연한 문법**: 변수 타입을 명시할 필요 없이 자유로운 코드 작성이 가능하다.
|
||||||
|
- **강력한 메타프로그래밍**: 코드 자체를 수정할 수 있는 기능을 제공하여 DSL(도메인 특화 언어) 구현이 용이하다.
|
||||||
|
- **풍부한 오픈소스 생태계**: RubyGems를 통해 다양한 라이브러리를 손쉽게 활용할 수 있다.
|
||||||
|
- **웹 개발 친화적**: Ruby on Rails 프레임워크를 통해 빠르고 효율적인 웹 애플리케이션 개발이 가능하다.
|
||||||
|
|
||||||
|
## **2. 리눅스에서 Ruby 개발 환경 설정하기**
|
||||||
|
|
||||||
|
리눅스에서 Ruby를 설치하고 개발 환경을 구축하는 방법을 단계별로 설명한다.
|
||||||
|
|
||||||
|
### **2.1. Ruby 설치 방법**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install ruby --classic
|
||||||
|
sudo apt install ruby-full
|
||||||
|
sudo apt install build-essentials
|
||||||
|
```
|
||||||
|
|
||||||
|
리눅스에서는 패키지 관리자를 사용해 Ruby를 설치할 수 있지만, 최신 버전을 유지하기 위해 **rbenv** 또는 **RVM(Ruby Version Manager)**을 사용하는 것이 권장된다.
|
||||||
|
|
||||||
|
#### **방법 1: rbenv를 사용한 설치 (추천)**
|
||||||
|
rbenv는 여러 버전의 Ruby를 쉽게 관리할 수 있는 도구다.
|
||||||
|
|
||||||
|
1. 필수 패키지 설치
|
||||||
|
```sh
|
||||||
|
sudo apt update && sudo apt install -y git curl build-essential libssl-dev libreadline-dev zlib1g-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
2. rbenv 및 ruby-build 플러그인 설치
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
|
||||||
|
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
|
||||||
|
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
|
||||||
|
source ~/.bashrc
|
||||||
|
|
||||||
|
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Ruby 최신 버전 설치
|
||||||
|
```sh
|
||||||
|
rbenv install 3.2.2 # 최신 버전 확인 후 설치
|
||||||
|
rbenv global 3.2.2 # 기본 버전 설정
|
||||||
|
```
|
||||||
|
|
||||||
|
4. 설치 확인
|
||||||
|
```sh
|
||||||
|
ruby -v
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **방법 2: RVM을 사용한 설치**
|
||||||
|
RVM은 Ruby 버전 관리를 위한 또 다른 도구다.
|
||||||
|
|
||||||
|
1. GPG 키 가져오기
|
||||||
|
```sh
|
||||||
|
gpg --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
|
||||||
|
```
|
||||||
|
|
||||||
|
2. RVM 설치 및 환경 반영
|
||||||
|
```sh
|
||||||
|
curl -sSL https://get.rvm.io | bash -s stable
|
||||||
|
source ~/.rvm/scripts/rvm
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Ruby 설치
|
||||||
|
```sh
|
||||||
|
rvm install 3.2.2
|
||||||
|
rvm use 3.2.2 --default
|
||||||
|
```
|
||||||
|
|
||||||
|
4. 설치 확인
|
||||||
|
```sh
|
||||||
|
ruby -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2.2. Bundler 및 기본 개발 도구 설치**
|
||||||
|
Ruby의 패키지 관리 도구인 Bundler를 설치하고 필수적인 개발 도구를 설정한다.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gem install bundler
|
||||||
|
bundle -v # 설치 확인
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2.3. 편집기 및 IDE 추천**
|
||||||
|
Ruby 개발을 위해 다음과 같은 코드 편집기를 사용할 수 있다.
|
||||||
|
- **VS Code**: `code` 명령어로 실행 가능
|
||||||
|
- **RubyMine**: JetBrains에서 제공하는 강력한 Ruby IDE
|
||||||
|
- **Vim 또는 Emacs**: 가벼운 환경에서 Ruby 개발 가능
|
||||||
|
|
||||||
|
### **2.4. Rails 개발 환경 설정 (선택 사항)**
|
||||||
|
Ruby on Rails를 사용하려면 다음 명령어로 설치할 수 있다.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gem install rails
|
||||||
|
rails -v # Rails 버전 확인
|
||||||
|
```
|
||||||
|
|
||||||
|
## **3. 마무리**
|
||||||
|
Ruby는 배우기 쉽고 강력한 기능을 제공하는 프로그래밍 언어다. 리눅스 환경에서 rbenv나 RVM을 이용하면 손쉽게 Ruby 개발 환경을 구성할 수 있다. 이제 Ruby의 문법과 활용법을 익히면서 실전 프로젝트에 적용해보자!
|
||||||
211
docs/02_기본 문법과 데이터 타입.md
Normal file
211
docs/02_기본 문법과 데이터 타입.md
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
# **Ruby 기본 문법과 데이터 타입**
|
||||||
|
|
||||||
|
Ruby는 간결한 문법과 강력한 객체지향 기능을 갖춘 프로그래밍 언어다. 이 글에서는 Ruby의 기본적인 문법과 주요 데이터 타입을 설명한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **1. Ruby의 기본 문법**
|
||||||
|
|
||||||
|
### **1.1. 변수와 상수**
|
||||||
|
Ruby에서 변수는 `snake_case`(소문자 + 밑줄)로 작성하는 것이 일반적이다. 변수 앞에 특정 기호를 붙이면 의미가 달라진다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
name = "Alice" # 일반 변수
|
||||||
|
$global_var = 10 # 전역 변수
|
||||||
|
@instance_var = 20 # 인스턴스 변수
|
||||||
|
@@class_var = 30 # 클래스 변수
|
||||||
|
```
|
||||||
|
|
||||||
|
상수는 대문자로 정의하며, 한 번 설정한 후 변경을 경고하지만 강제할 수는 없다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
PI = 3.14159
|
||||||
|
PI = 3.14 # 경고: 이미 정의된 상수를 변경
|
||||||
|
```
|
||||||
|
|
||||||
|
### **1.2. 출력 및 입력**
|
||||||
|
Ruby에서는 `puts`, `print`, `p` 등을 사용하여 출력을 수행한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
puts "Hello, Ruby!" # 줄 바꿈 포함 출력
|
||||||
|
print "Hello, " # 줄 바꿈 없이 출력
|
||||||
|
print "World!\n"
|
||||||
|
p [1, 2, 3] # 배열 출력 시 따옴표 포함
|
||||||
|
```
|
||||||
|
|
||||||
|
사용자로부터 입력을 받을 때는 `gets`를 사용한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
print "이름을 입력하세요: "
|
||||||
|
name = gets.chomp # 개행 문자 제거
|
||||||
|
puts "반갑습니다, #{name}님!"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **2. Ruby의 주요 데이터 타입**
|
||||||
|
|
||||||
|
Ruby의 모든 것은 객체이며, 기본 데이터 타입도 객체로 다룬다.
|
||||||
|
|
||||||
|
### **2.1. 숫자(Number)**
|
||||||
|
Ruby는 정수(`Integer`)와 실수(`Float`)를 지원한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
int_num = 10 # 정수
|
||||||
|
float_num = 3.14 # 실수
|
||||||
|
|
||||||
|
puts int_num.class # Integer
|
||||||
|
puts float_num.class # Float
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **기본 연산**
|
||||||
|
```ruby
|
||||||
|
puts 10 + 5 # 덧셈 (15)
|
||||||
|
puts 10 - 5 # 뺄셈 (5)
|
||||||
|
puts 10 * 5 # 곱셈 (50)
|
||||||
|
puts 10 / 3 # 정수 나눗셈 (3)
|
||||||
|
puts 10.0 / 3 # 실수 나눗셈 (3.333...)
|
||||||
|
puts 10 % 3 # 나머지 (1)
|
||||||
|
puts 2 ** 3 # 제곱 (8)
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2.2. 문자열(String)**
|
||||||
|
문자열은 작은따옴표(`'`) 또는 큰따옴표(`"`)로 감싼다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
str1 = 'Hello'
|
||||||
|
str2 = "World"
|
||||||
|
|
||||||
|
puts str1 + " " + str2 # "Hello World"
|
||||||
|
puts "#{str1}, #{str2}!" # "Hello, World!"
|
||||||
|
puts str1.upcase # "HELLO"
|
||||||
|
puts str2.downcase # "world"
|
||||||
|
puts "Ruby".reverse # "ybuR"
|
||||||
|
```
|
||||||
|
|
||||||
|
큰따옴표(`" "`)에서는 **문자열 보간(interpolation)**이 가능하지만, 작은따옴표(`' '`)에서는 지원되지 않는다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
name = "Alice"
|
||||||
|
puts "안녕하세요, #{name}님!" # 가능
|
||||||
|
puts '안녕하세요, #{name}님!' # 그대로 출력됨
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2.3. 심볼(Symbol)**
|
||||||
|
심볼은 `:name`처럼 콜론(`:`)으로 시작하며, 변경되지 않는 고유한 문자열을 표현할 때 사용한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
sym1 = :ruby
|
||||||
|
sym2 = :ruby
|
||||||
|
|
||||||
|
puts sym1 == sym2 # true (동일한 객체)
|
||||||
|
puts sym1.object_id == sym2.object_id # true
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2.4. 배열(Array)**
|
||||||
|
Ruby의 배열은 여러 개의 값을 순서대로 저장하는 자료구조다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
arr = [1, 2, 3, "Ruby", :symbol]
|
||||||
|
|
||||||
|
puts arr[0] # 1
|
||||||
|
puts arr[-1] # :symbol (마지막 요소)
|
||||||
|
puts arr.length # 5
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **배열 조작**
|
||||||
|
```ruby
|
||||||
|
arr << 6 # 요소 추가
|
||||||
|
arr.push(7) # 요소 추가
|
||||||
|
arr.pop # 마지막 요소 제거
|
||||||
|
arr.unshift(0) # 맨 앞에 요소 추가
|
||||||
|
arr.shift # 첫 번째 요소 제거
|
||||||
|
|
||||||
|
puts arr.inspect # [1, 2, 3, "Ruby", :symbol, 6]
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2.5. 해시(Hash)**
|
||||||
|
해시는 키-값 쌍으로 데이터를 저장하는 자료구조다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
person = { "name" => "Alice", "age" => 25 }
|
||||||
|
puts person["name"] # Alice
|
||||||
|
puts person["age"] # 25
|
||||||
|
```
|
||||||
|
|
||||||
|
심볼을 키로 사용할 수도 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
person = { name: "Alice", age: 25 }
|
||||||
|
puts person[:name] # Alice
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **해시 조작**
|
||||||
|
```ruby
|
||||||
|
person[:city] = "Seoul" # 새 키-값 추가
|
||||||
|
puts person.keys # [:name, :age, :city]
|
||||||
|
puts person.values # ["Alice", 25, "Seoul"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **3. 제어문**
|
||||||
|
|
||||||
|
### **3.1. 조건문(if, unless, case)**
|
||||||
|
```ruby
|
||||||
|
age = 20
|
||||||
|
|
||||||
|
if age >= 18
|
||||||
|
puts "성인입니다."
|
||||||
|
elsif age >= 13
|
||||||
|
puts "청소년입니다."
|
||||||
|
else
|
||||||
|
puts "어린이입니다."
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
`unless`는 `if not`과 같은 역할을 한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
unless age < 18
|
||||||
|
puts "성인입니다."
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
`case` 문을 사용하면 여러 조건을 간결하게 표현할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
grade = "A"
|
||||||
|
|
||||||
|
case grade
|
||||||
|
when "A"
|
||||||
|
puts "우수합니다."
|
||||||
|
when "B"
|
||||||
|
puts "좋습니다."
|
||||||
|
else
|
||||||
|
puts "더 노력하세요."
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### **3.2. 반복문(while, until, for, each)**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
i = 1
|
||||||
|
while i <= 5
|
||||||
|
puts i
|
||||||
|
i += 1
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
`each`를 사용하면 더 간결하게 반복할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
[1, 2, 3, 4, 5].each do |num|
|
||||||
|
puts num
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **4. 마무리**
|
||||||
|
Ruby는 간결하면서도 강력한 문법을 제공하는 언어다. 변수, 문자열, 배열, 해시 등 다양한 데이터 타입을 활용하면 유연한 코드를 작성할 수 있다. 기본 문법을 익혔다면, 이제 실습을 통해 Ruby의 객체지향 기능과 다양한 메서드를 활용해보자!
|
||||||
265
docs/03_메서드와 블록.md
Normal file
265
docs/03_메서드와 블록.md
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
# **Ruby 메서드와 블록**
|
||||||
|
|
||||||
|
Ruby는 간결하고 유연한 문법을 제공하는 언어로, 메서드와 블록을 활용하면 가독성이 뛰어나고 재사용 가능한 코드를 작성할 수 있다. 이번 글에서는 **메서드**와 **블록**을 중심으로 설명하겠다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **1. Ruby 메서드(Method)**
|
||||||
|
|
||||||
|
Ruby에서 메서드는 특정 동작을 수행하는 코드의 묶음이다. 다른 프로그래밍 언어에서 함수(function)와 비슷하지만, Ruby에서는 모든 것이 객체이므로 메서드 역시 객체에 속한다.
|
||||||
|
|
||||||
|
### **1.1. 메서드 정의와 호출**
|
||||||
|
|
||||||
|
메서드는 `def` 키워드를 사용하여 정의하며, `end`로 닫는다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def say_hello
|
||||||
|
puts "Hello, Ruby!"
|
||||||
|
end
|
||||||
|
|
||||||
|
say_hello # 메서드 호출
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **매개변수가 있는 메서드**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def greet(name)
|
||||||
|
puts "안녕하세요, #{name}님!"
|
||||||
|
end
|
||||||
|
|
||||||
|
greet("Alice") # "안녕하세요, Alice님!"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **기본값을 갖는 매개변수**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def greet(name = "Ruby")
|
||||||
|
puts "안녕하세요, #{name}님!"
|
||||||
|
end
|
||||||
|
|
||||||
|
greet # "안녕하세요, Ruby님!"
|
||||||
|
greet("Alice") # "안녕하세요, Alice님!"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **여러 개의 인수 받기 (가변 인수, splat 연산자 `*`)**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def sum(*numbers)
|
||||||
|
numbers.sum
|
||||||
|
end
|
||||||
|
|
||||||
|
puts sum(1, 2, 3, 4, 5) # 15
|
||||||
|
puts sum(10, 20, 30) # 60
|
||||||
|
```
|
||||||
|
|
||||||
|
`*numbers`는 가변 길이의 인수를 배열로 변환하여 처리한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **1.2. 반환값(Return Value)**
|
||||||
|
|
||||||
|
Ruby의 메서드는 기본적으로 마지막 실행된 표현식의 결과를 반환한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def add(a, b)
|
||||||
|
a + b # 마지막 줄이 반환값
|
||||||
|
end
|
||||||
|
|
||||||
|
puts add(3, 7) # 10
|
||||||
|
```
|
||||||
|
|
||||||
|
`return` 키워드를 사용하면 명시적으로 값을 반환할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def add(a, b)
|
||||||
|
return a + b
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
하지만, Ruby에서는 `return`을 생략하는 것이 일반적이다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **1.3. 키워드 인수(Keyword Arguments)**
|
||||||
|
|
||||||
|
Ruby 2.0부터 키워드 인수를 지원하여 가독성이 높아졌다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def introduce(name:, age:)
|
||||||
|
puts "이름: #{name}, 나이: #{age}"
|
||||||
|
end
|
||||||
|
|
||||||
|
introduce(name: "Alice", age: 25)
|
||||||
|
```
|
||||||
|
|
||||||
|
기본값을 설정할 수도 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def introduce(name: "홍길동", age: 20)
|
||||||
|
puts "이름: #{name}, 나이: #{age}"
|
||||||
|
end
|
||||||
|
|
||||||
|
introduce # "이름: 홍길동, 나이: 20"
|
||||||
|
introduce(name: "Bob") # "이름: Bob, 나이: 20"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **2. 블록(Block)과 반복문**
|
||||||
|
|
||||||
|
블록은 `{}` 또는 `do...end`로 감싸는 코드 덩어리다. 특정 메서드에서 실행할 코드를 블록으로 전달할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
3.times { puts "Ruby!" }
|
||||||
|
```
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
3.times do
|
||||||
|
puts "Ruby!"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
위 두 코드는 동일한 결과를 출력한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2.1. 블록을 사용하는 메서드**
|
||||||
|
|
||||||
|
블록을 전달받는 대표적인 메서드로 `each`가 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
[1, 2, 3].each { |num| puts num }
|
||||||
|
```
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
[1, 2, 3].each do |num|
|
||||||
|
puts num
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2.2. 블록을 명시적으로 호출 (`yield`)**
|
||||||
|
|
||||||
|
Ruby에서는 `yield`를 사용하여 블록을 실행할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def with_greeting
|
||||||
|
puts "안녕하세요!"
|
||||||
|
yield # 블록 실행
|
||||||
|
puts "좋은 하루 되세요!"
|
||||||
|
end
|
||||||
|
|
||||||
|
with_greeting { puts "블록 내부 실행!" }
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 결과:
|
||||||
|
```
|
||||||
|
안녕하세요!
|
||||||
|
블록 내부 실행!
|
||||||
|
좋은 하루 되세요!
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **블록에 값 전달**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def twice
|
||||||
|
yield 1
|
||||||
|
yield 2
|
||||||
|
end
|
||||||
|
|
||||||
|
twice { |num| puts "숫자: #{num}" }
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 결과:
|
||||||
|
```
|
||||||
|
숫자: 1
|
||||||
|
숫자: 2
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2.3. 블록을 매개변수로 받기 (`&block`)**
|
||||||
|
|
||||||
|
블록을 명시적으로 매개변수로 받으려면 `&block`을 사용한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def repeat(n, &block)
|
||||||
|
n.times { block.call }
|
||||||
|
end
|
||||||
|
|
||||||
|
repeat(3) { puts "블록 실행!" }
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 결과:
|
||||||
|
```
|
||||||
|
블록 실행!
|
||||||
|
블록 실행!
|
||||||
|
블록 실행!
|
||||||
|
```
|
||||||
|
|
||||||
|
블록이 주어지지 않은 경우의 예외 처리는 `block_given?`을 사용한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def optional_block
|
||||||
|
if block_given?
|
||||||
|
yield
|
||||||
|
else
|
||||||
|
puts "블록이 없습니다!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
optional_block # "블록이 없습니다!"
|
||||||
|
optional_block { puts "블록이 실행됨!" }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2.4. `Proc`과 `Lambda`**
|
||||||
|
|
||||||
|
Ruby에서는 블록을 `Proc` 또는 `Lambda` 객체로 저장할 수도 있다.
|
||||||
|
|
||||||
|
#### **Proc 객체**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
say_hello = Proc.new { puts "Hello!" }
|
||||||
|
say_hello.call # "Hello!"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **Lambda 객체**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
greet = ->(name) { puts "안녕하세요, #{name}님!" }
|
||||||
|
greet.call("Alice")
|
||||||
|
```
|
||||||
|
|
||||||
|
`Proc`과 `Lambda`의 차이점은 `return` 동작 방식과 매개변수 처리 방식에 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def test_proc
|
||||||
|
p = Proc.new { return "Proc 리턴" }
|
||||||
|
p.call
|
||||||
|
"메서드 종료"
|
||||||
|
end
|
||||||
|
|
||||||
|
puts test_proc # "Proc 리턴" (Proc의 return이 메서드까지 종료)
|
||||||
|
|
||||||
|
def test_lambda
|
||||||
|
l = -> { return "Lambda 리턴" }
|
||||||
|
l.call
|
||||||
|
"메서드 종료"
|
||||||
|
end
|
||||||
|
|
||||||
|
puts test_lambda # "메서드 종료" (Lambda의 return은 람다 내부만 종료)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **3. 마무리**
|
||||||
|
|
||||||
|
Ruby에서 메서드와 블록을 활용하면 가독성과 재사용성이 높은 코드를 작성할 수 있다.
|
||||||
|
- **메서드**는 `def`로 정의하며, 매개변수를 가질 수 있다.
|
||||||
|
- **블록**은 `{}` 또는 `do...end`로 감싸며, `yield` 또는 `&block`을 사용해 실행할 수 있다.
|
||||||
|
- **Proc과 Lambda**를 사용하면 블록을 객체로 다룰 수 있다.
|
||||||
|
|
||||||
|
이제 Ruby의 메서드와 블록을 활용하여 더 유연한 프로그램을 만들어보자!
|
||||||
281
docs/04_객체지향 프로그래밍.md
Normal file
281
docs/04_객체지향 프로그래밍.md
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
# **Ruby의 객체지향 프로그래밍(OOP) 개념과 활용**
|
||||||
|
|
||||||
|
Ruby는 순수 객체지향 언어(Object-Oriented Language)다. **모든 것이 객체**이며, 객체는 **클래스(Class)**에서 생성된다. 이번 글에서는 객체지향 프로그래밍(OOP)의 핵심 개념과 Ruby에서의 활용 방법을 설명한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **1. 객체(Object)란?**
|
||||||
|
|
||||||
|
객체는 **상태(데이터)와 행동(메서드)**을 가진 독립적인 단위다. 예를 들어, 자동차 객체를 생각해보자.
|
||||||
|
|
||||||
|
- **상태(속성, 데이터)**: 색상, 속도, 브랜드
|
||||||
|
- **행동(메서드)**: 가속, 감속, 방향 전환
|
||||||
|
|
||||||
|
Ruby에서는 모든 것이 객체이므로 숫자, 문자열, 배열도 객체다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
puts 10.class # Integer
|
||||||
|
puts "Ruby".class # String
|
||||||
|
puts [1, 2, 3].class # Array
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **2. 클래스(Class)와 객체 생성**
|
||||||
|
|
||||||
|
클래스는 객체를 만들기 위한 **설계도(템플릿)**이다.
|
||||||
|
|
||||||
|
### **2.1. 클래스 정의**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Car
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2.2. 객체(인스턴스) 생성**
|
||||||
|
|
||||||
|
`new` 메서드를 사용해 클래스로부터 객체를 생성할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
my_car = Car.new
|
||||||
|
puts my_car.class # Car
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **3. 인스턴스 변수와 메서드**
|
||||||
|
|
||||||
|
클래스 내부에는 **속성(인스턴스 변수, `@변수명`)과 동작(메서드)**을 정의할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Car
|
||||||
|
def initialize(brand, color)
|
||||||
|
@brand = brand # 인스턴스 변수
|
||||||
|
@color = color
|
||||||
|
end
|
||||||
|
|
||||||
|
def info
|
||||||
|
puts "브랜드: #{@brand}, 색상: #{@color}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
car1 = Car.new("Tesla", "Red")
|
||||||
|
car2 = Car.new("BMW", "Blue")
|
||||||
|
|
||||||
|
car1.info # "브랜드: Tesla, 색상: Red"
|
||||||
|
car2.info # "브랜드: BMW, 색상: Blue"
|
||||||
|
```
|
||||||
|
|
||||||
|
### **3.1. `initialize` 메서드**
|
||||||
|
- 객체가 생성될 때 자동으로 호출되는 **생성자(constructor)**다.
|
||||||
|
- `@변수명`을 사용해 객체 내부에서 데이터를 저장할 수 있다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **4. 접근자 메서드 (Getter, Setter)**
|
||||||
|
|
||||||
|
Ruby에서는 객체의 속성을 직접 접근하지 않고, **메서드를 통해 접근하는 것이 일반적**이다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Car
|
||||||
|
def initialize(brand, color)
|
||||||
|
@brand = brand
|
||||||
|
@color = color
|
||||||
|
end
|
||||||
|
|
||||||
|
# Getter (값을 반환)
|
||||||
|
def brand
|
||||||
|
@brand
|
||||||
|
end
|
||||||
|
|
||||||
|
# Setter (값을 변경)
|
||||||
|
def color=(new_color)
|
||||||
|
@color = new_color
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
car = Car.new("Tesla", "Red")
|
||||||
|
puts car.brand # "Tesla"
|
||||||
|
|
||||||
|
car.color = "Blue" # Setter 사용
|
||||||
|
```
|
||||||
|
|
||||||
|
Ruby에서는 이러한 Getter/Setter를 간편하게 정의할 수 있도록 `attr_accessor`, `attr_reader`, `attr_writer`를 제공한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Car
|
||||||
|
attr_accessor :brand, :color # Getter + Setter 자동 생성
|
||||||
|
|
||||||
|
def initialize(brand, color)
|
||||||
|
@brand = brand
|
||||||
|
@color = color
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
car = Car.new("BMW", "White")
|
||||||
|
puts car.brand # "BMW"
|
||||||
|
|
||||||
|
car.color = "Black"
|
||||||
|
puts car.color # "Black"
|
||||||
|
```
|
||||||
|
|
||||||
|
- `attr_reader :변수명` → 읽기 전용(Getter만)
|
||||||
|
- `attr_writer :변수명` → 쓰기 전용(Setter만)
|
||||||
|
- `attr_accessor :변수명` → 읽기 + 쓰기
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **5. 클래스 메서드와 클래스 변수**
|
||||||
|
|
||||||
|
### **5.1. 클래스 변수(`@@`)**
|
||||||
|
|
||||||
|
클래스 전체에서 공유되는 변수다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Car
|
||||||
|
@@count = 0 # 클래스 변수
|
||||||
|
|
||||||
|
def initialize(brand, color)
|
||||||
|
@brand = brand
|
||||||
|
@color = color
|
||||||
|
@@count += 1 # 생성될 때마다 증가
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.total_cars
|
||||||
|
@@count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Car.new("Tesla", "Red")
|
||||||
|
Car.new("BMW", "Blue")
|
||||||
|
|
||||||
|
puts Car.total_cars # 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### **5.2. 클래스 메서드 (`self.method_name`)**
|
||||||
|
|
||||||
|
클래스 자체에서 호출하는 메서드다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Car
|
||||||
|
def self.info
|
||||||
|
puts "자동차 클래스입니다."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Car.info # "자동차 클래스입니다."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **6. 상속(Inheritance)**
|
||||||
|
|
||||||
|
한 클래스가 다른 클래스를 상속받아 기능을 확장할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Vehicle
|
||||||
|
def move
|
||||||
|
puts "이동 중..."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Car < Vehicle
|
||||||
|
end
|
||||||
|
|
||||||
|
car = Car.new
|
||||||
|
car.move # "이동 중..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### **6.1. `super` 키워드**
|
||||||
|
|
||||||
|
부모 클래스의 메서드를 호출할 때 사용한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Vehicle
|
||||||
|
def initialize(type)
|
||||||
|
@type = type
|
||||||
|
end
|
||||||
|
|
||||||
|
def info
|
||||||
|
puts "종류: #{@type}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Car < Vehicle
|
||||||
|
def initialize(brand, color)
|
||||||
|
super("자동차") # 부모 클래스 생성자 호출
|
||||||
|
@brand = brand
|
||||||
|
@color = color
|
||||||
|
end
|
||||||
|
|
||||||
|
def info
|
||||||
|
super # 부모 클래스의 info 호출
|
||||||
|
puts "브랜드: #{@brand}, 색상: #{@color}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
car = Car.new("Tesla", "Red")
|
||||||
|
car.info
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 결과:
|
||||||
|
```
|
||||||
|
종류: 자동차
|
||||||
|
브랜드: Tesla, 색상: Red
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **7. 모듈(Module)과 믹스인(Mixin)**
|
||||||
|
|
||||||
|
Ruby는 다중 상속을 지원하지 않지만, **모듈(Module)**을 사용해 기능을 추가할 수 있다.
|
||||||
|
|
||||||
|
### **7.1. 모듈 정의**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
module Drivable
|
||||||
|
def drive
|
||||||
|
puts "운전 중..."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### **7.2. 모듈 포함 (`include`)**
|
||||||
|
|
||||||
|
`include`를 사용하면 인스턴스 메서드로 추가된다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Car
|
||||||
|
include Drivable
|
||||||
|
end
|
||||||
|
|
||||||
|
car = Car.new
|
||||||
|
car.drive # "운전 중..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### **7.3. 모듈 확장 (`extend`)**
|
||||||
|
|
||||||
|
`extend`를 사용하면 클래스 메서드로 추가된다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Car
|
||||||
|
extend Drivable
|
||||||
|
end
|
||||||
|
|
||||||
|
Car.drive # "운전 중..."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **8. 마무리**
|
||||||
|
|
||||||
|
Ruby의 객체지향 프로그래밍(OOP)은 코드의 재사용성과 유지보수성을 높이는 강력한 개념이다.
|
||||||
|
|
||||||
|
- **클래스(Class)와 객체(Object)** → 객체는 클래스로부터 생성됨
|
||||||
|
- **인스턴스 변수와 메서드** → `@변수`로 속성 저장, 메서드로 동작 정의
|
||||||
|
- **Getter/Setter** → `attr_accessor`로 간단하게 정의 가능
|
||||||
|
- **클래스 변수/메서드** → `@@변수`, `self.메서드`
|
||||||
|
- **상속(Inheritance)** → `class 자식클래스 < 부모클래스`
|
||||||
|
- **모듈(Module)과 믹스인(Mixin)** → `include`, `extend`로 기능 추가
|
||||||
|
|
||||||
|
이제 Ruby의 객체지향 개념을 활용하여 더욱 효율적인 프로그램을 만들어보자!
|
||||||
202
docs/05_파일 처리 및 입출력.md
Normal file
202
docs/05_파일 처리 및 입출력.md
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
# **Ruby에서 파일 처리 및 입출력(IO) 다루기**
|
||||||
|
|
||||||
|
프로그램을 작성하다 보면 데이터를 파일에 저장하거나, 파일에서 데이터를 읽어와야 할 때가 많다. Ruby에서는 파일을 간편하게 읽고 쓸 수 있는 다양한 기능을 제공한다. 이번 글에서는 **파일 읽기/쓰기, 표준 입출력(STDIN, STDOUT, STDERR), 디렉터리 작업** 등을 다룬다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **1. 파일 읽고 쓰기 (File 클래스)**
|
||||||
|
|
||||||
|
Ruby에서 파일을 다룰 때는 `File` 클래스를 사용한다. 파일을 열 때는 `File.open`을 사용하며, 읽기 모드, 쓰기 모드 등을 지정할 수 있다.
|
||||||
|
|
||||||
|
### **1.1. 파일 쓰기 (`w`, `a`, `w+`, `a+`)**
|
||||||
|
|
||||||
|
#### **파일 새로 쓰기 (`w` 모드)**
|
||||||
|
파일을 새로 생성하고 데이터를 저장한다. **기존 파일이 있으면 덮어쓴다.**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
File.open("example.txt", "w") do |file|
|
||||||
|
file.puts "Hello, Ruby!"
|
||||||
|
file.puts "파일 쓰기 예제입니다."
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
- `puts` → 문자열을 출력하고 자동으로 개행(`\n`) 추가
|
||||||
|
- `write` → 개행 없이 그대로 출력
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
File.open("example.txt", "w") do |file|
|
||||||
|
file.write "Hello, Ruby!"
|
||||||
|
file.write "이건 개행이 없습니다."
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 결과 (`example.txt`):
|
||||||
|
```
|
||||||
|
Hello, Ruby!이건 개행이 없습니다.
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **파일 이어 쓰기 (`a` 모드)**
|
||||||
|
기존 파일이 있으면 내용을 유지하면서 **새로운 내용을 추가**한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
File.open("example.txt", "a") do |file|
|
||||||
|
file.puts "새로운 줄이 추가됩니다."
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **읽기와 쓰기 (`w+`, `a+` 모드)**
|
||||||
|
- `w+` → 읽기 + 쓰기 가능, **기존 파일 삭제 후 새로 생성**
|
||||||
|
- `a+` → 읽기 + 쓰기 가능, **기존 내용 유지하며 추가 가능**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **1.2. 파일 읽기 (`r`, `r+`)**
|
||||||
|
|
||||||
|
#### **한 줄씩 읽기 (`gets`)**
|
||||||
|
```ruby
|
||||||
|
File.open("example.txt", "r") do |file|
|
||||||
|
puts file.gets # 첫 번째 줄 읽기
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **모든 줄 읽기 (`readlines`)**
|
||||||
|
파일의 모든 줄을 배열로 읽어온다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
File.open("example.txt", "r") do |file|
|
||||||
|
file.readlines.each do |line|
|
||||||
|
puts line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **파일 전체 읽기 (`read`)**
|
||||||
|
파일 내용을 한 번에 읽어 문자열로 반환한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
content = File.read("example.txt")
|
||||||
|
puts content
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **파일 존재 여부 확인**
|
||||||
|
```ruby
|
||||||
|
if File.exist?("example.txt")
|
||||||
|
puts "파일이 존재합니다!"
|
||||||
|
else
|
||||||
|
puts "파일이 없습니다."
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **2. 파일 삭제 및 기타 기능**
|
||||||
|
|
||||||
|
### **2.1. 파일 삭제**
|
||||||
|
```ruby
|
||||||
|
File.delete("example.txt") if File.exist?("example.txt")
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2.2. 파일 이름 변경**
|
||||||
|
```ruby
|
||||||
|
File.rename("old_name.txt", "new_name.txt")
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2.3. 파일 크기 확인**
|
||||||
|
```ruby
|
||||||
|
puts File.size("example.txt") # 바이트 단위 크기 반환
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **3. 표준 입출력 (STDIN, STDOUT, STDERR)**
|
||||||
|
|
||||||
|
### **3.1. 콘솔 입력 (STDIN)**
|
||||||
|
사용자로부터 입력을 받을 때는 `gets`를 사용한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
puts "이름을 입력하세요:"
|
||||||
|
name = gets.chomp # 개행 문자 제거
|
||||||
|
puts "안녕하세요, #{name}님!"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3.2. 표준 출력 (STDOUT)**
|
||||||
|
`puts`, `print`, `p`를 이용해 출력할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
puts "Hello, Ruby!" # 개행 포함
|
||||||
|
print "Hello, " # 개행 없음
|
||||||
|
print "World!\n"
|
||||||
|
p [1, 2, 3] # 디버깅용 출력
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 결과:
|
||||||
|
```
|
||||||
|
Hello, Ruby!
|
||||||
|
Hello, World!
|
||||||
|
[1, 2, 3]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3.3. 오류 출력 (STDERR)**
|
||||||
|
오류 메시지는 `STDERR.puts`를 사용해 출력할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
STDERR.puts "이건 오류 메시지입니다!"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **4. 디렉터리 작업 (Dir 클래스)**
|
||||||
|
|
||||||
|
### **4.1. 디렉터리 생성 및 삭제**
|
||||||
|
```ruby
|
||||||
|
Dir.mkdir("my_folder") unless Dir.exist?("my_folder") # 폴더 생성
|
||||||
|
Dir.rmdir("my_folder") # 폴더 삭제 (비어있을 때만 가능)
|
||||||
|
```
|
||||||
|
|
||||||
|
### **4.2. 디렉터리 내 파일 목록 조회**
|
||||||
|
```ruby
|
||||||
|
puts Dir.entries(".") # 현재 디렉터리의 파일 및 폴더 목록 출력
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **5. 실전 예제: 로그 파일 기록기**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Logger
|
||||||
|
LOG_FILE = "log.txt"
|
||||||
|
|
||||||
|
def self.log(message)
|
||||||
|
File.open(LOG_FILE, "a") do |file|
|
||||||
|
file.puts("[#{Time.now}] #{message}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Logger.log("프로그램이 실행되었습니다.")
|
||||||
|
Logger.log("사용자가 로그인했습니다.")
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 (`log.txt`):
|
||||||
|
```
|
||||||
|
[2025-03-03 12:34:56] 프로그램이 실행되었습니다.
|
||||||
|
[2025-03-03 12:35:10] 사용자가 로그인했습니다.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **6. 마무리**
|
||||||
|
|
||||||
|
Ruby에서는 파일과 입출력을 간편하게 다룰 수 있다.
|
||||||
|
|
||||||
|
- **파일 쓰기** → `"w"`, `"a"`, `"w+"`, `"a+"` 모드
|
||||||
|
- **파일 읽기** → `gets`, `readlines`, `read`
|
||||||
|
- **파일 관리** → `File.exist?`, `File.delete`, `File.rename`, `File.size`
|
||||||
|
- **입출력(IO)** → `gets`로 입력 받기, `puts`로 출력, `STDERR.puts`로 오류 출력
|
||||||
|
- **디렉터리 작업** → `Dir.mkdir`, `Dir.entries`
|
||||||
|
|
||||||
|
이제 Ruby에서 파일을 활용하여 로그 기록, 데이터 저장, 설정 파일 관리 등을 할 수 있다.
|
||||||
231
docs/06_CSV, JSON, YAML 파일 처리 및 네트워크 요청.md
Normal file
231
docs/06_CSV, JSON, YAML 파일 처리 및 네트워크 요청.md
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
# **Ruby에서 CSV, JSON, YAML 파일 처리 및 네트워크 요청 보내기**
|
||||||
|
|
||||||
|
현대 프로그래밍에서 데이터는 다양한 포맷으로 저장되며, 네트워크를 통해 주고받는 일이 많다. Ruby에서는 **CSV, JSON, YAML** 같은 파일을 쉽게 다룰 수 있고, **HTTP 요청**을 통해 웹 API와 데이터를 주고받을 수도 있다. 이번 글에서는 이러한 작업을 어떻게 수행하는지 설명한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **1. CSV 파일 다루기 (`csv` 라이브러리)**
|
||||||
|
|
||||||
|
CSV(Comma-Separated Values)는 데이터를 테이블 형식으로 저장하는 파일 포맷이다. Ruby에서는 `csv` 라이브러리를 사용해 CSV 파일을 읽고 쓸 수 있다.
|
||||||
|
|
||||||
|
### **1.1. CSV 파일 쓰기**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "csv"
|
||||||
|
|
||||||
|
CSV.open("data.csv", "w") do |csv|
|
||||||
|
csv << ["이름", "나이", "직업"]
|
||||||
|
csv << ["홍길동", 30, "개발자"]
|
||||||
|
csv << ["김철수", 25, "디자이너"]
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 (`data.csv`):
|
||||||
|
```
|
||||||
|
이름,나이,직업
|
||||||
|
홍길동,30,개발자
|
||||||
|
김철수,25,디자이너
|
||||||
|
```
|
||||||
|
|
||||||
|
### **1.2. CSV 파일 읽기**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
CSV.foreach("data.csv", headers: true) do |row|
|
||||||
|
puts "#{row["이름"]} (#{row["나이"]}세) - #{row["직업"]}"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
출력:
|
||||||
|
```
|
||||||
|
홍길동 (30세) - 개발자
|
||||||
|
김철수 (25세) - 디자이너
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **2. JSON 파일 다루기 (`json` 라이브러리)**
|
||||||
|
|
||||||
|
JSON(JavaScript Object Notation)은 웹 API에서 데이터를 주고받을 때 가장 많이 쓰이는 포맷이다.
|
||||||
|
|
||||||
|
### **2.1. JSON 파일 쓰기**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "json"
|
||||||
|
|
||||||
|
data = [
|
||||||
|
{ name: "홍길동", age: 30, job: "개발자" },
|
||||||
|
{ name: "김철수", age: 25, job: "디자이너" }
|
||||||
|
]
|
||||||
|
|
||||||
|
File.write("data.json", JSON.pretty_generate(data))
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 (`data.json`):
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "홍길동",
|
||||||
|
"age": 30,
|
||||||
|
"job": "개발자"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "김철수",
|
||||||
|
"age": 25,
|
||||||
|
"job": "디자이너"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2.2. JSON 파일 읽기**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
json_data = File.read("data.json")
|
||||||
|
data = JSON.parse(json_data)
|
||||||
|
|
||||||
|
data.each do |person|
|
||||||
|
puts "#{person["name"]} (#{person["age"]}세) - #{person["job"]}"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
출력:
|
||||||
|
```
|
||||||
|
홍길동 (30세) - 개발자
|
||||||
|
김철수 (25세) - 디자이너
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **3. YAML 파일 다루기 (`yaml` 라이브러리)**
|
||||||
|
|
||||||
|
YAML(YAML Ain't Markup Language)은 사람이 읽기 쉬운 데이터 포맷으로, 설정 파일 등에 많이 사용된다.
|
||||||
|
|
||||||
|
### **3.1. YAML 파일 쓰기**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "yaml"
|
||||||
|
|
||||||
|
data = [
|
||||||
|
{ "name" => "홍길동", "age" => 30, "job" => "개발자" },
|
||||||
|
{ "name" => "김철수", "age" => 25, "job" => "디자이너" }
|
||||||
|
]
|
||||||
|
|
||||||
|
File.write("data.yaml", data.to_yaml)
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 (`data.yaml`):
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
- name: 홍길동
|
||||||
|
age: 30
|
||||||
|
job: 개발자
|
||||||
|
- name: 김철수
|
||||||
|
age: 25
|
||||||
|
job: 디자이너
|
||||||
|
```
|
||||||
|
|
||||||
|
### **3.2. YAML 파일 읽기**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
yaml_data = File.read("data.yaml")
|
||||||
|
data = YAML.load(yaml_data)
|
||||||
|
|
||||||
|
data.each do |person|
|
||||||
|
puts "#{person["name"]} (#{person["age"]}세) - #{person["job"]}"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
출력:
|
||||||
|
```
|
||||||
|
홍길동 (30세) - 개발자
|
||||||
|
김철수 (25세) - 디자이너
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **4. 네트워크 요청 보내기 (`net/http` 라이브러리)**
|
||||||
|
|
||||||
|
웹 서버와 데이터를 주고받으려면 **HTTP 요청**을 사용해야 한다. Ruby에서는 `net/http` 라이브러리를 이용하면 간단하게 요청을 보낼 수 있다.
|
||||||
|
|
||||||
|
### **4.1. GET 요청 보내기**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "net/http"
|
||||||
|
require "json"
|
||||||
|
|
||||||
|
url = URI("https://jsonplaceholder.typicode.com/posts/1")
|
||||||
|
response = Net::HTTP.get(url)
|
||||||
|
|
||||||
|
data = JSON.parse(response)
|
||||||
|
puts "제목: #{data["title"]}"
|
||||||
|
puts "내용: #{data["body"]}"
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 (샘플 API 응답):
|
||||||
|
```
|
||||||
|
제목: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
|
||||||
|
내용: quia et suscipit suscipit...
|
||||||
|
```
|
||||||
|
|
||||||
|
### **4.2. POST 요청 보내기**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "net/http"
|
||||||
|
require "json"
|
||||||
|
|
||||||
|
url = URI("https://jsonplaceholder.typicode.com/posts")
|
||||||
|
http = Net::HTTP.new(url.host, url.port)
|
||||||
|
http.use_ssl = true # HTTPS 요청
|
||||||
|
|
||||||
|
request = Net::HTTP::Post.new(url, { "Content-Type" => "application/json" })
|
||||||
|
request.body = { title: "새 글", body: "내용입니다.", userId: 1 }.to_json
|
||||||
|
|
||||||
|
response = http.request(request)
|
||||||
|
puts response.body
|
||||||
|
```
|
||||||
|
|
||||||
|
출력 (샘플 API 응답):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"title": "새 글",
|
||||||
|
"body": "내용입니다.",
|
||||||
|
"userId": 1,
|
||||||
|
"id": 101
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **5. HTTP 요청을 쉽게 하는 `http` 라이브러리**
|
||||||
|
|
||||||
|
`net/http`보다 더 편리한 HTTP 클라이언트 라이브러리로 `http`를 사용할 수도 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "http"
|
||||||
|
|
||||||
|
response = HTTP.get("https://jsonplaceholder.typicode.com/posts/1")
|
||||||
|
data = response.parse
|
||||||
|
puts "제목: #{data["title"]}"
|
||||||
|
```
|
||||||
|
|
||||||
|
POST 요청도 매우 간단하다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
response = HTTP.post("https://jsonplaceholder.typicode.com/posts", json: { title: "새 글", body: "내용입니다.", userId: 1 })
|
||||||
|
puts response.parse
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **6. 마무리**
|
||||||
|
|
||||||
|
이번 글에서는 Ruby에서 **CSV, JSON, YAML 파일을 다루는 방법**과 **네트워크 요청을 보내는 방법**을 살펴보았다.
|
||||||
|
|
||||||
|
- **CSV 파일** → `CSV.open`, `CSV.foreach`
|
||||||
|
- **JSON 파일** → `JSON.parse`, `JSON.pretty_generate`
|
||||||
|
- **YAML 파일** → `YAML.load`, `data.to_yaml`
|
||||||
|
- **HTTP 요청 (`net/http`)**
|
||||||
|
- `Net::HTTP.get(url)` → GET 요청
|
||||||
|
- `Net::HTTP::Post.new(url, headers)` → POST 요청
|
||||||
|
- **더 쉬운 HTTP 요청 (`http` 라이브러리)** → `HTTP.get(url)`, `HTTP.post(url, json: {})`
|
||||||
|
|
||||||
|
이제 Ruby에서 다양한 데이터 포맷을 다루고, 웹 API와 상호작용하는 프로그램을 쉽게 만들 수 있다!
|
||||||
251
docs/07_예외 처리와 디버깅.md
Normal file
251
docs/07_예외 처리와 디버깅.md
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
# **Ruby에서 예외 처리와 디버깅**
|
||||||
|
|
||||||
|
프로그램을 개발할 때 **예외 처리(Exception Handling)** 는 필수적인 요소다. 오류를 제대로 처리하지 않으면 프로그램이 예상치 못한 방식으로 종료되거나, 심각한 버그가 발생할 수 있다. 또한 **디버깅(Debugging)** 기법을 활용하면 문제를 쉽게 찾아낼 수 있다. 이번 글에서는 **예외 처리 기법과 디버깅 방법**을 소개한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **1. 예외(Exception)란?**
|
||||||
|
|
||||||
|
예외(Exception)는 프로그램 실행 중 발생하는 오류이다. Ruby에서는 예외가 발생하면 프로그램이 즉시 종료되지만, 적절한 예외 처리를 통해 오류를 방지할 수 있다.
|
||||||
|
|
||||||
|
### **예외 발생 예시**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
puts 10 / 0 # ZeroDivisionError 발생
|
||||||
|
```
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
array = [1, 2, 3]
|
||||||
|
puts array[10] # IndexError 발생
|
||||||
|
```
|
||||||
|
|
||||||
|
위 코드들은 실행 중 오류가 발생하며, 프로그램이 강제 종료된다. 이를 방지하기 위해 **begin-rescue 문**을 사용한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **2. 예외 처리 (`begin-rescue`)**
|
||||||
|
|
||||||
|
Ruby에서는 `begin-rescue` 블록을 사용해 예외를 처리할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
begin
|
||||||
|
puts 10 / 0
|
||||||
|
rescue ZeroDivisionError
|
||||||
|
puts "0으로 나눌 수 없습니다!"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
출력:
|
||||||
|
```
|
||||||
|
0으로 나눌 수 없습니다!
|
||||||
|
```
|
||||||
|
|
||||||
|
### **여러 개의 예외 처리**
|
||||||
|
|
||||||
|
여러 종류의 예외를 처리하려면 `rescue`를 여러 개 사용할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
begin
|
||||||
|
array = [1, 2, 3]
|
||||||
|
puts array[10] # IndexError 발생
|
||||||
|
rescue ZeroDivisionError
|
||||||
|
puts "0으로 나눌 수 없습니다!"
|
||||||
|
rescue IndexError
|
||||||
|
puts "잘못된 인덱스 접근입니다!"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
출력:
|
||||||
|
```
|
||||||
|
잘못된 인덱스 접근입니다!
|
||||||
|
```
|
||||||
|
|
||||||
|
### **모든 예외 처리 (`rescue StandardError`)**
|
||||||
|
|
||||||
|
모든 예외를 처리하려면 `rescue StandardError`를 사용한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
begin
|
||||||
|
puts 10 / 0
|
||||||
|
rescue StandardError => e
|
||||||
|
puts "예외 발생: #{e.message}"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
출력:
|
||||||
|
```
|
||||||
|
예외 발생: divided by 0
|
||||||
|
```
|
||||||
|
|
||||||
|
### **예외 발생 여부와 관계없이 실행 (`ensure`)**
|
||||||
|
|
||||||
|
`ensure` 블록을 사용하면 **예외 발생 여부와 관계없이** 반드시 실행해야 하는 코드를 넣을 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
begin
|
||||||
|
file = File.open("example.txt", "r")
|
||||||
|
puts file.read
|
||||||
|
rescue Errno::ENOENT
|
||||||
|
puts "파일을 찾을 수 없습니다!"
|
||||||
|
ensure
|
||||||
|
file.close if file # 파일이 열려 있다면 닫기
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **3. 예외 강제 발생 (`raise`)**
|
||||||
|
|
||||||
|
`raise` 문을 사용하면 강제로 예외를 발생시킬 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def divide(a, b)
|
||||||
|
raise ArgumentError, "0으로 나눌 수 없습니다!" if b == 0
|
||||||
|
a / b
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
puts divide(10, 0)
|
||||||
|
rescue ArgumentError => e
|
||||||
|
puts "오류 발생: #{e.message}"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
출력:
|
||||||
|
```
|
||||||
|
오류 발생: 0으로 나눌 수 없습니다!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **4. 사용자 정의 예외 클래스**
|
||||||
|
|
||||||
|
Ruby에서는 예외 클래스를 직접 정의할 수도 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class CustomError < StandardError; end
|
||||||
|
|
||||||
|
def check_value(value)
|
||||||
|
raise CustomError, "값이 너무 큽니다!" if value > 100
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
check_value(200)
|
||||||
|
rescue CustomError => e
|
||||||
|
puts "사용자 정의 예외 발생: #{e.message}"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
출력:
|
||||||
|
```
|
||||||
|
사용자 정의 예외 발생: 값이 너무 큽니다!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **5. 디버깅 기법**
|
||||||
|
|
||||||
|
디버깅(Debugging)은 프로그램의 오류를 찾아 수정하는 과정이다. Ruby에서 디버깅하는 방법을 알아보자.
|
||||||
|
|
||||||
|
### **5.1. `puts`와 `p`로 값 출력**
|
||||||
|
|
||||||
|
가장 간단한 방법은 `puts` 또는 `p`를 사용해 변수 값을 확인하는 것이다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
name = "홍길동"
|
||||||
|
puts "이름: #{name}"
|
||||||
|
p name # `p`는 데이터 타입까지 출력해 줌
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **5.2. `irb`(Interactive Ruby) 사용**
|
||||||
|
|
||||||
|
Ruby의 대화형 콘솔 `irb`를 활용하면 코드를 실행하며 디버깅할 수 있다.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ irb
|
||||||
|
irb(main):001:0> 10 / 2
|
||||||
|
=> 5
|
||||||
|
irb(main):002:0> "hello".upcase
|
||||||
|
=> "HELLO"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **5.3. `binding.irb`로 중간 디버깅**
|
||||||
|
|
||||||
|
`binding.irb`를 코드 중간에 넣으면 특정 지점에서 실행을 멈추고 `irb`에서 값을 확인할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "irb"
|
||||||
|
|
||||||
|
def debug_example
|
||||||
|
x = 10
|
||||||
|
y = 20
|
||||||
|
binding.irb # 여기서 실행이 멈추고 irb에서 값을 확인할 수 있음
|
||||||
|
z = x + y
|
||||||
|
puts z
|
||||||
|
end
|
||||||
|
|
||||||
|
debug_example
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **5.4. `debug` 라이브러리 사용**
|
||||||
|
|
||||||
|
Ruby 3.1부터 `debug` 라이브러리를 기본으로 제공하며, 이를 이용하면 강력한 디버깅이 가능하다.
|
||||||
|
|
||||||
|
#### **설치 및 실행 방법**
|
||||||
|
|
||||||
|
1. `debug` 라이브러리 설치 (`Ruby 3.1 이상에서는 기본 제공`)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gem install debug
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 코드에 `require "debug"` 추가
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "debug"
|
||||||
|
|
||||||
|
def test_method
|
||||||
|
x = 5
|
||||||
|
y = 10
|
||||||
|
debugger # 여기서 실행이 멈춤
|
||||||
|
z = x + y
|
||||||
|
puts z
|
||||||
|
end
|
||||||
|
|
||||||
|
test_method
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 프로그램 실행 시 디버깅 모드가 활성화됨
|
||||||
|
|
||||||
|
```sh
|
||||||
|
(rdbg) p x
|
||||||
|
5
|
||||||
|
(rdbg) next
|
||||||
|
(rdbg) continue
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **6. 마무리**
|
||||||
|
|
||||||
|
이번 글에서는 **Ruby에서 예외 처리와 디버깅 기법**을 살펴보았다.
|
||||||
|
|
||||||
|
### **📌 예외 처리 정리**
|
||||||
|
- `begin-rescue` → 예외 처리
|
||||||
|
- `ensure` → 예외 발생 여부와 관계없이 실행
|
||||||
|
- `raise` → 강제 예외 발생
|
||||||
|
- 사용자 정의 예외 → `class CustomError < StandardError`
|
||||||
|
|
||||||
|
### **📌 디버깅 기법 정리**
|
||||||
|
- `puts`, `p` → 변수 값 출력
|
||||||
|
- `irb` → 대화형 실행
|
||||||
|
- `binding.irb` → 특정 지점에서 멈추고 값 확인
|
||||||
|
- `debugger` → 정식 디버깅 툴 사용 (`debug` 라이브러리)
|
||||||
|
|
||||||
|
이제 예외를 안전하게 처리하고, 버그를 효과적으로 찾아 수정할 수 있다!
|
||||||
256
docs/08_데이터베이스 연동 및 Active Record.md
Normal file
256
docs/08_데이터베이스 연동 및 Active Record.md
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
# **Ruby에서 데이터베이스 연동 및 Active Record 사용법**
|
||||||
|
|
||||||
|
웹 애플리케이션을 개발할 때 데이터베이스(Database)는 필수적인 요소다. Ruby에서는 다양한 데이터베이스와 쉽게 연동할 수 있으며, 특히 **Active Record**를 사용하면 객체지향적으로 데이터를 다룰 수 있다. 이번 글에서는 **Ruby에서 데이터베이스를 연동하는 방법과 Active Record의 기본 개념 및 사용법**을 설명한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **1. Ruby에서 데이터베이스 연동 방법**
|
||||||
|
|
||||||
|
Ruby는 다양한 데이터베이스를 지원한다. 대표적으로 **SQLite, MySQL, PostgreSQL** 등이 있으며, 각각의 데이터베이스를 사용하기 위해 적절한 **드라이버(Gem)** 를 설치해야 한다.
|
||||||
|
|
||||||
|
### **1.1. SQLite 사용하기**
|
||||||
|
|
||||||
|
SQLite는 가벼운 파일 기반의 데이터베이스로, 별도의 서버 설정 없이 사용할 수 있어 개발 및 테스트 환경에서 많이 사용된다.
|
||||||
|
|
||||||
|
#### **설치 및 초기 설정**
|
||||||
|
|
||||||
|
SQLite를 사용하려면 `sqlite3` gem을 설치해야 한다.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gem install sqlite3
|
||||||
|
```
|
||||||
|
|
||||||
|
데이터베이스 파일을 생성하고 연결하는 간단한 Ruby 코드:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "sqlite3"
|
||||||
|
|
||||||
|
# SQLite 데이터베이스 파일 생성 (파일이 없다면 자동 생성)
|
||||||
|
db = SQLite3::Database.new "test.db"
|
||||||
|
|
||||||
|
# 테이블 생성
|
||||||
|
db.execute <<-SQL
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
age INTEGER
|
||||||
|
);
|
||||||
|
SQL
|
||||||
|
|
||||||
|
# 데이터 삽입
|
||||||
|
db.execute "INSERT INTO users (name, age) VALUES (?, ?)", ["홍길동", 30]
|
||||||
|
|
||||||
|
# 데이터 조회
|
||||||
|
db.execute "SELECT * FROM users" do |row|
|
||||||
|
puts row.join(", ")
|
||||||
|
end
|
||||||
|
|
||||||
|
db.close # 연결 종료
|
||||||
|
```
|
||||||
|
|
||||||
|
출력:
|
||||||
|
```
|
||||||
|
1, 홍길동, 30
|
||||||
|
```
|
||||||
|
|
||||||
|
SQLite는 파일 기반이므로 `test.db`라는 파일이 생성된다. 이후 Ruby 코드에서 해당 파일을 사용하여 데이터를 읽고 쓸 수 있다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **1.2. MySQL 사용하기**
|
||||||
|
|
||||||
|
MySQL은 대규모 프로젝트에서 자주 사용되는 데이터베이스다. MySQL과 연동하려면 `mysql2` gem을 설치해야 한다.
|
||||||
|
|
||||||
|
#### **설치**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gem install mysql2
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **MySQL 데이터베이스 연결 및 쿼리 실행**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "mysql2"
|
||||||
|
|
||||||
|
# MySQL 클라이언트 설정
|
||||||
|
client = Mysql2::Client.new(
|
||||||
|
host: "localhost",
|
||||||
|
username: "root",
|
||||||
|
password: "password",
|
||||||
|
database: "test_db"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 테이블 생성
|
||||||
|
client.query <<-SQL
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
name VARCHAR(50),
|
||||||
|
age INT
|
||||||
|
);
|
||||||
|
SQL
|
||||||
|
|
||||||
|
# 데이터 삽입
|
||||||
|
client.query("INSERT INTO users (name, age) VALUES ('이순신', 45)")
|
||||||
|
|
||||||
|
# 데이터 조회
|
||||||
|
results = client.query("SELECT * FROM users")
|
||||||
|
results.each do |row|
|
||||||
|
puts row["id"], row["name"], row["age"]
|
||||||
|
end
|
||||||
|
|
||||||
|
client.close # 연결 종료
|
||||||
|
```
|
||||||
|
|
||||||
|
이 방식은 SQL을 직접 실행하는 방법으로, ORM(Object-Relational Mapping) 방식보다 코드가 길어질 수 있다. 이를 간편하게 하기 위해 **Active Record**를 사용할 수 있다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **2. Active Record란?**
|
||||||
|
|
||||||
|
**Active Record**는 Ruby on Rails에서 사용하는 ORM(Object-Relational Mapping) 라이브러리다. SQL을 직접 작성하지 않고도 Ruby 객체를 사용해 데이터를 조작할 수 있다.
|
||||||
|
|
||||||
|
Active Record를 사용하면 SQL 쿼리를 직접 작성할 필요 없이 **객체 지향 방식으로 데이터를 다룰 수 있다**.
|
||||||
|
|
||||||
|
### **2.1. Active Record 설치 및 설정**
|
||||||
|
|
||||||
|
Active Record는 별도로 Rails 프레임워크 없이 사용할 수도 있다.
|
||||||
|
|
||||||
|
#### **설치**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gem install activerecord sqlite3
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **데이터베이스 연결 설정**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "active_record"
|
||||||
|
|
||||||
|
# SQLite 데이터베이스 연결
|
||||||
|
ActiveRecord::Base.establish_connection(
|
||||||
|
adapter: "sqlite3",
|
||||||
|
database: "test.db"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
이제 Active Record를 활용하여 데이터를 다루는 방법을 살펴보자.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **3. Active Record 사용법**
|
||||||
|
|
||||||
|
Active Record를 사용하려면 데이터베이스 테이블에 매핑되는 **모델(Model)** 을 정의해야 한다.
|
||||||
|
|
||||||
|
### **3.1. 모델 정의하기**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class User < ActiveRecord::Base
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
위 코드에서 `User` 클래스는 `users` 테이블과 연결된다. Active Record는 자동으로 **클래스명을 기반으로 테이블명을 추론**하므로, `User` 모델은 `users` 테이블과 매칭된다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3.2. 테이블 생성 (마이그레이션 사용)**
|
||||||
|
|
||||||
|
Active Record에서는 **마이그레이션(Migration)** 을 사용하여 테이블을 생성할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "active_record"
|
||||||
|
|
||||||
|
ActiveRecord::Schema.define do
|
||||||
|
create_table :users, if_not_exists: true do |t|
|
||||||
|
t.string :name
|
||||||
|
t.integer :age
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
이제 `users` 테이블이 생성된다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3.3. 데이터 삽입**
|
||||||
|
|
||||||
|
객체를 생성하고 `.save` 메서드를 호출하면 데이터베이스에 저장된다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
user = User.new(name: "강감찬", age: 40)
|
||||||
|
user.save # 데이터베이스에 저장
|
||||||
|
```
|
||||||
|
|
||||||
|
또는 한 줄로 작성할 수도 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
User.create(name: "김유신", age: 35)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3.4. 데이터 조회**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
users = User.all # 모든 데이터 조회
|
||||||
|
users.each do |user|
|
||||||
|
puts "#{user.id}, #{user.name}, #{user.age}"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
특정 조건을 사용하여 데이터를 조회할 수도 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
user = User.find_by(name: "강감찬")
|
||||||
|
puts user.age # 강감찬의 나이 출력
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3.5. 데이터 수정**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
user = User.find_by(name: "강감찬")
|
||||||
|
user.age = 50
|
||||||
|
user.save # 변경된 내용 저장
|
||||||
|
```
|
||||||
|
|
||||||
|
또는 한 줄로 작성 가능하다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
User.find_by(name: "강감찬")&.update(age: 50)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3.6. 데이터 삭제**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
user = User.find_by(name: "강감찬")
|
||||||
|
user.destroy # 데이터 삭제
|
||||||
|
```
|
||||||
|
|
||||||
|
또는 한 번에 여러 개 삭제할 수도 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
User.where(age: 50).destroy_all
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **4. 정리**
|
||||||
|
|
||||||
|
Ruby에서 데이터베이스를 연동하는 방법과 **Active Record**를 활용하여 데이터를 다루는 방법을 살펴보았다.
|
||||||
|
|
||||||
|
### **📌 데이터베이스 연동 방식**
|
||||||
|
- `sqlite3`, `mysql2` 등의 Gem을 사용하여 SQL을 직접 실행할 수 있다.
|
||||||
|
- Active Record를 사용하면 ORM 방식으로 객체 지향적으로 데이터를 다룰 수 있다.
|
||||||
|
|
||||||
|
### **📌 Active Record 주요 기능**
|
||||||
|
- `User.create(name: "홍길동", age: 30)` → 데이터 삽입
|
||||||
|
- `User.all` → 모든 데이터 조회
|
||||||
|
- `User.find_by(name: "홍길동")` → 특정 데이터 조회
|
||||||
|
- `user.update(age: 35)` → 데이터 수정
|
||||||
|
- `user.destroy` → 데이터 삭제
|
||||||
|
|
||||||
|
Active Record를 사용하면 SQL을 직접 작성하지 않고도 데이터를 쉽게 관리할 수 있다. Ruby로 웹 애플리케이션을 개발할 계획이라면, Active Record는 반드시 익혀야 할 핵심 기술이다!
|
||||||
190
docs/09_테스트와 품질 관리.md
Normal file
190
docs/09_테스트와 품질 관리.md
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
# **Ruby에서 테스트와 품질 관리**
|
||||||
|
|
||||||
|
소프트웨어 개발에서 **테스트와 품질 관리**는 필수적인 과정이다. 테스트를 수행하면 코드가 정상적으로 동작하는지 확인할 수 있으며, 이후 유지보수 시 발생할 수 있는 문제를 줄일 수 있다. Ruby에서는 다양한 **테스트 프레임워크와 도구**를 활용해 자동화된 테스트를 수행하고 코드 품질을 관리할 수 있다.
|
||||||
|
|
||||||
|
이 글에서는 **Ruby의 테스트 개념, 주요 테스트 프레임워크, 테스트 코드 작성 방법, 품질 관리 도구**를 설명한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **1. 테스트의 중요성**
|
||||||
|
|
||||||
|
테스트를 작성하는 것은 단순히 "버그를 찾기 위해" 하는 일이 아니다.
|
||||||
|
|
||||||
|
### **1.1. 테스트의 목적**
|
||||||
|
- **코드 안정성 확보**: 변경 사항이 기존 기능을 망가뜨리지 않도록 보장
|
||||||
|
- **디버깅 시간 단축**: 오류를 빠르게 발견하여 수정
|
||||||
|
- **유지보수 용이**: 코드가 오래되더라도 안전하게 개선 가능
|
||||||
|
- **자동화된 검증**: 반복적인 수작업 검증을 줄이고 효율적인 개발 가능
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **2. Ruby에서 테스트 방법**
|
||||||
|
|
||||||
|
Ruby에서는 다양한 테스트 기법이 사용된다.
|
||||||
|
|
||||||
|
### **2.1. 주요 테스트 기법**
|
||||||
|
- **단위 테스트(Unit Test)**: 개별 함수나 메서드의 동작을 검증
|
||||||
|
- **통합 테스트(Integration Test)**: 여러 컴포넌트가 함께 동작하는지 확인
|
||||||
|
- **기능 테스트(Functional Test)**: 사용자의 시나리오를 따라가며 검증
|
||||||
|
- **성능 테스트(Performance Test)**: 애플리케이션의 응답 속도와 성능을 측정
|
||||||
|
|
||||||
|
### **2.2. Ruby에서 사용되는 주요 테스트 프레임워크**
|
||||||
|
| 프레임워크 | 특징 |
|
||||||
|
|------------|--------------------------|
|
||||||
|
| **Minitest** | Ruby에 기본 포함, 가볍고 빠름 |
|
||||||
|
| **RSpec** | 가독성이 높은 BDD 스타일의 테스트 |
|
||||||
|
| **Cucumber** | 자연어 기반 테스트 (Given-When-Then) |
|
||||||
|
| **Capybara** | 웹 애플리케이션 UI 테스트에 사용 |
|
||||||
|
|
||||||
|
이 글에서는 가장 많이 사용되는 **Minitest**와 **RSpec**을 중심으로 설명한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **3. Minitest: Ruby 기본 테스트 프레임워크**
|
||||||
|
|
||||||
|
`Minitest`는 Ruby에 기본 내장된 테스트 프레임워크로, 별도 설치 없이 사용할 수 있다.
|
||||||
|
|
||||||
|
### **3.1. Minitest로 테스트 작성하기**
|
||||||
|
|
||||||
|
파일: `test_example.rb`
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "minitest/autorun"
|
||||||
|
|
||||||
|
class TestExample < Minitest::Test
|
||||||
|
def test_addition
|
||||||
|
assert_equal 4, 2 + 2
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_subtraction
|
||||||
|
assert_equal 3, 5 - 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **실행 방법**
|
||||||
|
터미널에서 실행:
|
||||||
|
```sh
|
||||||
|
ruby test_example.rb
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **출력 예시**
|
||||||
|
```
|
||||||
|
Run options: --seed 12345
|
||||||
|
|
||||||
|
# Running:
|
||||||
|
|
||||||
|
..
|
||||||
|
|
||||||
|
Finished in 0.00123s
|
||||||
|
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
|
||||||
|
```
|
||||||
|
|
||||||
|
`..`은 테스트가 성공했다는 의미다.
|
||||||
|
|
||||||
|
### **3.2. 주요 Minitest 메서드**
|
||||||
|
| 메서드 | 설명 |
|
||||||
|
|--------|----------------------|
|
||||||
|
| `assert` | 조건이 `true`인지 확인 |
|
||||||
|
| `assert_equal(expected, actual)` | 기대값과 실제값 비교 |
|
||||||
|
| `assert_nil(value)` | 값이 `nil`인지 확인 |
|
||||||
|
| `assert_raises(Exception) { block }` | 특정 예외 발생 확인 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **4. RSpec: 가독성이 높은 테스트 프레임워크**
|
||||||
|
|
||||||
|
RSpec은 사람이 읽기 쉬운 **BDD(Behavior-Driven Development)** 스타일을 지원하는 테스트 프레임워크다.
|
||||||
|
|
||||||
|
### **4.1. RSpec 설치**
|
||||||
|
```sh
|
||||||
|
gem install rspec
|
||||||
|
```
|
||||||
|
|
||||||
|
### **4.2. RSpec 테스트 코드 작성**
|
||||||
|
|
||||||
|
파일: `spec/example_spec.rb`
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "rspec"
|
||||||
|
|
||||||
|
RSpec.describe "기본 연산" do
|
||||||
|
it "더하기 연산을 수행한다" do
|
||||||
|
expect(2 + 2).to eq(4)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "빼기 연산을 수행한다" do
|
||||||
|
expect(5 - 2).to eq(3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **실행 방법**
|
||||||
|
```sh
|
||||||
|
rspec spec/example_spec.rb
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **출력 예시**
|
||||||
|
```
|
||||||
|
..
|
||||||
|
|
||||||
|
Finished in 0.0023 seconds
|
||||||
|
2 examples, 0 failures
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **5. 테스트 주도 개발(TDD)과 행동 주도 개발(BDD)**
|
||||||
|
|
||||||
|
### **5.1. 테스트 주도 개발(TDD, Test-Driven Development)**
|
||||||
|
**TDD**는 코드 작성 전에 **테스트를 먼저 작성하는 방식**이다.
|
||||||
|
|
||||||
|
**TDD 주기**
|
||||||
|
1. **테스트 작성** (아직 구현되지 않은 기능에 대한 테스트)
|
||||||
|
2. **테스트 실행** (실패해야 정상)
|
||||||
|
3. **코드 작성** (테스트를 통과하도록 최소한의 코드 작성)
|
||||||
|
4. **리팩토링** (코드 개선 및 최적화)
|
||||||
|
|
||||||
|
### **5.2. 행동 주도 개발(BDD, Behavior-Driven Development)**
|
||||||
|
**BDD**는 TDD를 확장한 개념으로, 테스트를 **사람이 읽기 쉬운 형태**로 작성한다.
|
||||||
|
- RSpec의 `describe`, `it` 문법이 대표적
|
||||||
|
- Cucumber는 자연어(`Given`, `When`, `Then`) 기반 테스트 제공
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **6. 품질 관리 도구**
|
||||||
|
|
||||||
|
Ruby에서는 테스트뿐만 아니라 **코드 품질을 관리하는 도구**도 많이 사용된다.
|
||||||
|
|
||||||
|
| 도구 | 설명 |
|
||||||
|
|------|-----------------------------|
|
||||||
|
| **Rubocop** | 코드 스타일 검사 및 자동 수정 |
|
||||||
|
| **SimpleCov** | 코드 커버리지 분석 |
|
||||||
|
| **Brakeman** | 보안 취약점 검사 |
|
||||||
|
|
||||||
|
### **6.1. Rubocop: 코드 스타일 검사**
|
||||||
|
|
||||||
|
설치 및 실행:
|
||||||
|
```sh
|
||||||
|
gem install rubocop
|
||||||
|
rubocop example.rb
|
||||||
|
```
|
||||||
|
|
||||||
|
자동 수정 적용:
|
||||||
|
```sh
|
||||||
|
rubocop -A
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **7. 정리**
|
||||||
|
|
||||||
|
| 주제 | 설명 |
|
||||||
|
|------|----------------------------------|
|
||||||
|
| **테스트 프레임워크** | Minitest, RSpec, Cucumber |
|
||||||
|
| **테스트 기법** | 단위 테스트, 통합 테스트, 기능 테스트 |
|
||||||
|
| **TDD** | 테스트를 먼저 작성한 후 코드 구현 |
|
||||||
|
| **BDD** | 사람이 읽기 쉬운 테스트 작성 |
|
||||||
|
| **품질 관리 도구** | Rubocop(스타일 검사), SimpleCov(커버리지), Brakeman(보안) |
|
||||||
|
|
||||||
|
Ruby에서 테스트와 품질 관리를 잘 수행하면 **버그를 사전에 예방하고, 유지보수가 쉬운 코드를 작성할 수 있다.** TDD와 BDD를 적극 활용하면 코드의 신뢰성을 높이고 개발 효율성을 극대화할 수 있다.
|
||||||
207
docs/10_웹 개발.md
Normal file
207
docs/10_웹 개발.md
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
# **Ruby를 활용한 웹 개발**
|
||||||
|
|
||||||
|
Ruby는 웹 개발에 최적화된 언어 중 하나로, 강력한 웹 프레임워크인 **Ruby on Rails(Rails)**를 중심으로 많은 웹 애플리케이션이 개발되고 있다. 또한, Sinatra 같은 경량 웹 프레임워크도 있어 다양한 방식으로 웹 애플리케이션을 개발할 수 있다.
|
||||||
|
|
||||||
|
이 글에서는 **Ruby 웹 개발의 개요, 주요 프레임워크, 기본적인 웹 애플리케이션 개발 방법**을 설명한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **1. Ruby로 웹 개발을 하는 이유**
|
||||||
|
|
||||||
|
Ruby는 **간결하고 직관적인 문법**을 가지고 있어 생산성이 높은 언어다. 특히 **Ruby on Rails** 프레임워크를 활용하면 **빠르게 웹 애플리케이션을 개발**할 수 있다.
|
||||||
|
|
||||||
|
### **1.1. Ruby 웹 개발의 장점**
|
||||||
|
- **생산성이 높음**: 코드가 간결하여 개발 속도가 빠름
|
||||||
|
- **웹 프레임워크가 강력함**: Rails, Sinatra 등 다양한 프레임워크 제공
|
||||||
|
- **테스트 및 품질 관리가 쉬움**: RSpec, Capybara 등을 활용한 자동화 테스트 지원
|
||||||
|
- **커뮤니티 지원이 풍부함**: 많은 오픈소스 프로젝트와 패키지(gem) 제공
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **2. Ruby 웹 프레임워크 종류**
|
||||||
|
|
||||||
|
Ruby에는 여러 웹 프레임워크가 있지만, 가장 대표적인 두 가지는 다음과 같다.
|
||||||
|
|
||||||
|
| 웹 프레임워크 | 특징 |
|
||||||
|
|--------------|------------------------------------|
|
||||||
|
| **Ruby on Rails** | MVC 패턴 기반의 강력한 풀스택 프레임워크 |
|
||||||
|
| **Sinatra** | 가볍고 심플한 마이크로 프레임워크 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **3. Ruby on Rails 개요 및 기본 사용법**
|
||||||
|
|
||||||
|
### **3.1. Ruby on Rails란?**
|
||||||
|
**Rails**는 Ruby 언어로 만들어진 풀스택 웹 프레임워크로, **MVC(Model-View-Controller) 아키텍처**를 기반으로 한다.
|
||||||
|
|
||||||
|
**Rails의 특징**
|
||||||
|
- **Convention over Configuration (설정보다 관례)**: 기본 설정을 제공하여 개발자가 설정할 사항을 최소화
|
||||||
|
- **DRY (Don't Repeat Yourself, 중복 코드 최소화)**: 재사용성이 높은 코드를 지향
|
||||||
|
- **Active Record ORM**: 데이터베이스 연동이 쉬움
|
||||||
|
|
||||||
|
### **3.2. Rails 설치 및 프로젝트 생성**
|
||||||
|
|
||||||
|
#### **(1) Rails 설치**
|
||||||
|
Ruby와 Bundler가 설치되어 있어야 한다.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gem install rails
|
||||||
|
```
|
||||||
|
|
||||||
|
설치가 완료되면 Rails 버전을 확인할 수 있다.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
rails -v
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(2) 새로운 Rails 프로젝트 생성**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
rails new myapp
|
||||||
|
cd myapp
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(3) 서버 실행**
|
||||||
|
```sh
|
||||||
|
rails server
|
||||||
|
```
|
||||||
|
|
||||||
|
이제 브라우저에서 `http://localhost:3000`에 접속하면 Rails 기본 화면을 볼 수 있다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **4. Rails의 MVC 구조**
|
||||||
|
|
||||||
|
Rails는 **MVC 패턴**을 기반으로 동작한다.
|
||||||
|
|
||||||
|
| 컴포넌트 | 설명 |
|
||||||
|
|----------|-------------------------------|
|
||||||
|
| **Model** | 데이터 및 비즈니스 로직 담당 (Active Record) |
|
||||||
|
| **View** | 사용자에게 보여지는 화면 (HTML, ERB, JavaScript) |
|
||||||
|
| **Controller** | 사용자 요청을 처리하고 Model과 View를 연결 |
|
||||||
|
|
||||||
|
### **4.1. 컨트롤러 생성 및 라우팅 설정**
|
||||||
|
|
||||||
|
#### **(1) 컨트롤러 생성**
|
||||||
|
```sh
|
||||||
|
rails generate controller Home index
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(2) 라우팅 설정** (`config/routes.rb`)
|
||||||
|
```ruby
|
||||||
|
Rails.application.routes.draw do
|
||||||
|
root "home#index"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(3) View 수정** (`app/views/home/index.html.erb`)
|
||||||
|
```html
|
||||||
|
<h1>환영합니다! Ruby on Rails 웹사이트입니다.</h1>
|
||||||
|
```
|
||||||
|
|
||||||
|
서버를 실행하고 `http://localhost:3000`에 접속하면 해당 화면이 보인다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **5. Sinatra를 활용한 경량 웹 개발**
|
||||||
|
|
||||||
|
Rails가 큰 프로젝트에 적합하다면, **Sinatra**는 간단한 웹 애플리케이션을 만들기에 적합하다.
|
||||||
|
|
||||||
|
### **5.1. Sinatra 설치**
|
||||||
|
```sh
|
||||||
|
gem install sinatra
|
||||||
|
```
|
||||||
|
|
||||||
|
### **5.2. 기본 Sinatra 웹 애플리케이션**
|
||||||
|
|
||||||
|
파일: `app.rb`
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "sinatra"
|
||||||
|
|
||||||
|
get "/" do
|
||||||
|
"Hello, world!"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### **5.3. 실행 방법**
|
||||||
|
```sh
|
||||||
|
ruby app.rb
|
||||||
|
```
|
||||||
|
|
||||||
|
브라우저에서 `http://localhost:4567`에 접속하면 `"Hello, world!"`가 출력된다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **6. 데이터베이스 연동**
|
||||||
|
|
||||||
|
웹 애플리케이션에서 데이터 저장이 필요할 경우, **Active Record**(Rails의 ORM)를 활용하면 쉽게 데이터베이스를 다룰 수 있다.
|
||||||
|
|
||||||
|
### **6.1. 데이터베이스 설정 (SQLite3 사용)**
|
||||||
|
|
||||||
|
Rails 프로젝트에서 `config/database.yml`을 수정하여 사용할 데이터베이스를 지정할 수 있다. 기본적으로 SQLite3이 설정되어 있다.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
default: &default
|
||||||
|
adapter: sqlite3
|
||||||
|
pool: 5
|
||||||
|
timeout: 5000
|
||||||
|
```
|
||||||
|
|
||||||
|
### **6.2. 모델 생성 및 마이그레이션**
|
||||||
|
|
||||||
|
#### **(1) User 모델 생성**
|
||||||
|
```sh
|
||||||
|
rails generate model User name:string email:string
|
||||||
|
rails db:migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(2) 데이터 삽입 및 조회** (`rails console`)
|
||||||
|
```ruby
|
||||||
|
User.create(name: "홍길동", email: "hong@example.com")
|
||||||
|
|
||||||
|
users = User.all
|
||||||
|
puts users.inspect
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **7. 웹 애플리케이션 배포**
|
||||||
|
|
||||||
|
### **7.1. Heroku를 이용한 배포**
|
||||||
|
|
||||||
|
Heroku는 Ruby on Rails 애플리케이션을 쉽게 배포할 수 있는 PaaS(Platform as a Service)이다.
|
||||||
|
|
||||||
|
#### **(1) Heroku CLI 설치 및 로그인**
|
||||||
|
```sh
|
||||||
|
heroku login
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(2) Git 초기화 및 Heroku 앱 생성**
|
||||||
|
```sh
|
||||||
|
git init
|
||||||
|
git add .
|
||||||
|
git commit -m "Initial commit"
|
||||||
|
heroku create
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(3) 애플리케이션 배포**
|
||||||
|
```sh
|
||||||
|
git push heroku main
|
||||||
|
heroku open
|
||||||
|
```
|
||||||
|
|
||||||
|
이제 배포된 웹사이트를 브라우저에서 확인할 수 있다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **8. 정리**
|
||||||
|
|
||||||
|
| 주제 | 설명 |
|
||||||
|
|------|------------------------------|
|
||||||
|
| **Rails** | MVC 아키텍처 기반의 풀스택 웹 프레임워크 |
|
||||||
|
| **Sinatra** | 간단한 웹 애플리케이션을 위한 경량 프레임워크 |
|
||||||
|
| **Active Record** | ORM(Object-Relational Mapping) 방식으로 DB 연동 |
|
||||||
|
| **Heroku 배포** | 간단한 명령어로 Rails 애플리케이션 배포 |
|
||||||
|
|
||||||
|
Ruby를 활용한 웹 개발은 **빠른 개발 속도, 강력한 프레임워크, 간결한 문법** 덕분에 생산성이 높다. **Rails와 Sinatra** 중 프로젝트에 맞는 프레임워크를 선택하여 효율적으로 웹 애플리케이션을 개발할 수 있다.
|
||||||
224
docs/11_애플리케이션 배포와 운영.md
Normal file
224
docs/11_애플리케이션 배포와 운영.md
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
# **Ruby 애플리케이션 배포와 운영**
|
||||||
|
|
||||||
|
Ruby 애플리케이션을 개발한 후에는 **배포**와 **운영**이 중요하다. 배포 환경을 잘 설정하고 운영을 효율적으로 관리하면 애플리케이션의 성능과 안정성이 보장된다.
|
||||||
|
|
||||||
|
이 글에서는 **Ruby 애플리케이션 배포 방법**, **운영 중 고려해야 할 요소**, **자동화 및 모니터링 전략** 등을 설명한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **1. 배포란 무엇인가?**
|
||||||
|
|
||||||
|
배포(Deployment)는 **개발된 애플리케이션을 서버에 올려 실제 사용자들이 사용할 수 있도록 하는 과정**이다. 배포 환경에 따라 성능과 유지보수의 편의성이 달라질 수 있다.
|
||||||
|
|
||||||
|
배포 방식에는 여러 가지가 있다.
|
||||||
|
|
||||||
|
| 배포 방식 | 설명 |
|
||||||
|
|----------|--------------------------------|
|
||||||
|
| **PaaS 배포** | Heroku, Render 같은 클라우드 서비스를 활용한 간편 배포 |
|
||||||
|
| **VPS 배포** | AWS, Linode, DigitalOcean 같은 서버에 직접 배포 |
|
||||||
|
| **Docker 배포** | 컨테이너 기술을 활용한 배포 |
|
||||||
|
| **Kubernetes 배포** | 대규모 애플리케이션을 위한 컨테이너 오케스트레이션 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **2. Ruby 애플리케이션 배포 방법**
|
||||||
|
|
||||||
|
### **2.1. Heroku를 이용한 간단한 배포**
|
||||||
|
|
||||||
|
Heroku는 Ruby 애플리케이션을 빠르게 배포할 수 있는 PaaS 플랫폼이다.
|
||||||
|
|
||||||
|
#### **(1) Heroku CLI 설치 및 로그인**
|
||||||
|
```sh
|
||||||
|
heroku login
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(2) Git 저장소 초기화 및 커밋**
|
||||||
|
```sh
|
||||||
|
git init
|
||||||
|
git add .
|
||||||
|
git commit -m "Initial commit"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(3) Heroku 애플리케이션 생성**
|
||||||
|
```sh
|
||||||
|
heroku create my-ruby-app
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(4) 배포 실행**
|
||||||
|
```sh
|
||||||
|
git push heroku main
|
||||||
|
heroku open
|
||||||
|
```
|
||||||
|
|
||||||
|
이제 Heroku에서 애플리케이션을 실행할 수 있다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2.2. VPS에 배포 (예: AWS, DigitalOcean)**
|
||||||
|
|
||||||
|
VPS(가상 사설 서버)에서 Ruby 애플리케이션을 배포하려면 **Linux 서버 환경 설정**이 필요하다.
|
||||||
|
|
||||||
|
#### **(1) 서버 접속**
|
||||||
|
```sh
|
||||||
|
ssh user@your-server-ip
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(2) 필수 패키지 설치**
|
||||||
|
```sh
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y ruby ruby-dev build-essential
|
||||||
|
sudo apt install -y nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(3) 애플리케이션 배포 및 실행**
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/your-repo.git
|
||||||
|
cd your-repo
|
||||||
|
bundle install
|
||||||
|
rails db:migrate
|
||||||
|
rails server -d
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(4) Nginx 설정 (Reverse Proxy 설정)**
|
||||||
|
`/etc/nginx/sites-available/default` 파일을 열고 다음 내용을 추가한다.
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name your-domain.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:3000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(5) Nginx 재시작**
|
||||||
|
```sh
|
||||||
|
sudo systemctl restart nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
이제 브라우저에서 `http://your-domain.com`으로 접속하면 애플리케이션이 실행된다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2.3. Docker를 활용한 배포**
|
||||||
|
|
||||||
|
Docker를 사용하면 Ruby 애플리케이션을 컨테이너로 감싸 어디서든 실행할 수 있다.
|
||||||
|
|
||||||
|
#### **(1) `Dockerfile` 생성**
|
||||||
|
```dockerfile
|
||||||
|
FROM ruby:3.2
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . .
|
||||||
|
RUN bundle install
|
||||||
|
CMD ["rails", "server", "-b", "0.0.0.0"]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(2) Docker 이미지 빌드 및 실행**
|
||||||
|
```sh
|
||||||
|
docker build -t my-ruby-app .
|
||||||
|
docker run -p 3000:3000 my-ruby-app
|
||||||
|
```
|
||||||
|
|
||||||
|
이제 `http://localhost:3000`에서 애플리케이션을 확인할 수 있다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **3. 운영 및 유지보수 전략**
|
||||||
|
|
||||||
|
배포한 애플리케이션이 안정적으로 동작하려면 운영 및 유지보수가 중요하다.
|
||||||
|
|
||||||
|
### **3.1. 애플리케이션 모니터링**
|
||||||
|
|
||||||
|
서버 상태를 모니터링하고 성능 문제를 파악하기 위해 다음과 같은 도구를 사용할 수 있다.
|
||||||
|
|
||||||
|
| 도구 | 설명 |
|
||||||
|
|------|--------------------------------|
|
||||||
|
| **New Relic** | 성능 모니터링 및 에러 추적 |
|
||||||
|
| **Datadog** | 서버 및 애플리케이션 모니터링 |
|
||||||
|
| **Prometheus + Grafana** | 메트릭 수집 및 시각화 |
|
||||||
|
| **Logstash + Kibana** | 로그 분석 및 검색 |
|
||||||
|
|
||||||
|
예를 들어, `top` 명령어로 서버 상태를 확인할 수 있다.
|
||||||
|
```sh
|
||||||
|
top
|
||||||
|
```
|
||||||
|
|
||||||
|
로그 파일을 확인하여 오류를 분석할 수도 있다.
|
||||||
|
```sh
|
||||||
|
tail -f log/production.log
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3.2. 자동화 배포 (CI/CD 적용)**
|
||||||
|
|
||||||
|
CI/CD(Continuous Integration/Continuous Deployment)를 설정하면 **배포 자동화**가 가능하다.
|
||||||
|
|
||||||
|
GitHub Actions를 사용한 예제:
|
||||||
|
|
||||||
|
`.github/workflows/deploy.yml`
|
||||||
|
```yaml
|
||||||
|
name: Deploy Ruby App
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install Ruby and Bundler
|
||||||
|
run: |
|
||||||
|
sudo apt-get install -y ruby bundler
|
||||||
|
- name: Install dependencies
|
||||||
|
run: bundle install
|
||||||
|
- name: Deploy to Server
|
||||||
|
run: |
|
||||||
|
ssh user@your-server-ip "cd /app && git pull && bundle install && rails db:migrate && sudo systemctl restart your-app"
|
||||||
|
```
|
||||||
|
|
||||||
|
이제 `git push` 하면 자동으로 배포가 이루어진다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3.3. 보안 및 유지보수**
|
||||||
|
|
||||||
|
운영 중인 애플리케이션은 보안에도 신경 써야 한다.
|
||||||
|
|
||||||
|
#### **(1) SSL 인증서 적용 (Let's Encrypt)**
|
||||||
|
```sh
|
||||||
|
sudo apt install certbot python3-certbot-nginx
|
||||||
|
sudo certbot --nginx -d your-domain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(2) 정기적인 업데이트**
|
||||||
|
Ruby와 라이브러리는 보안 패치를 적용해야 한다.
|
||||||
|
```sh
|
||||||
|
gem update --system
|
||||||
|
bundle update
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **(3) 백업 전략**
|
||||||
|
데이터 손실을 방지하기 위해 정기적인 백업이 필요하다.
|
||||||
|
```sh
|
||||||
|
pg_dump -U postgres -h localhost mydatabase > backup.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **4. 결론**
|
||||||
|
|
||||||
|
Ruby 애플리케이션을 배포하고 운영하는 과정은 **서버 설정, 성능 모니터링, 자동화, 보안 관리** 등 여러 요소를 포함한다.
|
||||||
|
|
||||||
|
| 주제 | 핵심 내용 |
|
||||||
|
|------|---------------------------------|
|
||||||
|
| **배포 방법** | Heroku, VPS, Docker를 활용한 배포 |
|
||||||
|
| **운영 전략** | 모니터링, 자동화 배포 (CI/CD) |
|
||||||
|
| **보안 관리** | SSL 적용, 업데이트, 백업 |
|
||||||
|
|
||||||
|
효율적인 배포 및 운영 전략을 수립하면 Ruby 애플리케이션을 안정적으로 서비스할 수 있다.
|
||||||
211
docs/12_최적화 및 메타프로그래밍.md
Normal file
211
docs/12_최적화 및 메타프로그래밍.md
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
# **Ruby 최적화 및 메타프로그래밍**
|
||||||
|
|
||||||
|
Ruby는 강력한 동적 언어로서 **코드를 간결하게 유지하면서도 유연한 프로그래밍이 가능**하다. 하지만 동적 특성으로 인해 성능이 저하될 수 있으며, 이를 해결하기 위한 최적화 기법이 필요하다.
|
||||||
|
|
||||||
|
또한, Ruby는 **메타프로그래밍**을 통해 코드를 동적으로 생성하고 수정할 수 있는 강력한 기능을 제공한다. 이 글에서는 **Ruby 성능 최적화 방법**과 **메타프로그래밍 활용법**을 정리한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **1. Ruby 성능 최적화**
|
||||||
|
|
||||||
|
Ruby는 생산성이 높은 언어지만 속도는 C나 Java보다 느릴 수 있다. 따라서 Ruby 코드의 성능을 최적화하는 것이 중요하다.
|
||||||
|
|
||||||
|
### **1.1. 불필요한 객체 생성을 줄이기**
|
||||||
|
|
||||||
|
Ruby에서는 **모든 것이 객체**이므로, 불필요한 객체 생성을 피하는 것이 중요하다.
|
||||||
|
|
||||||
|
#### **(1) 문자열 객체 재사용**
|
||||||
|
`String` 객체를 반복 생성하면 메모리를 낭비할 수 있다.
|
||||||
|
|
||||||
|
**비효율적인 코드:**
|
||||||
|
```ruby
|
||||||
|
100_000.times do
|
||||||
|
str = "Hello" # 새로운 String 객체 생성
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
**효율적인 코드:**
|
||||||
|
```ruby
|
||||||
|
100_000.times do
|
||||||
|
str = "Hello".freeze # 동일 객체 재사용
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
`.freeze`를 사용하면 객체가 변경되지 않도록 고정되어 **메모리 사용량을 줄일 수 있다.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **1.2. `each` 대신 `map`과 `reduce` 활용**
|
||||||
|
|
||||||
|
반복문(`each`)을 사용하면 불필요한 루프가 발생할 수 있다. `map`과 `reduce`를 사용하면 코드의 가독성이 향상되고 성능이 개선된다.
|
||||||
|
|
||||||
|
**비효율적인 코드:**
|
||||||
|
```ruby
|
||||||
|
result = []
|
||||||
|
[1, 2, 3, 4, 5].each do |num|
|
||||||
|
result << num * 2
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
**효율적인 코드:**
|
||||||
|
```ruby
|
||||||
|
result = [1, 2, 3, 4, 5].map { |num| num * 2 }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **1.3. `symbol`과 `hash` 활용**
|
||||||
|
|
||||||
|
Ruby에서 `Symbol`은 `String`보다 가볍고 성능이 좋다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# String 기반 키 사용 (비효율적)
|
||||||
|
hash = { "name" => "Alice", "age" => 25 }
|
||||||
|
|
||||||
|
# Symbol 기반 키 사용 (효율적)
|
||||||
|
hash = { name: "Alice", age: 25 }
|
||||||
|
```
|
||||||
|
|
||||||
|
**`Symbol`은 불변 객체이므로, 동일한 값이 여러 번 생성되지 않아 성능이 향상된다.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **1.4. `lazy`를 활용한 지연 평가**
|
||||||
|
|
||||||
|
`lazy`를 사용하면 **모든 데이터를 한 번에 로드하지 않고, 필요한 만큼만 계산**할 수 있다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
numbers = (1..Float::INFINITY).lazy.map { |n| n * 2 }
|
||||||
|
puts numbers.first(5) # [2, 4, 6, 8, 10]만 생성됨
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **1.5. 메모이제이션(Memoization) 활용**
|
||||||
|
|
||||||
|
반복적으로 계산해야 하는 값은 **한 번만 계산하고 저장**하는 것이 좋다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def slow_method
|
||||||
|
@result ||= expensive_computation
|
||||||
|
end
|
||||||
|
|
||||||
|
def expensive_computation
|
||||||
|
sleep(2)
|
||||||
|
"Computed!"
|
||||||
|
end
|
||||||
|
|
||||||
|
puts slow_method # 첫 실행은 2초 대기
|
||||||
|
puts slow_method # 두 번째 실행은 즉시 반환
|
||||||
|
```
|
||||||
|
|
||||||
|
`@result ||= expensive_computation`을 사용하면 **한 번만 계산하고 이후에는 캐시된 값을 반환**한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **2. 메타프로그래밍**
|
||||||
|
|
||||||
|
메타프로그래밍이란 **코드를 실행 중에 변경하거나 새로운 메서드를 동적으로 정의하는 기법**이다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2.1. `define_method`를 활용한 동적 메서드 생성**
|
||||||
|
|
||||||
|
`define_method`를 사용하면 **반복적인 메서드 정의를 줄이고 코드의 유연성을 높일 수 있다.**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class User
|
||||||
|
[:name, :age, :email].each do |attribute|
|
||||||
|
define_method(attribute) do
|
||||||
|
instance_variable_get("@#{attribute}")
|
||||||
|
end
|
||||||
|
|
||||||
|
define_method("#{attribute}=") do |value|
|
||||||
|
instance_variable_set("@#{attribute}", value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
user = User.new
|
||||||
|
user.name = "Alice"
|
||||||
|
puts user.name # Alice
|
||||||
|
```
|
||||||
|
|
||||||
|
이렇게 하면 **setter/getter 메서드를 자동으로 생성**할 수 있다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2.2. `method_missing`을 활용한 동적 메서드 처리**
|
||||||
|
|
||||||
|
정의되지 않은 메서드가 호출될 때 `method_missing`을 활용하면 유연한 처리가 가능하다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class DynamicMethod
|
||||||
|
def method_missing(name, *args)
|
||||||
|
puts "#{name} 메서드가 호출됨 (args: #{args})"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
obj = DynamicMethod.new
|
||||||
|
obj.hello(1, 2, 3) # hello 메서드가 호출됨 (args: [1, 2, 3])
|
||||||
|
```
|
||||||
|
|
||||||
|
`method_missing`을 이용하면 **일일이 메서드를 정의하지 않고도 유연하게 동작을 처리할 수 있다.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2.3. `class_eval`과 `instance_eval`을 활용한 클래스 동적 수정**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Person
|
||||||
|
end
|
||||||
|
|
||||||
|
Person.class_eval do
|
||||||
|
def greet
|
||||||
|
"Hello!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts Person.new.greet # Hello!
|
||||||
|
```
|
||||||
|
|
||||||
|
`class_eval`을 사용하면 **기존 클래스에 동적으로 메서드를 추가할 수 있다.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2.4. `self.included`을 활용한 모듈 자동 확장**
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
module AutoMethods
|
||||||
|
def self.included(base)
|
||||||
|
base.extend ClassMethods
|
||||||
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
def say_hello
|
||||||
|
"Hello from #{self}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class MyClass
|
||||||
|
include AutoMethods
|
||||||
|
end
|
||||||
|
|
||||||
|
puts MyClass.say_hello # Hello from MyClass
|
||||||
|
```
|
||||||
|
|
||||||
|
모듈을 `include`하면 자동으로 클래스 메서드가 추가되도록 설정할 수 있다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## **3. 결론**
|
||||||
|
|
||||||
|
Ruby는 **동적인 특성**을 활용하여 성능 최적화와 메타프로그래밍이 가능하다.
|
||||||
|
|
||||||
|
| 주제 | 주요 내용 |
|
||||||
|
|------|---------------------------------|
|
||||||
|
| **최적화** | 객체 생성을 줄이고, `map`, `symbol`, `lazy` 등을 활용 |
|
||||||
|
| **메타프로그래밍** | `define_method`, `method_missing`, `class_eval`을 활용한 동적 코드 작성 |
|
||||||
|
|
||||||
|
**최적화를 통해 성능을 개선하고, 메타프로그래밍을 활용하여 유지보수가 쉬운 코드를 작성하는 것이 핵심이다.**
|
||||||
66
docs/21_웹 크롤러.md
Normal file
66
docs/21_웹 크롤러.md
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
Ruby에서 간단한 **웹 크롤러**를 작성하려면 `nokogiri`와 `open-uri` 라이브러리를 사용할 수 있다.
|
||||||
|
|
||||||
|
### **1. 사전 준비**
|
||||||
|
웹 크롤링을 위해 `nokogiri`를 설치해야 한다.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gem install nokogiri
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2. 간단한 웹 크롤러 예제**
|
||||||
|
다음은 특정 웹사이트에서 제목을 가져오는 간단한 크롤러이다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require 'nokogiri'
|
||||||
|
require 'open-uri'
|
||||||
|
|
||||||
|
# 크롤링할 웹페이지 URL
|
||||||
|
url = "https://news.ycombinator.com/"
|
||||||
|
|
||||||
|
# 페이지 가져오기
|
||||||
|
html = URI.open(url)
|
||||||
|
doc = Nokogiri::HTML(html)
|
||||||
|
|
||||||
|
# 뉴스 제목 가져오기
|
||||||
|
doc.css('.titleline a').each_with_index do |title, index|
|
||||||
|
puts "#{index + 1}. #{title.text}"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3. 코드 설명**
|
||||||
|
1. **라이브러리 로드**
|
||||||
|
- `nokogiri` : HTML을 파싱하는 라이브러리
|
||||||
|
- `open-uri` : 웹페이지 내용을 가져오는 라이브러리
|
||||||
|
|
||||||
|
2. **웹페이지 가져오기**
|
||||||
|
```ruby
|
||||||
|
html = URI.open(url)
|
||||||
|
doc = Nokogiri::HTML(html)
|
||||||
|
```
|
||||||
|
- `URI.open(url)` : 해당 URL의 HTML을 가져온다.
|
||||||
|
- `Nokogiri::HTML(html)` : HTML을 파싱하여 문서 객체를 생성한다.
|
||||||
|
|
||||||
|
3. **데이터 추출**
|
||||||
|
```ruby
|
||||||
|
doc.css('.titleline a').each_with_index do |title, index|
|
||||||
|
puts "#{index + 1}. #{title.text}"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
- `.css('.titleline a')` : CSS 선택자로 제목을 선택한다.
|
||||||
|
- `.each_with_index` : 제목을 하나씩 출력한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **4. 실행 결과 예시**
|
||||||
|
```sh
|
||||||
|
1. OpenAI releases GPT-4.5
|
||||||
|
2. Ruby 4.0 announced
|
||||||
|
3. NASA discovers new exoplanet
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
이제 Ruby를 사용하여 원하는 웹페이지의 데이터를 쉽게 크롤링할 수 있다.
|
||||||
97
docs/22_CLI(Command Line Interface) 툴.md
Normal file
97
docs/22_CLI(Command Line Interface) 툴.md
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
## **Ruby CLI(Command Line Interface) 툴 예제**
|
||||||
|
|
||||||
|
Ruby로 간단한 **CLI(Command Line Interface) 툴**을 만들어보자. 이 예제에서는 사용자가 입력한 도시의 **현재 날씨를 출력하는 CLI 프로그램**을 작성한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **1. 사전 준비**
|
||||||
|
|
||||||
|
이 프로젝트에서는 `httparty` 라이브러리를 사용하여 **API 요청**을 보낼 것이다. 먼저 라이브러리를 설치하자.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gem install httparty
|
||||||
|
```
|
||||||
|
|
||||||
|
그리고 **무료 날씨 API**인 [OpenWeatherMap](https://openweathermap.org/)에서 API 키를 발급받아야 한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2. CLI 툴 코드**
|
||||||
|
|
||||||
|
`weather_cli.rb` 파일을 생성하고 다음 코드를 작성한다.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'httparty'
|
||||||
|
require 'json'
|
||||||
|
|
||||||
|
API_KEY = "YOUR_OPENWEATHERMAP_API_KEY" # 여기에 API 키 입력
|
||||||
|
BASE_URL = "https://api.openweathermap.org/data/2.5/weather"
|
||||||
|
|
||||||
|
def fetch_weather(city)
|
||||||
|
url = "#{BASE_URL}?q=#{city}&appid=#{API_KEY}&units=metric"
|
||||||
|
response = HTTParty.get(url)
|
||||||
|
|
||||||
|
if response.code == 200
|
||||||
|
data = JSON.parse(response.body)
|
||||||
|
temperature = data["main"]["temp"]
|
||||||
|
description = data["weather"].first["description"]
|
||||||
|
puts "🌤️ #{city}의 현재 기온: #{temperature}°C (#{description})"
|
||||||
|
else
|
||||||
|
puts "⚠️ 도시 정보를 가져오지 못했습니다. 도시 이름을 확인하세요!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if ARGV.empty?
|
||||||
|
puts "사용법: ruby weather_cli.rb <도시명>"
|
||||||
|
else
|
||||||
|
city = ARGV.join(" ")
|
||||||
|
fetch_weather(city)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3. 코드 설명**
|
||||||
|
|
||||||
|
1. **라이브러리 로드**
|
||||||
|
- `httparty` : API 요청을 보낼 때 사용
|
||||||
|
- `json` : JSON 응답을 파싱
|
||||||
|
|
||||||
|
2. **날씨 정보 가져오기 (`fetch_weather` 메서드)**
|
||||||
|
- `HTTParty.get(url)`을 사용하여 OpenWeatherMap API에 요청을 보낸다.
|
||||||
|
- 응답이 정상(`code == 200`)이면 JSON 데이터를 파싱하고 온도 및 날씨 정보를 출력한다.
|
||||||
|
- 오류가 발생하면 메시지를 출력한다.
|
||||||
|
|
||||||
|
3. **사용자 입력 처리 (`ARGV`)**
|
||||||
|
- 사용자가 도시명을 입력하면 `ARGV.join(" ")`으로 받아서 API 요청을 보낸다.
|
||||||
|
- 입력이 없으면 사용법을 출력한다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **4. 실행 방법**
|
||||||
|
|
||||||
|
터미널에서 실행 권한을 부여하고 실행하면 된다.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
chmod +x weather_cli.rb
|
||||||
|
./weather_cli.rb Seoul
|
||||||
|
```
|
||||||
|
|
||||||
|
**출력 예시:**
|
||||||
|
```sh
|
||||||
|
🌤️ Seoul의 현재 기온: 15°C (clear sky)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **5. 확장 가능성**
|
||||||
|
|
||||||
|
이 CLI 툴은 간단하지만 다음과 같은 기능을 추가하여 확장할 수 있다.
|
||||||
|
|
||||||
|
✅ **다른 API 연동** (예: 뉴스, 주가, 환율 정보)
|
||||||
|
✅ **파일 입력/출력 지원** (예: 여러 도시의 날씨를 한 번에 조회)
|
||||||
|
✅ **사용자 옵션 추가** (`--unit metric` 같은 옵션 지원)
|
||||||
|
|
||||||
|
이제 Ruby로 CLI 프로그램을 쉽게 만들 수 있다!
|
||||||
170
docs/23_API 서버.md
Normal file
170
docs/23_API 서버.md
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
## **Ruby API 서버 예제 (Sinatra 사용)**
|
||||||
|
|
||||||
|
Ruby로 간단한 **API 서버**를 만들기 위해 **Sinatra** 프레임워크를 사용할 것이다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **1. 사전 준비**
|
||||||
|
|
||||||
|
#### **Sinatra 설치**
|
||||||
|
Sinatra는 가볍고 사용하기 쉬운 웹 프레임워크이다. 먼저 Sinatra를 설치하자.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gem install sinatra
|
||||||
|
```
|
||||||
|
|
||||||
|
또는 `Gemfile`을 사용한다면 다음을 추가한 후 `bundle install`을 실행하자.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
gem 'sinatra'
|
||||||
|
gem 'json'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2. API 서버 코드**
|
||||||
|
|
||||||
|
`app.rb` 파일을 만들고 아래 코드를 작성하자.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require 'sinatra'
|
||||||
|
require 'json'
|
||||||
|
|
||||||
|
# 서버 기본 설정
|
||||||
|
set :port, 4567
|
||||||
|
set :bind, '0.0.0.0'
|
||||||
|
|
||||||
|
# 샘플 데이터 (가상의 사용자 목록)
|
||||||
|
users = [
|
||||||
|
{ id: 1, name: "Alice", age: 30 },
|
||||||
|
{ id: 2, name: "Bob", age: 25 },
|
||||||
|
{ id: 3, name: "Charlie", age: 35 }
|
||||||
|
]
|
||||||
|
|
||||||
|
# 1. 모든 사용자 조회 (GET /users)
|
||||||
|
get '/users' do
|
||||||
|
content_type :json
|
||||||
|
{ users: users }.to_json
|
||||||
|
end
|
||||||
|
|
||||||
|
# 2. 특정 사용자 조회 (GET /users/:id)
|
||||||
|
get '/users/:id' do
|
||||||
|
content_type :json
|
||||||
|
user = users.find { |u| u[:id] == params[:id].to_i }
|
||||||
|
if user
|
||||||
|
user.to_json
|
||||||
|
else
|
||||||
|
status 404
|
||||||
|
{ error: "User not found" }.to_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# 3. 사용자 추가 (POST /users)
|
||||||
|
post '/users' do
|
||||||
|
content_type :json
|
||||||
|
request_payload = JSON.parse(request.body.read) rescue {}
|
||||||
|
|
||||||
|
if request_payload["name"] && request_payload["age"]
|
||||||
|
new_user = {
|
||||||
|
id: users.size + 1,
|
||||||
|
name: request_payload["name"],
|
||||||
|
age: request_payload["age"]
|
||||||
|
}
|
||||||
|
users << new_user
|
||||||
|
status 201
|
||||||
|
new_user.to_json
|
||||||
|
else
|
||||||
|
status 400
|
||||||
|
{ error: "Invalid data" }.to_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# 4. 사용자 삭제 (DELETE /users/:id)
|
||||||
|
delete '/users/:id' do
|
||||||
|
content_type :json
|
||||||
|
user = users.find { |u| u[:id] == params[:id].to_i }
|
||||||
|
|
||||||
|
if user
|
||||||
|
users.delete(user)
|
||||||
|
{ message: "User deleted" }.to_json
|
||||||
|
else
|
||||||
|
status 404
|
||||||
|
{ error: "User not found" }.to_json
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3. 실행 방법**
|
||||||
|
|
||||||
|
터미널에서 다음 명령어를 실행하자.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ruby app.rb
|
||||||
|
```
|
||||||
|
|
||||||
|
서버가 `http://localhost:4567`에서 실행된다.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **4. API 테스트**
|
||||||
|
|
||||||
|
#### **모든 사용자 조회**
|
||||||
|
```sh
|
||||||
|
curl http://localhost:4567/users
|
||||||
|
```
|
||||||
|
**응답:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"users": [
|
||||||
|
{ "id": 1, "name": "Alice", "age": 30 },
|
||||||
|
{ "id": 2, "name": "Bob", "age": 25 },
|
||||||
|
{ "id": 3, "name": "Charlie", "age": 35 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### **특정 사용자 조회**
|
||||||
|
```sh
|
||||||
|
curl http://localhost:4567/users/1
|
||||||
|
```
|
||||||
|
**응답:**
|
||||||
|
```json
|
||||||
|
{ "id": 1, "name": "Alice", "age": 30 }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### **새로운 사용자 추가**
|
||||||
|
```sh
|
||||||
|
curl -X POST http://localhost:4567/users -H "Content-Type: application/json" -d '{"name": "David", "age": 40}'
|
||||||
|
```
|
||||||
|
**응답:**
|
||||||
|
```json
|
||||||
|
{ "id": 4, "name": "David", "age": 40 }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### **사용자 삭제**
|
||||||
|
```sh
|
||||||
|
curl -X DELETE http://localhost:4567/users/2
|
||||||
|
```
|
||||||
|
**응답:**
|
||||||
|
```json
|
||||||
|
{ "message": "User deleted" }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **5. 결론**
|
||||||
|
|
||||||
|
이제 Sinatra를 이용하여 간단한 RESTful API 서버를 만들 수 있다.
|
||||||
|
✅ **GET, POST, DELETE 요청 처리**
|
||||||
|
✅ **JSON 데이터 반환**
|
||||||
|
✅ **간단한 데이터 저장 및 관리**
|
||||||
|
|
||||||
|
Sinatra는 **가볍고 배우기 쉬운 프레임워크**이므로, 빠르게 API 서버를 구축할 때 유용하다!
|
||||||
103
docs/31_유용한 라이브러리 정리.md
Normal file
103
docs/31_유용한 라이브러리 정리.md
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
## **Ruby에서 유용한 라이브러리 정리**
|
||||||
|
|
||||||
|
Ruby 개발을 할 때 자주 사용하는 유용한 라이브러리들을 **목적별로 정리**했다.
|
||||||
|
|
||||||
|
### **1. 웹 개발 및 API 서버**
|
||||||
|
| 라이브러리 | 설명 |
|
||||||
|
|------------|------------------------------------------------------------|
|
||||||
|
| **Sinatra** | 가벼운 웹 프레임워크로, 간단한 웹 애플리케이션 및 API 서버 구축에 적합 |
|
||||||
|
| **Rails** | MVC 패턴을 따르는 강력한 웹 프레임워크 (Ruby on Rails) |
|
||||||
|
| **Grape** | RESTful API 개발을 위한 경량 라이브러리 |
|
||||||
|
| **Rack** | 웹 애플리케이션과 웹 서버 간의 인터페이스를 제공하는 미들웨어 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **2. HTTP 요청 및 웹 크롤링**
|
||||||
|
| 라이브러리 | 설명 |
|
||||||
|
|------------|------------------------------------------------------------|
|
||||||
|
| **HTTParty** | REST API 요청을 간편하게 보낼 수 있는 라이브러리 |
|
||||||
|
| **Faraday** | HTTP 요청을 다루는 유연한 라이브러리, 다양한 어댑터 지원 |
|
||||||
|
| **Nokogiri** | HTML, XML 파싱 및 웹 크롤링을 위한 강력한 라이브러리 |
|
||||||
|
| **Mechanize** | 폼 제출, 링크 클릭 등 브라우저 자동화를 지원하는 웹 크롤링 라이브러리 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **3. 데이터베이스 및 ORM**
|
||||||
|
| 라이브러리 | 설명 |
|
||||||
|
|------------|------------------------------------------------------------|
|
||||||
|
| **ActiveRecord** | Rails에서 사용하는 ORM(Object-Relational Mapping) 라이브러리 |
|
||||||
|
| **Sequel** | 간결하고 강력한 Ruby용 ORM, ActiveRecord보다 가벼움 |
|
||||||
|
| **Redis** | Redis 데이터베이스와 상호작용하기 위한 클라이언트 라이브러리 |
|
||||||
|
| **Mongoid** | MongoDB와 연결할 때 사용하는 ORM 라이브러리 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **4. 테스트 및 품질 관리**
|
||||||
|
| 라이브러리 | 설명 |
|
||||||
|
|------------|------------------------------------------------------------|
|
||||||
|
| **RSpec** | Ruby에서 가장 널리 사용되는 BDD 기반 테스트 프레임워크 |
|
||||||
|
| **Minitest** | Ruby 표준 라이브러리에 포함된 가벼운 테스트 프레임워크 |
|
||||||
|
| **FactoryBot** | 테스트 데이터 생성을 쉽게 할 수 있도록 도와주는 라이브러리 |
|
||||||
|
| **Capybara** | 웹 애플리케이션의 통합 테스트를 위한 라이브러리 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **5. 파일 처리 및 데이터 포맷**
|
||||||
|
| 라이브러리 | 설명 |
|
||||||
|
|------------|------------------------------------------------------------|
|
||||||
|
| **CSV** | Ruby 표준 라이브러리, CSV 파일을 쉽게 다룰 수 있음 |
|
||||||
|
| **JSON** | Ruby 표준 라이브러리, JSON 데이터를 파싱하고 생성할 때 사용 |
|
||||||
|
| **YAML** | YAML 데이터를 파싱하고 저장하는 라이브러리 |
|
||||||
|
| **PStore** | Ruby에서 Key-Value 기반의 데이터 저장을 지원하는 라이브러리 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **6. CLI 도구 개발**
|
||||||
|
| 라이브러리 | 설명 |
|
||||||
|
|------------|------------------------------------------------------------|
|
||||||
|
| **Thor** | 강력한 CLI(Command Line Interface) 도구를 만들 때 유용 |
|
||||||
|
| **TTY** | 터미널에서 다양한 UI 요소(프로그레스 바, 테이블 등)를 만들 수 있음 |
|
||||||
|
| **Optparse** | Ruby 표준 라이브러리, CLI 옵션을 쉽게 파싱할 수 있음 |
|
||||||
|
| **HighLine** | 터미널 입력 및 출력을 쉽게 다룰 수 있도록 돕는 라이브러리 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **7. 네트워크 및 소켓 프로그래밍**
|
||||||
|
| 라이브러리 | 설명 |
|
||||||
|
|------------|------------------------------------------------------------|
|
||||||
|
| **Socket** | Ruby 표준 라이브러리, TCP/UDP 소켓 프로그래밍을 지원 |
|
||||||
|
| **Net::HTTP** | Ruby 표준 라이브러리, HTTP 요청을 보낼 때 사용 |
|
||||||
|
| **EventMachine** | 비동기 네트워크 프로그래밍을 위한 라이브러리 |
|
||||||
|
| **Celluloid** | 멀티스레딩 및 병렬 처리 지원을 위한 라이브러리 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **8. 메타프로그래밍 및 성능 최적화**
|
||||||
|
| 라이브러리 | 설명 |
|
||||||
|
|------------|------------------------------------------------------------|
|
||||||
|
| **Benchmark** | Ruby 표준 라이브러리, 코드 실행 시간을 측정할 때 사용 |
|
||||||
|
| **Profile** | 코드의 성능 병목을 분석할 때 사용 |
|
||||||
|
| **Concurrent-Ruby** | 병렬 및 동시 실행을 위한 다양한 기능 제공 |
|
||||||
|
| **Dry-Rb** | 함수형 프로그래밍 스타일을 적용할 수 있도록 도와주는 라이브러리 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **9. 기타 유용한 라이브러리**
|
||||||
|
| 라이브러리 | 설명 |
|
||||||
|
|------------|------------------------------------------------------------|
|
||||||
|
| **Faker** | 가짜 데이터(이름, 주소, 이메일 등)를 생성할 때 유용 |
|
||||||
|
| **dotenv** | 환경변수 파일(.env)에서 변수를 로드하는 라이브러리 |
|
||||||
|
| **Mail** | 이메일을 전송할 때 사용하는 라이브러리 |
|
||||||
|
| **Rake** | Ruby에서 작업 자동화 및 빌드를 쉽게 할 수 있도록 지원 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### **결론**
|
||||||
|
위 라이브러리들은 Ruby 개발을 더욱 쉽고 강력하게 만들어준다.
|
||||||
|
- **웹 개발**을 할 때는 `Sinatra` 또는 `Rails`
|
||||||
|
- **HTTP 요청**을 보낼 때는 `HTTParty` 또는 `Faraday`
|
||||||
|
- **테스트**를 할 때는 `RSpec`
|
||||||
|
- **데이터베이스 연동**을 할 때는 `ActiveRecord` 또는 `Sequel`
|
||||||
|
- **CLI 도구**를 만들 때는 `Thor`
|
||||||
|
|
||||||
|
이처럼 목적에 맞는 라이브러리를 잘 활용하면 Ruby 개발이 훨씬 더 쉬워진다!
|
||||||
Reference in New Issue
Block a user