06.09(월) 개인과제 Level4 역할 분리 및 구조 개선 회고

2025. 6. 9. 17:05·🖋️ TIL Journal
-->

2주차 개인 과제의 Level4를 구현하는 도중, 복잡해진 구조를 변경해보았다.
아직 파일 단위로 구조를 잘 나누지 못해서, 함수 단위로 역할 분리를 하며 정리하려고 노력했다.

 

작성한 코드
더보기
//
//  level4.swift
//  Week2Assignment
//
//  Created by 서광용 on 6/5/25.
//

// MARK: - Introducible 프로토콜 정의
protocol Introducible {
    var name: String { get set }
    func introduce() -> String
}

struct StandardLevel4 {
    private static var robot = Robot()
    private static let cat = Cat()
    private static let dog = Dog()

    
    
    static func run() {
        print("\n👉 [필수 문제 4-1] Introducible 소개 메서드 실행 + Robot 변경 로직 테스트")
        level4_1()
        
        print("\n👉 [필수 문제 4-2] Introducible 배열 순회하며 각 타입 고유 메서드 실행")
        level4_2()
    }
    
    private static func level4_1() {
        // Robot 소개 및 이름 변경 확인
        print("<로봇>")
        robot.name = "AI"
        print(robot.introduce())
        
        // Cat 소개
        print("\n<고양이>")
        print(cat.name)
        print(cat.introduce())
        
        // Dog 소개
        print("\n<강아지>")
        print(dog.name)
        print(dog.introduce())
    }
    
    private static func level4_2() {
        // Introducible 배열 생성 후, 각 인스턴스 추가
        var animals: [Introducible] = []
        animals.append(robot)
        animals.append(cat)
        animals.append(dog)
        
        // 배열을 순회하며 타입 캐스팅 후, 각 타입의 고유 메서드 호출
        animals.forEach { animal in
            if let robot = animal as? Robot {
                robot.charge()
            } else if let cat = animal as? Cat {
                cat.scratch()
            } else if let dog = animal as? Dog {
                dog.wagTail()
            }
        }
    }
}

// MARK: - Robot
private struct Robot: Introducible {
    // 이름 변경 감지 및 변경 사항 출력
    var name: String = "로봇" {
        didSet(oldValue) {
            // 변경 이전값과 이후값이 같다면 출력하지 않음
            if name != oldValue {
                print("name 변경 알림")
                print("변경 이전 값: \(oldValue)")
                print("변경 이후 값: \(name)")
            }
        }
    }
    
    func introduce() -> String {
        return "안녕하세요, 저는 \(name)입니다."
    }
    
    // Robot의 고유 메서드
    func charge() {
        print("\(name)가 충전을 시작합니다.")
    }
}

// MARK: - Cat
private struct Cat: Introducible {
    var name: String = "나비"
    
    func introduce() -> String {
        return "고양이 나비"
    }
    
    // Cat의 고유 메서드
    func scratch() {
        print("\(name)가 발톱으로 긁어요!")
    }
}

// MARK: - Dog
private struct Dog: Introducible {
    var name: String = "송이"
    
    func introduce() -> String {
        return "강아지 송이"
    }
    
    // Dog의 고유 메서드
    func wagTail() {
        print("\(name)가 꼬리를 흔들어요.")
    }
}

 

처음에는 Level3처럼 run() 안에서 기능별로 자연스럽게 나눠 호출하게 될 거라고 생각했다.

 

그래서 우선 기능들을 순서대로 구현해나갔고, 하다 보면 나눌 지점이 보이겠지 라고 생각했다.

 

하지만 막상 구현을 끝내고 보니, Robot, Cat, Dog 인스턴스 생성부터 출력, 배열 구성, 타입 캐스팅, 고유 메서드 호출까지 전부 level4_1() 안에 몰려 있는 상태가 되었고, 한눈에 봐도 구조가 복잡해져 있었다.

static func run() {
    level4_1() // 내부에 모든 동작 포함
}

 

방금 전에 했던 Level3에서는 이런 고민 자체가 없었다. 왜 그랬지? 하고 생각해보니, 애초에 요구사항 자체가 하나의 역할만 하도록 a, b, c, d로 나뉘어져 있었다.

 

하지만 level4는 level3와 다르게, 요구사항이 줄글처럼 이어져 하나의 흐름으로 구현되는 느낌이 강했고, 그걸 생각하지 못해 구현을 우선으로 하다보니 정작 구조에는 신경을 못 썼던 것이다.

 


✅ 해결 방법

이런 문제를 해결하기 위해, 구조를 다음과 같이 분리했다:

      1. level4_1( ): Introducible 소개 메서드 실행 + Robot 변경 로직 테스트
      2. level4_2( ):  Introducible 배열 순회하며 각 타입 고유 메서드 실행
static func run() {
    level4_1()
    level4_2()
}

또한, 처음엔 Robot, Cat, Dog 구조체를 level4_1() 함수 내부에서 정의했지만, 이 타입들이 여러 함수에서 공통으로 사용되기 때문에, 파일 최상단으로 분리하여 전체적으로 접근이 가능한 구조로 변경했다.

 


🧠 회고

처음엔 막연하게 구현하다 보면 자연스럽게 Level3처럼 구조가 나뉠 거라 생각했지만, 결국 기능이 한곳에 몰리면서 가독성도 떨어지고 구조도 직관적이지 않게 되었다.

 

사실 요구사항을 처음부터 나눠보고 고민했어야 했는데, 무작정 “일단 시간내에 구현부터 마치자”는 생각에 구조 설계를 우선순위에서 밀어버린 게 컸던 것 같다.

 

이를 통해 구현보다 먼저, 어떻게 나눠서 만들지 고민하는 게 얼마나 중요한지 알게 됐다. 처음부터 역할에 맞게 구조를 잘 나눠두면 전체 흐름도 훨씬 깔끔하고, 기능을 다 구현한 뒤에 다시 고칠 일도 없어진다는 것을 깨달았다.

 

앞으로는 구현 전에 구조부터 고민해보려는 습관을 꼭 들여야겠다는 생각이 들었다.

 

'🖋️ TIL Journal' 카테고리의 다른 글

06.11 (수) Swift 주석 총 정리!  (1) 2025.06.11
06.10 (화) 구문 레이블(Statement Label, outerLoop)  (1) 2025.06.10
06.05 (목) enumerated()가 제네릭에서 안 된다고..?  (1) 2025.06.05
06.04 (수) 열거형(Enum)과 compactMap, flatMap  (0) 2025.06.04
06.02 (월) Closure.. 난 너가 밉다..  (0) 2025.06.02
'🖋️ TIL Journal' 카테고리의 다른 글
  • 06.11 (수) Swift 주석 총 정리!
  • 06.10 (화) 구문 레이블(Statement Label, outerLoop)
  • 06.05 (목) enumerated()가 제네릭에서 안 된다고..?
  • 06.04 (수) 열거형(Enum)과 compactMap, flatMap
MoriOS
MoriOS
기억하기 위해 기록하는 공간 🖋️
  • MoriOS
    MoriOS
    MoriOS
  • 전체
    오늘
    어제
    • 분류 전체보기 (56) N
      • 📌 Swift (10)
      • 📱 iOS (4)
      • 💡 Algorithm (1)
      • ❕Data structure (4)
      • 🪙 Python (0)
      • ⚙️ Git (2)
      • 🖋️ TIL Journal (32) N
      • 📝 Etc (3)
  • 블로그 메뉴

    • GitHub
  • 인기 글

  • 태그

    네비게이션 주석
    addaction
    ios
    시뮬레이터 변경
    swift optional
    swift
    주석 활용
    버튼 액션
    weak
    Codable
    문서화 주석
    TiL
    rawpepresentable
    코코아 프레임워크 이름
    Optional
    cocoa 프레임워크
    swift json
    후행클로저
    Split
    버튼 동작
    아이폰 시뮬레이터 추가
    GitHub
    코코아 프레임워크
    SnapKit
    mark:
    속성 감시자
    Components
    inset
    static
    시뮬레이터 추가
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
MoriOS
06.09(월) 개인과제 Level4 역할 분리 및 구조 개선 회고
상단으로

티스토리툴바