λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ₯– Bread Basics/Swift

Swift 곡식 λ¬Έμ„œ 정리 - μ€‘μ²©λœ νƒ€μž… (Nested Types)

by BreadDev 2025. 4. 12.
728x90

μ•ˆλ…•ν•˜μ„Έμš”. μ˜€λŠ˜μ€ Swift의 '쀑첩 νƒ€μž…(Nested Types)'에 λŒ€ν•΄ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€. 쀑첩 νƒ€μž…μ„ 효과적으둜 ν™œμš©ν•˜λ©΄ μ½”λ“œμ˜ ꡬ쑰와 가독성을 ν–₯μƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ“Œ 쀑첩 νƒ€μž…μ΄λž€?

쀑첩 νƒ€μž…(Nested Types)은 λ‹€λ₯Έ νƒ€μž…(클래슀, ꡬ쑰체, μ—΄κ±°ν˜•) 내뢀에 μ •μ˜λœ νƒ€μž…μ„ λ§ν•©λ‹ˆλ‹€. μ΄λŠ” νŠΉμ • νƒ€μž…κ³Ό λ°€μ ‘ν•˜κ²Œ μ—°κ΄€λœ 보쑰 νƒ€μž…μ„ λ…Όλ¦¬μ μœΌλ‘œ κ·Έλ£Ήν™”ν•˜λŠ” 데 μœ μš©ν•©λ‹ˆλ‹€.

struct OuterType {
    // μ€‘μ²©λœ μ—΄κ±°ν˜•
    enum NestedEnum {
        // μ—΄κ±°ν˜• λ‚΄μš©
    }
    
    // μ€‘μ²©λœ ꡬ쑰체
    struct NestedStruct {
        // ꡬ쑰체 λ‚΄μš©
    }
    
    // μ€‘μ²©λœ 클래슀
    class NestedClass {
        // 클래슀 λ‚΄μš©
    }
}

쀑첩 νƒ€μž…μ˜ μž₯점: κ΄€λ ¨ νƒ€μž…μ„ λ…Όλ¦¬μ μœΌλ‘œ κ·Έλ£Ήν™”ν•˜κ³ , λ„€μž„μŠ€νŽ˜μ΄μŠ€λ₯Ό μ œκ³΅ν•˜λ©°, μ½”λ“œμ˜ λ²”μœ„μ™€ κ°€μ‹œμ„±μ„ λͺ…ν™•ν•˜κ²Œ ν•©λ‹ˆλ‹€.

πŸ“Œ 쀑첩 νƒ€μž…μ„ μ‚¬μš©ν•˜λŠ” 이유

  1. κ΄€λ ¨μ„±: νŠΉμ • νƒ€μž…λ§Œμ„ μœ„ν•œ 보쑰 νƒ€μž…μ„ λͺ…ν™•νžˆ ν‘œν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  2. λ„€μž„μŠ€νŽ˜μ΄μŠ€: 이름 μΆ©λŒμ„ λ°©μ§€ν•˜κ³  μ½”λ“œ ꡬ쑰λ₯Ό 더 λͺ…ν™•ν•˜κ²Œ ν•©λ‹ˆλ‹€.
  3. μΊ‘μŠν™”: μ™ΈλΆ€μ—μ„œ μ ‘κ·Όν•  ν•„μš”κ°€ μ—†λŠ” νƒ€μž…μ„ 숨길 수 μžˆμŠ΅λ‹ˆλ‹€.
  4. μ½”λ“œ ꡬ성: κ΄€λ ¨ κΈ°λŠ₯을 λ…Όλ¦¬μ μœΌλ‘œ κ·Έλ£Ήν™”ν•˜μ—¬ μ½”λ“œλ₯Ό 더 μ‰½κ²Œ 이해할 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ“Œ 쀑첩 νƒ€μž…μ˜ μ‹€μ œ 예제: λΈ”λž™μž­ μΉ΄λ“œ

λ‹€μŒ μ˜ˆμ œλŠ” λΈ”λž™μž­ κ²Œμž„μ˜ μΉ΄λ“œλ₯Ό λͺ¨λΈλ§ν•˜λŠ” BlackjackCard ꡬ쑰체λ₯Ό μ •μ˜ν•©λ‹ˆλ‹€. 이 ꡬ쑰체 내에 μΉ΄λ“œ λͺ¨μ–‘(Suit)κ³Ό μΉ΄λ“œ 숫자(Rank)λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 쀑첩 μ—΄κ±°ν˜•μ„ ν¬ν•¨ν•©λ‹ˆλ‹€:

struct BlackjackCard {
    // μ€‘μ²©λœ Suit μ—΄κ±°ν˜•
    enum Suit: Character {
        case spades = "♠", hearts = "β™‘", diamonds = "β™’", clubs = "♣"
    }

    // μ€‘μ²©λœ Rank μ—΄κ±°ν˜•
    enum Rank: Int {
        case two = 2, three, four, five, six, seven, eight, nine, ten
        case jack, queen, king, ace
        
        // Rank 내에 μ€‘μ²©λœ Values ꡬ쑰체
        struct Values {
            let first: Int, second: Int?
        }
        
        var values: Values {
            switch self {
            case .ace:
                return Values(first: 1, second: 11)
            case .jack, .queen, .king:
                return Values(first: 10, second: nil)
            default:
                return Values(first: self.rawValue, second: nil)
            }
        }
    }

    // BlackjackCard의 ν”„λ‘œνΌν‹°μ™€ λ©”μ„œλ“œ
    let rank: Rank, suit: Suit
    var description: String {
        var output = "suit is \(suit.rawValue),"
        output += " value is \(rank.values.first)"
        if let second = rank.values.second {
            output += " or \(second)"
        }
        return output
    }
}

이 μ˜ˆμ œμ—μ„œ 각 쀑첩 νƒ€μž…μ˜ 역할을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€:

  1. Suit μ—΄κ±°ν˜•: μΉ΄λ“œμ˜ λͺ¨μ–‘(μŠ€νŽ˜μ΄λ“œ, ν•˜νŠΈ, 닀이아λͺ¬λ“œ, 클럽)을 μ •μ˜ν•©λ‹ˆλ‹€.
    • Character νƒ€μž…μ˜ μ›μ‹œκ°’μ„ μ‚¬μš©ν•˜μ—¬ 각 λͺ¨μ–‘μ˜ 기호λ₯Ό μ €μž₯ν•©λ‹ˆλ‹€.
  2. Rank μ—΄κ±°ν˜•: μΉ΄λ“œμ˜ 숫자(2~10, J, Q, K, A)λ₯Ό μ •μ˜ν•©λ‹ˆλ‹€.
    • Int νƒ€μž…μ˜ μ›μ‹œκ°’μ„ μ‚¬μš©ν•˜μ—¬ 숫자 μΉ΄λ“œμ˜ 값을 μ €μž₯ν•©λ‹ˆλ‹€.
  3. Values ꡬ쑰체: Rank 내에 μ€‘μ²©λœ ꡬ쑰체둜, μΉ΄λ“œμ˜ 점수 값을 μ €μž₯ν•©λ‹ˆλ‹€.
    • first: κΈ°λ³Έ 점수 κ°’
    • second: λŒ€μ²΄ 점수 κ°’(μ—μ΄μŠ€ μΉ΄λ“œμ˜ 경우 1 λ˜λŠ” 11)

이런 κ΅¬μ‘°λŠ” μΉ΄λ“œμ˜ 논리적 ꡬ성을 μ½”λ“œ ꡬ쑰에 κ·ΈλŒ€λ‘œ λ°˜μ˜ν•©λ‹ˆλ‹€. λ˜ν•œ Suit와 RankλΌλŠ” 일반적인 이름을 μ‚¬μš©ν•˜λ©΄μ„œλ„ λ‹€λ₯Έ μ½”λ“œμ™€μ˜ 이름 μΆ©λŒμ„ λ°©μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ“Œ μ€‘μ²©λœ νƒ€μž… μ‚¬μš©ν•˜κΈ°

BlackjackCard ꡬ쑰체의 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κ³  μ‚¬μš©ν•˜λŠ” 방법을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€:

let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
print("theAceOfSpades: \(theAceOfSpades.description)")
// 좜λ ₯: "theAceOfSpades: suit is ♠, value is 1 or 11"

μ—¬κΈ°μ„œ μ£Όλͺ©ν•  점은 μ΄ˆκΈ°ν™” μ‹œ .ace와 .spades와 같이 μ—΄κ±°ν˜• μΌ€μ΄μŠ€ μ΄λ¦„λ§ŒμœΌλ‘œ 값을 μ°Έμ‘°ν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. μ΄λŠ” Swiftκ°€ νƒ€μž…μ„ μ»¨ν…μŠ€νŠΈμ—μ„œ μΆ”λ‘ ν•  수 있기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

πŸ“Œ μ™ΈλΆ€μ—μ„œ 쀑첩 νƒ€μž… μ°Έμ‘°ν•˜κΈ°

쀑첩 νƒ€μž…μ„ μ •μ˜ν•œ νƒ€μž… μ™ΈλΆ€μ—μ„œ μ°Έμ‘°ν•΄μ•Ό ν•  경우, 전체 경둜λ₯Ό μ§€μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€:

let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
// heartsSymbol은 "β™‘"

μ΄λ ‡κ²Œ 점 ν‘œκΈ°λ²•(dot notation)을 μ‚¬μš©ν•˜μ—¬ 쀑첩 νƒ€μž…μ˜ 전체 경둜λ₯Ό λͺ…μ‹œν•©λ‹ˆλ‹€. μ΄λŠ” Javaλ‚˜ C#의 λ„€μž„μŠ€νŽ˜μ΄μŠ€ κ°œλ…κ³Ό μœ μ‚¬ν•©λ‹ˆλ‹€.

πŸ“Œ 쀑첩 νƒ€μž… ν™œμš© μ „λž΅

쀑첩 νƒ€μž…μ„ 효과적으둜 ν™œμš©ν•˜κΈ° μœ„ν•œ λͺ‡ κ°€μ§€ μ „λž΅μ„ μ†Œκ°œν•©λ‹ˆλ‹€:

1. κ΄€λ ¨ μƒμˆ˜ κ·Έλ£Ήν™”

νŠΉμ • νƒ€μž…κ³Ό κ΄€λ ¨λœ μƒμˆ˜λ₯Ό 쀑첩 μ—΄κ±°ν˜•μœΌλ‘œ κ·Έλ£Ήν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

struct NetworkManager {
    enum HTTPMethod: String {
        case get = "GET"
        case post = "POST"
        case put = "PUT"
        case delete = "DELETE"
    }
    
    func request(url: URL, method: HTTPMethod) {
        // κ΅¬ν˜„ λ‚΄μš©
    }
}

2. νŠΉμ • νƒ€μž…μ—μ„œλ§Œ μ‚¬μš©ν•˜λŠ” 였λ₯˜ νƒ€μž… μ •μ˜

class DataManager {
    enum DataError: Error {
        case fileNotFound
        case corruptData
        case insufficientPermissions
    }
    
    func loadData() throws {
        throw DataError.fileNotFound
    }
}

3. μ—¬λŸ¬ μˆ˜μ€€μ˜ 쀑첩 ν™œμš©

ν•„μš”μ— 따라 μ—¬λŸ¬ μˆ˜μ€€μ˜ 쀑첩을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

struct AppConfiguration {
    struct UI {
        struct Colors {
            static let primary = "#FF5733"
            static let secondary = "#33FF57"
        }
        
        struct Fonts {
            static let title = "Helvetica-Bold"
            static let body = "Helvetica"
        }
    }
    
    struct API {
        static let baseURL = "https://api.example.com"
        static let timeout = 30.0
    }
}

// μ‚¬μš© 예
let primaryColor = AppConfiguration.UI.Colors.primary

πŸ“Œ 쀑첩 νƒ€μž…μ„ μ‚¬μš©ν•  λ•Œ μ£Όμ˜μ‚¬ν•­

  1. κ³Όλ„ν•œ 쀑첩 ν”Όν•˜κΈ°: λ„ˆλ¬΄ κΉŠμ€ 쀑첩은 μ½”λ“œ 가독성을 λ–¨μ–΄λœ¨λ¦΄ 수 μžˆμŠ΅λ‹ˆλ‹€.
  2. μ ‘κ·Ό μ œμ–΄ κ³ λ €ν•˜κΈ°: 쀑첩 νƒ€μž…λ„ private, internal, public λ“±μ˜ μ ‘κ·Ό μ œμ–΄μžλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  3. ν™•μž₯μ„± κ³ λ €: λ‚˜μ€‘μ— νƒ€μž… 관계가 변경될 κ°€λŠ₯성이 μžˆλ‹€λ©΄ μ€‘μ²©λ³΄λ‹€λŠ” λ³„λ„μ˜ νƒ€μž…μœΌλ‘œ μ •μ˜ν•˜λŠ” 것이 쒋을 수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ“Œ Swift ν‘œμ€€ 라이브러리의 쀑첩 νƒ€μž… μ˜ˆμ‹œ

Swift ν‘œμ€€ λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œλ„ 쀑첩 νƒ€μž…μ„ 효과적으둜 ν™œμš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€:

// Array의 쀑첩 νƒ€μž… μ˜ˆμ‹œ
let iterator: Array<Int>.Iterator
let index: Array<Int>.Index

// String의 쀑첩 νƒ€μž… μ˜ˆμ‹œ
let stringIndex: String.Index

πŸ“Œ 정리

쀑첩 νƒ€μž…μ€ Swiftμ—μ„œ μ½”λ“œλ₯Ό λ…Όλ¦¬μ μœΌλ‘œ κ΅¬μ„±ν•˜κ³  κ΄€λ ¨ κΈ°λŠ₯을 κ·Έλ£Ήν™”ν•˜λŠ” λ„κ΅¬μž…λ‹ˆλ‹€. 특히 νŠΉμ • νƒ€μž…μ—μ„œλ§Œ μ‚¬μš©λ˜λŠ” 보쑰 νƒ€μž…μ„ μ •μ˜ν•  λ•Œ μœ μš©ν•˜λ©°, μ½”λ“œμ˜ 가독성과 μœ μ§€λ³΄μˆ˜μ„±μ„ ν–₯μƒμ‹œν‚΅λ‹ˆλ‹€.

λΈ”λž™μž­ μΉ΄λ“œ μ˜ˆμ œμ—μ„œ λ³΄μ•˜λ“―μ΄, 쀑첩 νƒ€μž…μ„ μ‚¬μš©ν•˜λ©΄ μ½”λ“œμ˜ ꡬ쑰가 μ‹€μ œ κ°œλ…μ  λͺ¨λΈμ„ 더 잘 λ°˜μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” μ½”λ“œλ₯Ό 읽고 μ΄ν•΄ν•˜κΈ° μ‰½κ²Œ λ§Œλ“€λ©°, 더 직관적인 APIλ₯Ό μ„€κ³„ν•˜λŠ” 데 도움이 λ©λ‹ˆλ‹€.