들어가기 앞서
책 소개
원작자: Michael Hartl (마이클 허틀)
Ruby on Rails 프레임워크를 활용하여 Custom Web Application을 만들기 위한 튜토리얼 과정을 소개하고 있는 책이다. Learn Enough to Be Dangerous의 시리즈 중 하나로 Ruby on Rails(이하 레일즈)의 기초 지식을 배우는데 적절한 튜토리얼이다. 원본은 영어이고 번역본은 일어판이 존재하지만 정말 감사하게도 GitHub에 번역 작업을 해놓으신 천사님이 계신다..! 덕분에 해당 GitHub 참고해서 학습을 진행하였고 정말 감사한 마음이다.
개발 환경
- OS: macOS Big Sur 11.5.2
- IDE: Visual Studio Code, RubyMine를 혼용하여 사용
(책에서는 AWS Cloud9 IDE 환경에서 사용) - Ruby: ruby 2.6.9p207 (2021-11-24 revision 67954) [x86_64-darwin20]
- Ruby on Rails: Rails 5.1.6
- SCM: GitHub
AWS Cloud9 환경이 아닌 로컬환경에서 실행하였기 때문에 루비와 레일즈 설치는 가이드 문서를 보고 진행하였다.
클라우드 IDE를 사용할 경우 책의 내용을 따라하면 된다.
Ruby on Rails (루비 온 레일즈)
개요
2004년 등장한 Ruby(루비)언어 기반의 웹 개발 프레임워크이다. 동적인 웹 애플리케이션 개발을 위한 프레임워크로 인지도가 있어 Airbnb, Basecamp , Disney , GitHub , Hulu , Kickstarter , Shopify , Twitter , Yellow Pages 등의 기업에서 사용하였다.
인기 요인
대표적으로 아래와 같은 이유로 인기를 끌었다고 볼 수 있다.
- MIT 라이선스로 이루어진 100% 오픈소스
: 제약이 적은 MIT 라이선스로 이루어져 있다. - 간결하고 아름다운 설계
: 레일즈의 기반이 되는 루비 언어는 매우 유연하고 웹 애플리케이션 개발에 특화된 DSL(도메인 고유 언어)를 구현하고 있어 웹 개발 시 코드 구조가 간결하고 읽기 쉬워진다. - REST라는 설계 사상을 빠르게 받아들였다.
- 활발하고 다양한 커뮤니티
: 한국에서는 사용률이 낮지만 전세계적 방대한 커뮤니티를 보유하고 있다.
애플리케이션 생성
디렉토리 생성
애플리케이션을 생성하기 전 레일즈 프로젝트를 위한 디렉토리를 생성한다. 책에서는 홈 디렉터리 하위에 environment 디렉토리를 만들었지만 본인은 ~/Documents/workspace/로 대체하였다.
$ cd # 홈 디렉토리로 이동한다.
$ mkdir environment # 'environment' 디렉토리를 만든다.
$ cd environment/ # 'environment' 디렉토리로 이동한다.
# 아래는 본인의 환경
$ cd ~/Documents # 홈 디렉토리 하위의 문서 디렉토리로 이동한다.
$ mkdir workspace # 'workspace' 디렉토리를 만든다.
$ cd workspace # 'workspace' 디렉토리로 이동한다.
지금은 비교를 위해 책의 개발 환경도 함께 작성하였지만 향후부터는 본인의 개발환경 기준으로 작성을 하게 될 예정이다. 혹시 글을 읽다 막히는 부분이 있다면 원문을 함께 참고하시길 바랍니다.
$ cd ~/Documents/workspace/
$ rails _5.1.6_ new hello_app
create
create README.md
create Rakefile
create config.ru
create .gitignore
create Gemfile
create app
create app/assets/config/manifest.js
create app/assets/javascripts/application.js
create app/assets/javascripts/cable.js
create app/assets/stylesheets/application.css
create app/channels/application_cable/channel.rb
create app/channels/application_cable/connection.rb
create app/controllers/application_controller.rb
.
.
.
create tmp/cache/assets
create vendor/assets/javascripts
create vendor/assets/javascripts/.keep
create vendor/assets/stylesheets
create vendor/assets/stylesheets/.keep
remove config/initializers/cors.rb
run bundle install
Fetching gem metadata from https://rubygems.org/……….
Fetching additional metadata from https://rubygems.org/..
Resolving dependencies…
Installing rake 11.1.2
Using concurrent-ruby 1.0.2
.
.
.
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.
run bundle exec spring binstub —all
* bin/rake: spring inserted
* bin/rails: spring inserted
위와 같이 rails new를 실행하면 파일 작성 후 run bundle install이 자동적으로 실행되고 대량의 파일과 디렉토리가 생성된 것을 확인할 수 있다.
파일구조
일반적으로 웹 프레임워크는 가독성을 위해 파일 구조가 어느 정도 표준화되어있고 레일즈도 마찬가지이다.
- app/ : 모델, 뷰, 컨트롤러, 헬퍼등을 포함한 주요 어플리케이션 코드
- assets/ : 어플리케이션에서 쓰이는 CSS, Javascript파일, 영상 등의 에셋
- bin/ : 바이너리 실행가능 파일
- rails : : 코드의 생성, 콘솔의 기동, 로컬의 웹서버 기동 등에 쓰이는 Rails script
- config/ : 어플리케이션의 설정
- db/ : 데이터베이스 관련 파일
- doc/ : 메뉴얼등 어플리케이션의 도큐먼트
- lib/ : 라이브러리 모듈
- assets/ : 라이브러리 CSS, Javascript, 영상 파일
- log/ : 어플리케이션의 로그파일
- public/ : 에러페이지, 일반적으로 직접 공개되는 데이터
- test/ : 어플리케이션의 테스트
- tmp/ : 일시 파일
- vendor/ : 서드파티의 플러그인이나 gem
- assets/ : 서드파티의 플러그인이나 gem에서 쓰이는 CSS, Javascript, 영상 파일 등
- README.md : 어플리케이션의 간단한 설명
- Rakefile : rake커맨드에서 쓰이는 task
- Gemfile : 해당 어플리케이션에서 필요한 gem의 정의 파일
- Gemfile.lock : 어플리케이션에서 쓰이는 gem의 버전을 확인하기 위한 리스트 파일
- config.ru : Rack 미들웨어 용의 설정 파일
- .gitignore : Git에 포함시키고 싶지 않은 파일들을 지정하기 위한 파일
Gem Install
디렉토리 생성 시 rails new를 실행하면 파일 작성 후 bundle install이 자동적으로 실행된다. 여기서는 gem을 변경할 예정이기 때문에 bundle을 다시 실행해본다.
1. 기존 Gemfile을 확인한다.
source 'https://rubygems.org'
git_source(:github) do |repo_name|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
"https://github.com/#{repo_name}.git"
end
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.1.6'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use Puma as the app server
gem 'puma', '~> 3.7'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '~> 2.13'
gem 'selenium-webdriver'
end
group :development do
# Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
gem 'web-console', '>= 3.3.0'
gem 'listen', '>= 3.0.5', '< 3.2'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
기존 파일에서 2가지의 버전 설정 방법을 확인할 수 있다.
- >= : 특정 버전 이상을 의미하며 항상 최신 버전의 gem이 설치된다.
예시). gem 'uglifier', '>= 1.3.0' 는 1.3.0 이상이면 최신 버전의 gem이 설치된다. - ~> : 메이저 버전을 지정하는 방법으로 마이너 버전의 최신만 유지된다.
예시) gem 'coffee-rails', '~> 4.0.0' 로 지정시 coffee-rails의 버전이 4.0.0보다 크고 4.1보다 작으면 설치가 진행된다.
2. 아래와 같이 파일을 수정한다.
튜토리얼 진행 중에는 버전이 다를 경우 설명하고 있는 애플리케이션의 움직임이 다를 가능성이 있기 때문에 아래와 같이 고정한 후 진행한다.
source 'https://rubygems.org'
gem 'rails', '5.1.6'
gem 'puma', '3.9.1'
gem 'sass-rails', '5.0.6'
gem 'uglifier', '3.2.0'
gem 'coffee-rails', '4.2.2'
gem 'jquery-rails', '4.3.1'
gem 'turbolinks', '5.0.1'
gem 'jbuilder', '2.6.4'
group :development, :test do
gem 'sqlite3', '1.3.13'
gem 'byebug', '9.0.6', platform: :mri
end
group :development do
gem 'web-console', '3.5.1'
gem 'listen', '3.1.5'
gem 'spring', '2.0.2'
gem 'spring-watcher-listen', '2.0.1'
end
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
3. bundle install 명령어를 사용하여 gem 설치
$ cd hello_app/
$ bundle install
Fetching source index for https://rubygems.org/
.
.
.
애플리케이션 구동
레일즈는 개발 머신에서만 동작되는 로컬 웹 서버를 구동시키기 위한 커맨드라인 프로그램이 있기 때문에 rails server 라는 커맨드를 실행시키는 것만으로도 애플리케이션을 간단하게 동작시킬 수 있다.
$ cd hello_app/
$ rails server
=> Booting Puma
=> Rails application starting on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
http://localhost:3000/ 에 접속하면 아래와 같은 화면을 확인할 수 있다. C9 환경에서 작업하는 경우 원본 문서를 참고바란다.
Model - View - Controller (MVC)
위에서 설명한 레일즈의 폴더 구조를 자세히 살펴봤다면 app 디렉토리 하위에 models, views, controllers라는 세 개의 서브 디렉토리가 있는 것을 확인할 수 있었을 것이다. 여기에서 알 수 있듯 레일즈는 MVC 아키텍처 패턴을 사용하고 있다.
레일즈 애플리케이션과 통신할 때,브라우저는 일반적으로 웹 서버에 요청을 보내고 이것은 요청 처리를 담당하는 컨트롤러(Controller)로 전달된다. 컨트롤러는 경우에 따라 바로 뷰(View)를 생성하여 HTML을 브라우저에 응답하지만 동적인 사이트에서는 보통 데이터베이스와 통신을 담당하는 모델(Model)과 통신한 후 완성된 페이지를 HTML로 바꾸어 브라우저에 보낸다. 이와 관련된 내용은 추후 더 자세히 다룰 예정이다.
모든 언어의 시작, Hello world!
새로운 언어를 배울 때는 역시 Hello world를 찍어봐야지 배우는 느낌이 난다. 이를 위해 간단히 컨트롤러에 액션을 추가하고 기본 레일즈 페이즈 수정을 진행한다. 아래 명령어를 통해 현재 컨트롤러는 ApplicationController 하나 밖에 없음을 확인할 수 있다.
$ ls app/controllers/*_controller.rb
app/controllers/application_controller.rb
해당 파일을 아래와 같이 수정해보자.
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def hello
render html: 'hello, world!'
end
end
요청을 처리할 액션을 정의하였으니 기본 레일즈 페이지가 해당 액션을 사용하도록 설정해주어야 한다. 이를 위해 라우터(router)를 수정하겠다. 라우터는 컨트롤러와 브라우저 사이에서 요청이 오면 어떤 컨트롤러로 보내야할지 결정하는 역할을 한다. 기본 페이지를 바꾸는게 목적이기 때문에, Root routing(어플리케이션의 홈에 접속했을때의 라우팅)를 수정한다. 레일즈의 라우팅 파일은 confing/routes.rb이다. 해당 파일을 열어 아래와 같이 수정한다.
Rails.application.routes.draw do
root 'application#hello'
end
파일을 수정 후 다시 접속하면 아래와 같이 출력되는 것을 확인할 수 있다.
연습 문제
1. Rails에서는 ASCII 코드가 아닌 문자도 지원합니다. ¡Hola, mundo! 에는 스페인어 특유의 역느낌표 *¡*가 포함되어 있습니다. hello 액션을 조금 수정해서 hello world! 대신 hola mundo! 가 출력되게 수정해봅시다.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def hello
# render html: 'hello, world!'
render html: '¡Hola, mundo!'
end
end
2. hello 액션을 참고하여 새로운 액션 goodbye 를 추가해봅시다. 이 액션은 goodbye, world! 라는 텍스트를 출력하도록 합니다. routes.rb 를 수정하여 루트디렉토리를 hello액션에서 goodbye 액션으로 수정해봅시다
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def hello
render html: 'hello, world!'
#render html: '¡Hola, mundo!'
end
def goodbye
render html: 'goodbye, world!'
end
end
# config/routes.rb
Rails.application.routes.draw do
# root 'application#hello'
root 'application#goodbye'
end
글을 마치며
1장에서는 아래와 같은 내용을 배울 수 있었다.
- Ruby on Rails는 웹 개발을 위한 프레임워크로 Ruby 언어로 작성되었다.
- 레일즈를 설치하고 간단하게 애플리케이션 생성, 수정을 진행하였다.
- 컨트롤러의 액션을 추가하고 루트 라우팅을 변경하여 hello world를 표시할 수 있다.
- 레일즈는 rails 라고 하는 이름의 커맨드라인 커맨드가 있으며 아래와 같은 커맨드를 배웠다.
- rails new : 새로운 레일즈 애플리케이션 생성
- rails server(= rails s) : 로컬 서버 실행
실제 원문에는 Git과 Bigbucket을 통한 형상관리에 대한 내용까지 나와있지만 해당 내용까지는 다룰 필요가 없어보여 제외하였다. 혹시라도 Git에 대한 초기 설정이 궁금할 경우 아래 포스팅 참고 부탁드립니다.
추가로 오늘 작성한 코드는 모두 아래 GitHub에서 확인할 수 있다.
참고 자료 및 사이트
- https://www.railstutorial.org/
- https://github.com/Yoodahun/Rails_Tutorials_Translation
- https://gorails.com/setup/macos/11-big-sur