iOS/Swift

내가 더 이상 헷갈리기 싫어서 적는 Swift의 핵심 구성 요소

태애니 2025. 5. 1. 19:20
728x90

 

 

내가 맨날 파라미터, 메소드, 함수 등을 제대로 딱 인지 못하고 부르는 것 같아서

(걍 막 냅다 함수라고 쓰거나, 걍 넘긴다 받는다 이런식으로 쓰는게 많아서)

각자의 애들에게 정확한 이름을 확인하기로 했다.

 

1. Property 프로퍼티

클래스, 구조체, 열거형에 속한 값

저장 프로퍼티(Stored Properties) : 값을 저장하는 변수나 상수

계산 프로퍼티(Computed Properties) : 값을 계산하여 반환

타입 프로퍼티(Type Properties) : 인스턴스가 아닌 타입 자체에 속한 프로퍼티

프로퍼티 옵저버(Property Observers) : 프로퍼티 값 변경을 관찰 후 반응

 

struct Person {
    var name: String       // 변수 저장 프로퍼티
    let birthDate: Date    // 상수 저장 프로퍼티
}

struct Circle {
    var radius: Double
    var area: Double {
        get {
            return Double.pi * radius * radius
        }
    }
}

class SomeClass {
    static var typeProperty: Int = 0
}

class StepCounter {
    var totalSteps: Int = 0 {
        willSet {
            print("About to set to \(newValue)")
        }
        didSet {
            print("Added \(totalSteps - oldValue) steps")
        }
    }
}

 

 

2. 메서드 (Methods)

메서드는 특정 타입(클래스, 구조체, 열거형)에 연관된 함수

 

인스턴스 메서드 (Instance Methods)

  • 특정 인스턴스에서 호출하는 메서드
타입 메서드 (Type Methods)
  • 타입 자체에서 호출하는 메서드

mutating 메서드

  • 구조체나 열거형에서 속성을 수정할 수 있는 메서드
class Counter {
    var count = 0
    func increment() { //인스턴스 메서드
        count += 1
    }
}

class Math {
    static func absoluteValue(of number: Int) -> Int { //타입 메서드
        return abs(number)
    }
}

struct Point {
    var x = 0, y = 0
    mutating func moveBy(x deltaX: Int, y deltaY: Int) { // mutating 메서드
        x += deltaX
        y += deltaY
    }
}
 

 

 

3. 함수 (Functions)

함수는 특정 작업을 수행하는 코드 블록. 메서드와 달리 특정 타입에 종속되지않는다.

 
1. 전역 함수
어떤 타입에도 속하지 않는 독립 함수
2. 중첩 함수
다른 함수 내부에 정의된 함수
3. 클로저
이름 없는 함수적 코드 블록 
 
func greet(person: String) -> String { // 전역함수
    return "Hello, \(person)!"
}

func chooseFunction(plus: Bool) -> (Int, Int) -> Int { // 중첩함수
    func addFunction(a: Int, b: Int) -> Int {
        return a + b
    }
    func multiplyFunction(a: Int, b: Int) -> Int {
        return a * b
    }
    return plus ? addFunction : multiplyFunction
}

let numbers = [1, 2, 3, 4] 
let squared = numbers.map { $0 * $0 } // 클로저
 
 
 

3. 파라미터 (Parameters)

함수나 메서드에 전달되는 값 

 

기본 파라미터 (Default Parameters) - 값을 전달하지 않으면 기본값 사용

 

가변 파라미터 (Variadic Parameters) - 여러 값을 받을 수 있음

 

inout 파라미터 - 함수 내에서 수정하면 원본 변수도 수정되는 파라미터

 

내부/외부 파라미터명 (Parameter Labels) - 함수 내부와 호출 시 다른 이름을 사용할 수 있다.

 

// 기본 파라미터
func greet(person: String, greeting: String = "Hello") {
    print("\(greeting), \(person)!")
}

// 가편 파라미터
func sum(_ numbers: Int...) -> Int {
    return numbers.reduce(0, +)
}

// inout 파라미터
func swapValues(_ a: inout Int, _ b: inout Int) {
    let temp = a
    a = b
    b = temp
}

// 내부/외부 파라미터명
func greet(to person: String) { 
    // 내부에서는 person으로 사용
    print("Hello, \(person)!")
}
// 호출 시에는 to 사용
greet(to: "John")

 

 

 


 

잠깐 멘토분과 이야기 하면서

기본 한번 더 짚어보려고 찾아본 것들..

 

 

 

SOLID 원칙

SOLID는 객체 지향 프로그래밍 및 설계의 다섯 가지 기본 원칙을 나타내는 약어.

로버트 C. 마틴(Uncle Bob)이 제안한 이 원칙들은 유지보수가 쉽고 확장 가능한 소프트웨어를 개발하는데 도움이 되는 원칙.

S - 단일 책임 원칙 (Single Responsibility Principle)

원칙: 클래스는 단 하나의 책임만 가져야 한다.

의미: 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.

핵심: 하나의 클래스는 하나의 기능만 담당해야 하며, 그 기능을 완전히 캡슐화해야 한다.

O - 개방-폐쇄 원칙 (Open-Closed Principle)

원칙: 소프트웨어 엔티티는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다.

의미: 기존 코드를 변경하지 않고 새로운 기능을 추가할 수 있어야 한다.

핵심: 인터페이스나 추상 클래스를 통해 기능을 확장할 수 있도록 설계한다.

L - 리스코프 치환 원칙 (Liskov Substitution Principle)

원칙: 부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 대체해도 프로그램의 정확성은 유지되어야 한다.

의미: 자식 클래스는 부모 클래스의 행동을 유지해야 한다.

핵심: 상속 관계에서 자식 클래스는 부모 클래스의 계약을 위반하지 않아야 한다.

I - 인터페이스 분리 원칙 (Interface Segregation Principle)

원칙: 클라이언트는 사용하지 않는 인터페이스에 의존하지 않아야 한다.

의미: 하나의 큰 인터페이스보다 구체적인 여러 개의 인터페이스가 낫다.

핵심: 인터페이스를 클라이언트 별로 분리하여 불필요한 의존성을 제거한다.

D - 의존성 역전 원칙 (Dependency Inversion Principle)

원칙:

  1. 고수준 모듈은 저수준 모듈에 의존해서는 안 됩니다. 둘 다 추상화에 의존해야 한다.
  2. 추상화는 세부 사항에 의존해서는 안 됩니다. 세부 사항이 추상화에 의존해야 한다.

의미: 구체적인 구현보다 인터페이스에 의존하도록 설계해야 한다.

핵심: 의존성 주입을 통해 컴포넌트 간의 결합도를 낮춘다.

SOLID 원칙의 이점

  1. 유지보수성 향상: 코드 변경이 필요할 때 영향 범위가 최소화된다.
  2. 확장성 개선: 새로운 기능을 추가하기 쉬워진다.
  3. 재사용성 증가: 구성 요소를 다른 맥락에서도 사용할 수 있다.
  4. 테스트 용이성: 의존성을 제어할 수 있어 단위 테스트가 쉬워진다.
  5. 코드 복잡성 감소: 각 클래스가 단일 책임을 가지므로 이해하기 쉬워진다.

이러한 원칙들은 좋은 코드 설계의 기본이지만, 상황에 맞게 균형 있게 적용하는 것이 중요하다.

 

728x90