🗂️ 루비(Ruby) 데이터 정리의 기술: 배열과 해시 완전 정복! (Part 4)

코딩의 세계에 점점 더 빠져들고 계신가요? 😄 지난 Part 3: 코드 흐름 제어 마스터에서는 조건문과 반복문을 통해 코드가 스스로 판단하고 반복 작업을 수행하게 만들었습니다. 이제는 여러 개의 데이터를 깔끔하게 정리하고 관리하는 방법을 배울 차례예요!

이번 파트에서는 루비에서 여러 데이터를 묶어서 다루는 가장 대표적인 두 가지 방법, 바로 배열(Array)해시(Hash)에 대해 깊이 알아볼 거예요. 마치 어지럽게 흩어진 물건들을 정리함에 차곡차곡 정리하는 것처럼, 배열과 해시를 사용하면 데이터를 훨씬 효율적으로 관리하고 활용할 수 있게 됩니다. 📦✨

데이터를 다루는 능력은 프로그래밍의 핵심 중 하나! 루비의 강력한 배열과 해시 기능을 함께 마스터해 봅시다!


🔢 순서대로 착착! 배열 (Array)

배열(Array)은 여러 개의 데이터를 순서대로 모아 놓은 목록과 같습니다. 쇼핑 목록, 학생 명단처럼 순서가 중요한 데이터를 저장할 때 아주 유용하죠. 루비 배열은 대괄호([])를 사용하여 만들고, 각 데이터(요소, element)는 쉼표(,)로 구분합니다.


# 빈 배열 만들기
empty_array = []

# 숫자가 들어있는 배열
numbers = [1, 2, 3, 4, 5]

# 문자열이 들어있는 배열
fruits = ["사과", "바나나", "딸기"]

# 다양한 종류의 데이터도 함께 넣을 수 있어요!
mixed_array = [1, "hello", 3.14, true]

puts numbers   # 출력: [1, 2, 3, 4, 5]
puts fruits    # 출력: ["사과", "바나나", "딸기"]
puts mixed_array # 출력: [1, "hello", 3.14, true]
  

배열 요소에 접근하기 (Indexing)

배열 안의 특정 데이터에 접근하려면 '인덱스(index)'를 사용합니다. 인덱스는 배열 요소의 순서 번호인데,

⚠️ 중요: 프로그래밍에서는 숫자를 0부터 센다는 점!

첫 번째 요소의 인덱스는 0, 두 번째는 1, 이런 식입니다.


colors = ["빨강", "주황", "노랑", "초록"]

puts colors[0]  # 출력: 빨강 (첫 번째 요소)
puts colors[1]  # 출력: 주황 (두 번째 요소)
puts colors[3]  # 출력: 초록 (네 번째 요소)

# 음수 인덱스도 가능해요! (-1은 마지막 요소, -2는 마지막에서 두 번째 요소)
puts colors[-1] # 출력: 초록 (마지막 요소)
puts colors[-2] # 출력: 노랑 (마지막에서 두 번째 요소)
  

배열에 요소 추가/삭제하기

배열은 고정된 것이 아니라, 요소를 자유롭게 추가하거나 삭제할 수 있습니다.


my_list = ["밥먹기", "공부하기"]

# 요소 추가하기
my_list.push("운동하기") # 배열 맨 뒤에 추가 (가장 일반적)
my_list << "청소하기"    # 이것도 맨 뒤에 추가하는 다른 표현

puts my_list.inspect # 출력: ["밥먹기", "공부하기", "운동하기", "청소하기"]

# 요소 삭제하기
last_item = my_list.pop # 배열 맨 뒤 요소를 제거하고 그 값을 반환
puts "제거된 항목: #{last_item}" # 출력: 제거된 항목: 청소하기
puts my_list.inspect          # 출력: ["밥먹기", "공부하기", "운동하기"]

first_item = my_list.shift # 배열 맨 앞 요소를 제거하고 그 값을 반환
puts "제거된 항목: #{first_item}" # 출력: 제거된 항목: 밥먹기
puts my_list.inspect           # 출력: ["공부하기", "운동하기"]

# 특정 위치(인덱스)의 요소 삭제하기
my_list.delete_at(0) # 인덱스 0 (첫 번째) 요소 삭제
puts my_list.inspect # 출력: ["운동하기"]
  

✨ 유용한 배열 메소드들

루비 배열은 정말 다양한 기능(메소드)들을 가지고 있어요. 몇 가지 자주 쓰는 것들을 알아볼까요?

  • .length 또는 .size: 배열에 들어있는 요소의 개수를 알려줍니다.
  • .first: 첫 번째 요소를 반환합니다.
  • .last: 마지막 요소를 반환합니다.
  • .include?(값): 배열 안에 특정 값이 포함되어 있는지 확인합니다. (true 또는 false 반환)
  • .sort: 요소들을 정렬하여 새로운 배열을 반환합니다.
  • .reverse: 요소들의 순서를 뒤집은 새로운 배열을 반환합니다.
  • .join(구분자): 배열 요소들을 하나의 문자열로 합쳐줍니다. 구분자를 생략하면 그냥 이어 붙입니다.

nums = [3, 1, 4, 1, 5, 9]

puts nums.length    # 출력: 6
puts nums.first     # 출력: 3
puts nums.last      # 출력: 9
puts nums.include?(4) # 출력: true
puts nums.include?(2) # 출력: false

sorted_nums = nums.sort
puts sorted_nums.inspect # 출력: [1, 1, 3, 4, 5, 9]

reversed_nums = nums.reverse
puts reversed_nums.inspect # 출력: [9, 5, 1, 4, 1, 3]

puts ["a", "b", "c"].join          # 출력: abc
puts ["a", "b", "c"].join("-")     # 출력: a-b-c
  

이 외에도 Part 3에서 잠깐 맛봤던 .each, .map, .select 등 강력한 이터레이터 메소드들이 배열과 함께 자주 사용됩니다!


🏷️ 이름표로 찾는 사전! 해시 (Hash)

배열이 순서대로 데이터를 관리했다면, 해시(Hash)는 순서 대신 고유한 키(Key)를 사용하여 데이터를 관리합니다. 마치 사전에서 단어(키)를 찾아 뜻(값)을 찾는 것과 비슷하죠. 각 키는 하나의 값(Value)과 짝을 이룹니다 (키-값 쌍, Key-Value Pair).

해시는 중괄호({})를 사용하여 만들고, 키와 값은 => (해시 로켓) 또는 : (JSON 스타일 - 키가 심볼일 때) 로 연결합니다. 각 키-값 쌍은 쉼표(,)로 구분합니다.


# 빈 해시 만들기
empty_hash = {}

# 기본적인 해시 (키: 문자열, 값: 다양함)
student = {
  "name" => "김루비",
  "age" => 21,
  "major" => "컴퓨터공학"
}

# ✨ 루비 스타일: 심볼(Symbol)을 키로 사용하는 해시 (더 효율적이고 일반적!)
# 심볼은 이름 앞에 콜론(:)을 붙여 만듭니다. (예: :name)
# JSON 스타일 (key: value) 로 더 간결하게 표현 가능!
person = {
  name: "박해시",  # "name": 와 같음
  age: 28,
  city: "서울"
}

puts student  # 출력: {"name"=>"김루비", "age"=>21, "major"=>"컴퓨터공학"}
puts person   # 출력: {:name=>"박해시", :age=>28, :city=>"서울"}
  
💡 심볼(Symbol) 키 사용 권장! 루비에서는 해시의 키로 문자열보다는 심볼을 사용하는 것이 일반적입니다. 심볼은 내부적으로 더 효율적으로 처리되며, JSON 스타일 key: value 문법으로 더 깔끔하게 작성할 수 있습니다.

해시 값에 접근하기

해시 안의 값에 접근할 때는 배열처럼 대괄호([])를 사용하지만, 인덱스 대신 **키**를 넣어줍니다.


product = { name: "노트북", price: 1200000, stock: 5 }

puts product[:name]   # 출력: 노트북 (심볼 키로 접근)
puts product[:price]  # 출력: 1200000

# 존재하지 않는 키로 접근하면? -> nil 반환! (오류 발생 안 함)
puts product[:color]  # 출력: nil
  

해시에 키-값 쌍 추가/수정하기

새로운 키-값 쌍을 추가하거나 기존 키의 값을 변경하는 것도 간단합니다.


config = { theme: "dark", font_size: 12 }

# 새로운 키-값 쌍 추가
config[:language] = "한국어"
puts config.inspect # 출력: {:theme=>"dark", :font_size=>12, :language=>"한국어"}

# 기존 키의 값 수정
config[:font_size] = 14
puts config.inspect # 출력: {:theme=>"dark", :font_size=>14, :language=>"한국어"}
  

✨ 유용한 해시 메소드들

해시도 편리한 기능들을 많이 제공합니다.

  • .keys: 해시의 모든 키들을 배열로 반환합니다.
  • .values: 해시의 모든 값들을 배열로 반환합니다.
  • .has_key?(키) 또는 .key?(키): 해시에 특정 키가 있는지 확인합니다. (true/false)
  • .has_value?(값) 또는 .value?(값): 해시에 특정 값이 있는지 확인합니다. (true/false)
  • .length 또는 .size: 해시에 들어있는 키-값 쌍의 개수를 반환합니다.
  • .each: 해시의 각 키-값 쌍을 순회하며 블록을 실행합니다. (블록 변수로 |key, value| 를 받음)

options = { color: "blue", size: "M", quantity: 10 }

puts options.keys.inspect      # 출력: [:color, :size, :quantity]
puts options.values.inspect    # 출력: ["blue", "M", 10]
puts options.has_key?(:color)  # 출력: true
puts options.has_value?("L")   # 출력: false
puts options.length          # 출력: 3

options.each do |key, value|
  puts "옵션 #{key}: #{value}"
end
# 출력:
# 옵션 color: blue
# 옵션 size: M
# 옵션 quantity: 10
  

🎮 오늘의 실습: 간단한 할 일 목록 관리

배열을 이용해서 간단한 할 일 목록(To-Do List) 관리 기능을 만들어 봅시다!

요구사항:

  1. 할 일들을 저장할 빈 배열 `todos`를 만듭니다.
  2. `todos` 배열에 "루비 공부하기", "저녁 장보기", "운동하기" 세 가지 할 일을 추가합니다.
  3. 현재 할 일 목록 전체를 화면에 번호와 함께 출력합니다. (예: "1. 루비 공부하기")
  4. 목록에서 첫 번째 할 일("루비 공부하기")을 완료했다고 가정하고, 배열에서 제거합니다.
  5. 변경된 할 일 목록을 다시 화면에 번호와 함께 출력합니다.

힌트: 배열 생성, 요소 추가(push 또는 <<), 요소 접근(인덱스), 요소 제거(shift 또는 delete_at), 반복문(.each_with_index 사용하면 인덱스도 함께 얻을 수 있어요!)을 활용해보세요.

👇 아래는 정답 코드 예시입니다. 스스로 먼저 꼭 풀어보세요! 😉


# 1. 빈 배열 생성
todos = []

# 2. 할 일 추가
todos << "루비 공부하기"
todos.push("저녁 장보기")
todos << "운동하기"

# 3. 현재 목록 출력
puts "--- 현재 할 일 목록 ---"
todos.each_with_index do |todo, index|
  puts "#{index + 1}. #{todo}" # 인덱스는 0부터 시작하므로 +1 해줌
end
puts "----------------------"

# 4. 첫 번째 할 일 완료 (제거)
puts "\n'#{todos.first}' 완료!"
todos.shift # 첫 번째 요소 제거

# 5. 변경된 목록 출력
puts "\n--- 남은 할 일 목록 ---"
todos.each_with_index do |todo, index|
  puts "#{index + 1}. #{todo}"
end
puts "----------------------"
  

💡 Part 4 핵심 요약

  • 배열 (Array): 순서가 있는 데이터 목록. []로 만들고 인덱스(0부터 시작)로 접근.
    • 추가: push, <<
    • 삭제: pop(뒤), shift(앞), delete_at(index)
    • 유용한 메소드: length, first, last, include?, sort, reverse, join, each, map
  • 해시 (Hash): 순서 대신 고유한 키(Key)로 값(Value)을 관리하는 사전. {}로 만들고 키로 접근.
    • 키는 심볼(:key_name) 사용 권장 (JSON 스타일 key: value 가능).
    • 값 접근/수정/추가: hash[key]
    • 유용한 메소드: keys, values, has_key?, has_value?, length, each

🚀 다음 단계로!

축하합니다! 이제 루비에서 데이터를 묶어서 관리하는 강력한 도구인 배열과 해시의 기본 사용법을 익히셨습니다! 🎉 이 두 가지 자료구조는 앞으로 루비 프로그래밍을 하면서 정말 정말 많이 사용하게 될 거예요. 특히 이터레이터와 함께 사용할 때 그 진가가 발휘되죠!

오늘 배운 내용들을 IRB에서 직접 배열과 해시를 만들고 여러 메소드를 실행해보면서 충분히 연습해보세요. 실습 문제도 조금씩 바꿔가면서 응용해보면 더욱 좋습니다.

다음 Part 5: 코드 재사용 끝판왕, 메소드 만들기 에서는 반복되는 코드들을 하나의 기능 단위로 묶어 재사용할 수 있게 해주는 '메소드(Method)'에 대해 배울 거예요. 코드를 더욱 깔끔하고 효율적으로 만드는 방법을 기대해주세요! 😉