



//
// ViewController.swift
// tableA
//
// Created by 컴소뉴맥 on 2026/04/13.
//
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
//부모:자식, 친구(알바생,프로토콜),친구(알바생,프로토콜)
@IBOutlet weak var table: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(indexPath.description) //didSelectRowAt: 보이는 셀을 리턴
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! MyTableViewCell
cell.myLabel.text = name[indexPath.row]
print(indexPath.row)
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 7
}
override func viewDidLoad() {
super.viewDidLoad()
table.delegate = self
table.dataSource = self
}
}
👉 iOS에서 UI를 만들 때 사용하는 기본 프레임워크
(버튼, 테이블, 화면 등 전부 포함)
👉 클래스 선언
- UIViewController 👉 화면 하나를 관리하는 부모 클래스
- UITableViewDelegate 👉 사용자 동작 처리 (클릭 등)
- UITableViewDataSource 👉 테이블에 데이터 공급
💡 즉,
👉 “이 클래스가 테이블의 데이터 + 이벤트를 다 담당한다”는 의미
👉 스토리보드에 있는 테이블뷰와 연결된 변수
- @IBOutlet 👉 UI 연결용 키워드
- weak 👉 메모리 순환 참조 방지
- ! 👉 nil이 아님을 가정 (강제 옵셔널)
return 5
}
👉 한 섹션에 들어갈 행(row) 개수
- section 👉 현재 섹션 번호
- 항상 5를 반환 → 각 섹션마다 5개 셀 생성
print(indexPath.description)
}
👉 셀을 클릭했을 때 실행되는 함수 (Delegate)
- indexPath 👉 클릭된 위치 정보
- section
- row
👉 클릭한 위치를 콘솔에 출력
예: [0, 2] → 0번 섹션, 2번 셀
💡 주의
👉 “셀을 리턴하는 함수”가 아니라
👉 “클릭 이벤트를 처리하는 함수”
👉 테이블의 각 셀을 만드는 핵심 함수
- 테이블이 셀 하나 필요할 때마다 호출됨
👉 셀 재사용 (매우 중요 ⭐)
- dequeueReusableCell 👉 재사용 가능한 셀 가져오기
- "myCell" 👉 스토리보드에서 설정한 Identifier
- as! MyTableViewCell 👉 커스텀 셀로 강제 형변환
💡 이유
👉 셀을 계속 새로 만들면 메모리 낭비 → 재사용
👉 셀에 데이터 넣기
- indexPath.row 👉 몇 번째 줄인지
- name 배열에서 해당 값 가져옴
❗ 주의
👉 name 배열이 반드시 선언되어 있어야 함
👉 현재 생성 중인 셀의 row 번호 출력
(디버깅용)
👉 완성된 셀을 테이블에 전달
return 7
}
👉 테이블의 섹션 개수
- 총 7개의 섹션 생성
super.viewDidLoad()
👉 화면이 처음 로드될 때 실행되는 함수
table.dataSource = self
👉 테이블에게 역할 지정
- delegate 👉 클릭, 스크롤 같은 이벤트 처리
- dataSource 👉 데이터 공급
💡 이거 안 하면 테이블 안 나옴 (중요 ⭐)
📊 전체 동작 흐름
1️⃣ 앱 실행 → viewDidLoad 호출
2️⃣ 테이블이 데이터 요청
3️⃣ 섹션 개수 요청 → 7
4️⃣ 각 섹션마다 행 개수 요청 → 5
5️⃣ 셀을 하나씩 생성 (cellForRowAt)
6️⃣ 사용자 클릭 → didSelectRowAt 실행
❗ 코드에서 꼭 짚고 넘어갈 부분
1️⃣ 총 셀 개수
👉 7 섹션 × 5 행 = 35개 셀
2️⃣ 데이터 문제 가능성
👉 모든 섹션이 같은 데이터 사용
→ 보통은 이렇게 안 하고
👉 section까지 포함해서 데이터 구조 만듦
💡 핵심 요약
👉 DataSource
- 몇 개 만들지
- 셀 내용 무엇인지
👉 Delegate
- 클릭했을 때 뭐 할지
import UIKit // iOS UI를 만들기 위한 기본 프레임워크
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// UIViewController를 상속받고,
// UITableView의 이벤트 처리(Delegate)와 데이터 제공(DataSource)을 담당하는 클래스
@IBOutlet weak var table: UITableView!
// 스토리보드에 있는 UITableView와 연결된 변수
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// 각 섹션(section)마다 몇 개의 행(row)을 만들지 결정하는 함수
return 5 // 모든 섹션에 5개의 셀 생성
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// 사용자가 셀을 클릭했을 때 호출되는 함수 (Delegate 역할)
print(indexPath.description)
// 클릭한 셀의 위치 출력 (예: [section, row])
// ❗ 주의: 셀을 "리턴"하는 함수가 아니라
// 클릭 이벤트를 처리하는 함수임
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// 각 셀을 생성하고 내용을 설정하는 가장 중요한 함수
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! MyTableViewCell
// 재사용 가능한 셀을 가져옴 (메모리 효율)
// "myCell"은 스토리보드에서 설정한 Identifier
// MyTableViewCell 타입으로 강제 형변환
cell.myLabel.text = name[indexPath.row]
// 셀의 라벨에 데이터 넣기
// indexPath.row는 현재 행 번호
// ❗ name 배열이 미리 정의되어 있어야 함
print(indexPath.row)
// 현재 생성 중인 셀의 row 번호 출력 (디버깅용)
return cell
// 완성된 셀을 테이블뷰에 반환
}
func numberOfSections(in tableView: UITableView) -> Int {
// 테이블뷰의 섹션 개수를 설정하는 함수
return 7 // 총 7개의 섹션 생성
}
override func viewDidLoad() {
super.viewDidLoad()
// 뷰가 처음 로드될 때 실행되는 함수
table.delegate = self
// 테이블의 이벤트(클릭, 스크롤 등)를 이 클래스에서 처리
table.dataSource = self
// 테이블에 표시할 데이터도 이 클래스에서 제공
}
}
💡 핵심 요약 (짧게 정리)
- DataSource → 셀 개수 + 내용 설정
- Delegate → 클릭 같은 사용자 이벤트 처리
- indexPath → (섹션, 행) 위치 정보
- dequeueReusableCell → 셀 재사용 (성능 핵심)
------------------------------------------------------------------------------------------------------------
<Optional Chaining>
var x : Int? => nil
x = 10
🍬 옵셔널 체이닝 한 줄 정의
👉 값이 있으면 계속 진행하고, 없으면 그냥 nil 반환하는 것
🧱 왜 필요할까?
Swift에서는 값이 **없을 수도 있는 변수(옵셔널)**가 있어요.
예:
❌ 문제 상황
👉 name이 nil이면?
💥 앱 크래시 (에러 발생)
✅ 옵셔널 체이닝 사용
👉 의미:
- name이 있으면 → count 실행
- 없으면 → 그냥 nil
👉 절대 안 터짐 👍
🧠 핵심 개념
👉 뜻:
"이거 있으면 다음 실행해"
🔗 연결되는 구조 (체이닝)
👉 해석:
- person 있으면
- home 있으면
- address 있으면
- city 가져오기
👉 중간에 하나라도 없으면 → 바로 nil
🍕 쉬운 비유
👉 자동문 🚪
- 사람이 있으면 → 문 열림
- 사람이 없으면 → 아무 일도 안 일어남
👉 ? = 자동문
❗ 결과 특징
👉 결과 타입:
👉 왜?
→ 중간에 nil 될 수 있으니까
🎯 핵심 요약
- ? = 안전하게 접근
- 값 있으면 실행
- 없으면 nil 반환
- 절대 크래시 안 남


**
if let a = x {
print(a)
} //옵셔널 바인딩
var x : String? //= "Hi"//Hi지우고도 실습
//print(x, x!)
if let a = x {
print(a)
} //옵셔널 바인딩
let b = x!.count -> x의 값은 nil 풀면 x
print(type(of:b),b)
let b1 = x?.count //조심스럽게 풀음
print(type(of:b1),b1, b1!)
let c = x ?? ""
print(c)

중요 예시(이것만 기억)


class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
let kim: Person = Person(name: "Kim", age: 20)
print(kim.age)
let han: Person? = Person(name: "Han", age: 25) //옵셔널 -> 값이 없을 수도 있음
//print(han.age) //에러 ->풀어서 접근
print(han!.age)
print(han?.age) // ?조심스럽게 접근->크래시 방지 //Optional(25), 옵셔널 체이닝
print((han?.age)!)
if let hanAge = han?.age {
print(hanAge)
} else {
print("nil")
}
🍬 예제 1: 가장 기본
print(name?.count)
👉 설명
- name이 있으면 → 글자 수 출력
- 없으면 → nil
👉 결과:
print(name?.count)
👉 결과:
👉 핵심
- 값 없으면 그냥 nil
- 절대 에러 안 남 👍
🍬 예제 2: 객체 안의 값 접근
var name: String = "Coco"
}
var dog: Dog? = Dog()
print(dog?.name)
👉 설명
- dog가 있으면 → name 가져오기
- 없으면 → nil
👉 결과:
print(dog?.name)
👉 결과:
🍬 예제 3: 여러 단계 체이닝 (중요 ⭐)
var city: String = "Seoul"
}
class Person {
var address: Address? = Address()
}
var person: Person? = Person()
print(person?.address?.city)
👉 설명 (흐름)
- person 있나?
- address 있나?
- city 가져오기
👉 결과:
print(person?.address?.city)
👉 결과:
👉 중간에 하나라도 nil이면 전체가 nil
🍬 예제 4: 함수 호출
func sound() {
print("야옹")
}
}
var cat: Cat? = Cat()
cat?.sound()
👉 설명
- cat이 있으면 → sound 실행
- 없으면 → 아무 일도 안 일어남
👉 결과:
cat?.sound()
👉 결과:
👉 아무 출력 없음 (조용함)
🧠 핵심 정리
👉 ?. 의미
"있으면 실행, 없으면 멈춤"
🎯 진짜 중요한 포인트
- 중간에 하나라도 nil → 전체 결과 nil
- 앱이 절대 크래시 안 남
- 결과는 항상 옵셔널 타입
💡 한 줄 요약
👉 옵셔널 체이닝 = 안전하게 연결해서 값 꺼내는 방법
-------------------------------------------------------------------------------------------------------------------
오류 처리 <Error Handling>
📊 Error Handling 방법 비교표
| try-catch | 에러가 발생할 수 있는 코드를 감싸고, 에러를 잡아서 처리 | try { } catch { } | 가장 일반적이고 강력 | Swift, Java, Python |
| throws (던지기) | 함수에서 에러를 직접 처리하지 않고 호출한 쪽으로 넘김 | throws | 책임을 위로 전달 | Swift, Java |
| Optional (nil 처리) | 값이 없을 수 있음을 nil로 표현 | ? | 간단하지만 상세한 에러 정보 없음 | Swift |
| Result 타입 | 성공/실패를 하나의 값으로 반환 | Result<T, Error> | 함수형 스타일 | Swift, Rust |
| if/else 체크 | 조건문으로 직접 에러 상황 처리 | if (x == nil) | 가장 단순하지만 반복 많음 | 모든 언어 |
| assert | 특정 조건이 맞지 않으면 프로그램 중단 | assert() | 디버깅용 | Swift, Python |
| panic / fatalError | 치명적 에러 발생 시 즉시 종료 | fatalError() | 복구 불가능 상황 | Swift, Rust |
| error code 반환 | 숫자/코드로 에러 상태 전달 | return -1 | C 스타일 | C, C++ |
| logging | 에러를 기록만 하고 계속 실행 | print/log | 디버깅 및 추적용 | 모든 언어 |
📌 Swift 기준으로 핵심 4가지
Swift에서는 특히 이 4개가 중요합니다 👇
1️⃣ try-catch
try someFunction()
} catch {
print("에러 발생")
}
2️⃣ throws
// 에러 발생 가능
}
3️⃣ Optional
👉 값 없으면 nil로 처리
4️⃣ Result 타입
👉 성공 vs 실패를 명확히 구분

swift 오류 제어

throwing function(시험*)

AVAudioPlayer


throws 매소드 메게변수 ()다음에 화살표(->)앞에 사용
예외 처리를 할때 리턴값이 있을 경우 리턴값을 작성한다
(throws매소드는 반드시 예외처리를 해야한다)

do~catch 예제
🍬 예제: 숫자 나눗셈 (0으로 나누기 에러)
1️⃣ 에러 타입 만들기
case divideByZero
}
👉 의미
- Error 프로토콜을 따르는 에러 종류 정의
- 여기서는 “0으로 나누기” 에러만 있음
2️⃣ 에러를 던지는 함수
if b == 0 {
throw MathError.divideByZero
}
return a / b
}
👉 설명
- throws 👉 이 함수는 에러 발생 가능
- throw 👉 실제로 에러 발생시키기
3️⃣ do-catch로 처리
let result = try divide(10, 0)
print(result)
} catch {
print("에러 발생!")
}
👉 결과
🎯 흐름 정리
- try divide(10, 0) 실행
- b == 0 → 에러 발생 (throw)
- catch로 이동
- 에러 메시지 출력
🍬 에러 종류별로 처리 (조금 더 발전)
let result = try divide(10, 0)
print(result)
} catch MathError.divideByZero {
print("0으로 나눌 수 없습니다!")
} catch {
print("알 수 없는 에러")
}
👉 결과
🧠 핵심 개념
- throws 👉 에러 던질 수 있음
- throw 👉 에러 발생
- try 👉 에러 날 수 있는 코드 실행
- do-catch 👉 에러 잡기
💡 한 줄 요약
👉 do-catch는 “에러가 나면 여기서 잡아서 처리하겠다”는 구조

🚨 에러 메시지 해석
Call can throw, but it is not marked with 'try' and the error is not handled
👉 쉽게 번역하면:
👉 “이 함수는 에러(throw)를 발생시킬 수 있는데,
너는 try도 안 썼고 do-catch로도 처리 안 했어!”
📌 왜 이런 에러가 생기냐?
Swift에서는 에러 가능한 함수에 반드시 표시가 있어요:
👉 throws = “이 함수 에러 날 수 있음”
❌ 잘못된 사용
👉 문제:
- 에러 날 수 있는 함수인데
- try도 없음
- do-catch도 없음
💥 그래서 컴파일 에러 발생
✅ 해결 방법 3가지
1️⃣ try + do-catch (정석 👍)
let result = try divide(10, 0)
print(result)
} catch {
print("에러 발생")
}
👉 가장 안전한 방법
2️⃣ try? (간단 처리)
👉 에러 나면 nil
3️⃣ try! (위험하지만 간단)
👉 에러 나면 💥 앱 크래시
🧠 핵심 원리
Swift는 일부러 이렇게 강하게 체크함:
👉 “에러 날 가능성 있는데 무시하면 위험하니까 꼭 처리해!”
🎯 한 줄 정리
👉 이 에러는
“throw 가능한 함수인데 try 또는 에러 처리를 안 해서 생긴 컴파일 에러”
-------------------------------------------------------------------------------------------------------------------
Generic <>
📌 1️⃣ 가장 중요한 역할: 제네릭(Generic)
👉 “어떤 타입이든 받을 수 있게 만드는 기능”
Swift 예시:
print(value)
}
🔍 설명
- T = 아직 정해지지 않은 타입
- <> 안에 타입을 넣을 수 있는 “틀”
프로그래밍언어에서 [],{},(),<>
📌 프로그래밍 기호 기본 의미
| () | 괄호 (parentheses) | 함수 호출 / 계산 우선순위 | “이거 먼저 해!” |
| [] | 대괄호 (square brackets) | 배열 / 리스트 / 인덱스 | “여러 개 모아놓기” |
| {} | 중괄호 (curly braces) | 코드 블록 | “여기부터 여기까지 한 덩어리” |
| <> | 꺾쇠 괄호 (angle brackets) | 제네릭 / 타입 지정 | “타입을 나중에 정함” |
🍬 1️⃣ ()
👉 괄호 = “실행 / 묶기”
예제
👉 먼저 계산하고 실행
함수 호출
👉 “이 함수 실행해!”
🍬 2️⃣ []
👉 대괄호 = “리스트 / 배열 / 위치”
배열
특정 값 꺼내기
👉 A 출력 (0번째)
💡 느낌
👉 “여러 개 담는 상자”
🍬 3️⃣ {}
👉 중괄호 = “코드 묶음”
함수
print("Hi")
}
if문
print("ok")
}
💡 느낌
👉 “여기부터 여기까지 하나의 블록”
🍬 4️⃣ <>
👉 꺾쇠 = “타입을 나중에 넣는 틀”
Swift 제네릭
print(value)
}
👉 T = 어떤 타입이든 가능
배열 타입
💡 느낌
👉 “비어있는 상자 (나중에 타입 결정)”
🎮 한눈에 비유
| () | 버튼 누르기 |
| [] | 상자 / 리스트 |
| {} | 방 / 구역 |
| <> | 템플릿 / 틀 |
🎯 핵심 정리
- () → 실행 / 함수
- [] → 여러 개 / 인덱스
- {} → 코드 영역
- <> → 타입 틀 (제네릭)
제네릭 지원하는 대표 프로그래밍 언어들
🟦 1️⃣ 모바일 / 앱 개발
- Swift (iOS)
- Kotlin (Android)
- Java (Android/Backend)
👉 거의 모든 모바일 메인 언어는 제네릭 지원
🟨 2️⃣ 웹 개발
- TypeScript (JavaScript 상위)
- JavaScript (제네릭은 TS에서 주로 사용)
- Dart (Flutter)
🟥 3️⃣ 시스템 / 고성능
- C++
- Rust
- Go (제네릭은 Go 1.18+ 이후 지원)
🟩 4️⃣ 백엔드 / 서버
- Java
- Kotlin
- C#
- Scala
- Python (런타임 제네릭은 약하지만 typing에서 지원)
🟪 5️⃣ 기타 언어
- Haskell
- Swift (이미 포함)
- Objective-C (제한적)
- F#
- OCaml
📊 한눈에 핵심 정리
| 모바일 | Swift, Kotlin, Java |
| 웹 | TypeScript, JavaScript(부분), Dart |
| 시스템 | C++, Rust, Go |
| 서버 | Java, Kotlin, C#, Scala |
| 함수형 | Haskell, F#, OCaml |
🧠 중요한 포인트
👉 요즘 “현대 언어 = 거의 다 제네릭 지원”
왜냐하면:
- 코드 재사용 ↑
- 타입 안정성 ↑
- 버그 감소 ↑
🍬 아주 쉽게 이해
제네릭 없는 코드:
String용 함수
Double용 함수
→ 다 따로 만들어야 함
제네릭 있는 코드:
🎯 핵심 한 줄
👉 제네릭은 거의 모든 현대 프로그래밍 언어에 있는 “기본 기능”이다
Swift Generic
-> 자료형이 실행할때 결정되는 방식
func myPrint<T> (a: T, b: T) {
//myPrint는 결정되지 않은 자료형이 있다-> T
print(b,a)
}
myPrint(a:1,b:2)
myPrint(a:Int(2.5),b:Int(3.5))//double형
func myPrint<T> (a: T, b: T) {
//myPrint는 결정되지 않은 자료형이 있다-> T
print(b,a)
}
myPrint(a:1,b:2)
myPrint(a:2.5,b:3.5)//double형
myPrint(a: "aaa", b: "bbb")
->출력값
2 1
3.5 2.5
bbb aaa
class Box<T> { //클래스 이름 뒤 <>를 사용(제너릭 클래스)
var item: T
init(item: T) {
self.item = item
}//이니셜 라이저
func getItem() -> T {
return item
}
} //일반 클래스
let intBox = Box<Int>(item: 12)
// Box<Int>(item: 123), generic class는 이렇게 쓰지만 타입 추론으로 <Int> 생략 가능
print(intBox.getItem()) // 12
let stringBox = Box(item: "Hello") //Box<String>(item: "Hello")
print(stringBox.getItem()) // Hello
📦 1️⃣ 제네릭 클래스 선언
👉 의미:
- Box라는 “상자 클래스” 만들기
- <T> = 아직 타입이 정해지지 않은 자리
💡 쉽게 말하면:
“이 상자에는 어떤 타입이든 들어갈 수 있어”
예:
- Int 넣을 수도 있고
- String 넣을 수도 있음
📦 2️⃣ 변수 선언
👉 의미:
- item은 상자 안의 내용물
- 타입은 T (나중에 결정됨)
💡 즉:
“아직 모르지만 어떤 타입이든 하나 들어올 거야”
📦 3️⃣ 초기화 (init)
self.item = item
}
👉 의미:
- Box를 만들 때 값을 넣어줘야 함
- 넣은 값을 item에 저장
💡 예:
👉 10이 item에 들어감
📦 4️⃣ 값 꺼내기 함수
return item
}
👉 의미:
- 상자 안에 있는 값을 꺼내는 함수
- 반환 타입도 T (같은 타입 유지)
💡 즉:
“넣은 타입 그대로 꺼내준다”
🧪 5️⃣ Int 타입으로 사용
👉 의미:
- T = Int로 결정됨
- 이제 Box는 “Int 전용 상자”
💡 내부적으로:
👉 결과:
🧪 6️⃣ String 타입으로 사용
👉 여기 중요한 포인트 ⭐
Swift는 타입을 자동으로 추론함
👉 컴파일러가 이렇게 이해:
👉 결과:
🧠 핵심 개념 정리
📌 1. T의 의미
👉 “아직 모르는 타입 자리”
📌 2. 한 번 정해지면 고정
👉 이 Box는 절대 String 못 넣음
📌 3. 타입 안전성
👉 잘못 쓰면 에러
🍬 쉬운 비유
👉 Box<T> = “종이 상자”
- 만들 때 라벨 붙임
- Int 상자 📦
- String 상자 📦
👉 한번 정하면 바꿀 수 없음
🎯 핵심 요약
- <T> = 타입 자리 예약
- Box<T> = 어떤 타입이든 담을 수 있는 상자
- 생성할 때 타입 결정됨
- 이후에는 그 타입만 사용 가능
💡 한 줄 정리
👉 제네릭은 “하나의 코드로 여러 타입을 처리하는 기술”
class Box<T> {
// 제네릭 클래스 선언
// <T>는 "아직 정해지지 않은 타입 자리"
// Int, String, Double 등 어떤 타입이든 들어올 수 있음
var item: T
// item 변수의 타입은 T
// 즉, Box를 만들 때 T가 결정되면 item 타입도 같이 결정됨
init(item: T) {
// 생성자 (init)
// Box를 만들 때 item 값을 반드시 넣어줘야 함
self.item = item
// 전달받은 item 값을 클래스의 item에 저장
}
func getItem() -> T {
// item 값을 꺼내는 함수
// 반환 타입도 T (입력 타입과 동일하게 유지됨)
return item
// 저장된 item 값을 그대로 반환
}
}
// 👉 이 클래스는 "어떤 타입이든 담을 수 있는 상자(Box)" 역할
// ==========================
// 1️⃣ Int 타입으로 Box 사용
// ==========================
let intBox = Box<Int>(item: 12)
// Box<Int> → T가 Int로 결정됨
// 즉, item의 타입은 Int가 됨
// item에 12를 넣어서 intBox 생성
// 참고:
// Box<Int>(item: 12) 이렇게 명시적으로 써도 되고
// Swift가 타입을 추론해서 Box(item: 12)로도 가능
print(intBox.getItem())
// getItem() 호출 → item 반환
// 결과: 12
// ==========================
// 2️⃣ String 타입으로 Box 사용
// ==========================
let stringBox = Box(item: "Hello")
// <String> 생략됨 (타입 추론)
// Swift가 자동으로 Box<String>으로 판단
// 내부적으로는 이렇게 해석됨:
// let stringBox = Box<String>(item: "Hello")
print(stringBox.getItem())
// getItem() 호출 → item 반환
// 결과: "Hello"
🧠 핵심 정리 (진짜 중요)
📌 1. <T> 의미
👉 “타입을 나중에 결정하겠다”
📌 2. Box<Int>
👉 T = Int로 고정됨
👉 이제 이 Box는 Int 전용
📌 3. Box<String>
👉 T = String으로 고정됨
👉 문자열 전용 Box
📌 4. 타입 추론
👉 Swift가 자동으로:
🎮 쉬운 비유
👉 Box<T> = “택배 상자”
- 만들 때 라벨 붙임
- 📦 Int 상자
- 📦 String 상자
👉 한 번 정하면 내용물 종류 고정
💡 한 줄 요약
👉 제네릭 클래스는 “하나의 코드로 여러 타입을 담는 상자”
--------------------------------------------------------------------------------------------------------------
Collection Type

3가지
📦 1️⃣ Array (배열)
👉 순서가 있는 값들의 모음
📌 특징
- 순서 있음 (index 존재)
- 중복 허용
- numbers[0]처럼 접근
📌 예시
💡 비유:
👉 “줄 서 있는 사람들”
📦 2️⃣ Dictionary (딕셔너리)
👉 키(Key) - 값(Value) 구조
"name": "Tom",
"age": 20
]
📌 특징
- 순서 없음
- key로 값 찾음
- key는 유일해야 함
📌 예시
💡 비유:
👉 “사전 (단어 → 뜻)”
📦 3️⃣ Set (집합)
👉 중복 없는 값들의 모음
print(set) // [1, 2, 3]
📌 특징
- 중복 제거됨
- 순서 없음
- 빠른 검색
💡 비유:
👉 “중복 없는 명단”
📊 한눈에 비교
| Array | 있음 | 가능 | index (0,1,2) |
| Dictionary | 없음 | key는 유일 | key로 접근 |
| Set | 없음 | 불가능 | 값 자체 |
🧠 핵심 정리
- Array → 순서 있는 리스트
- Dictionary → 키-값 구조
- Set → 중복 없는 집합


swift에서 array는 일반배열 or 빈배열를 만든다


주요예시

append로 접근하지 않고 값을 접근하면 값이 나오지 않음
append는 값을 넣어라는 뜻
var number : [Int] = []
//빈 배열을 let으로 만들 수는 있지만 초기값에서 변경 불가이니 배열의 의미 없음
var odd = [Int]()
var even : Array<Int> = Array()
print(number) //[]
//print(number[0]) //오류, 빈 배열을 값을 넣은 다음에 접근
number.append(100) //let으로 선언한 불변형 배열이라 추가 불가능
//error: cannot use mutating member on immutable value: 'number' is a 'let' constant
print(number[0])
number.append(200)
print(number[0], number[1],number)


Array(repeating:count:)
배열의 여러개의 같은 값을 저장


=>Optional(1) Optional(4)
nil nil
1 4
첨자(subscript)로 항목 접근


append