-
//
// AppDelegate.swift
// 930
//
// Created by Induk-cs-9 on 2025/09/30.
//
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}
올려주신 AppDelegate.swift 코드는 iOS 앱의 실행 진입점과 앱의 생명주기를 관리하는 기본 뼈대 소스입니다. Swift + UIKit 기반으로 Xcode에서 새로운 프로젝트를 만들면 자동으로 생성되는 코드예요. 하나씩 설명드릴게요.
📌 주요 구조
1. @main
- Swift 5.3 이후부터는 @UIApplicationMain 대신 @main을 붙여서 이 클래스가 앱 실행의 시작점임을 표시합니다.
- 즉, iOS가 앱을 실행하면 여기서부터 시작돼요.
2. class AppDelegate: UIResponder, UIApplicationDelegate
- AppDelegate 클래스는 앱 전반의 이벤트(실행, 종료, 백그라운드 전환 등)를 관리합니다.
- UIResponder: 이벤트(터치, 키보드 등)를 처리할 수 있게 하는 UIKit 클래스.
- UIApplicationDelegate: 앱의 상태 변화를 감지하고 대응하는 메서드를 정의하는 프로토콜.
📌 메서드별 설명
func application(_:didFinishLaunchingWithOptions:) -> Bool
- 앱이 실행되고 초기 설정을 마친 직후 호출됩니다.
- 앱 시작 시 초기화 작업을 여기에 넣습니다.
(예: Firebase 설정, UserDefaults 초기값 세팅, 로그 출력 등) - 기본값은 return true → 앱 정상 실행.
func application(_:configurationForConnecting:options:) -> UISceneConfiguration
- iOS 13 이후 멀티 윈도우/Scene 지원이 추가되면서 생긴 메서드.
- 새로운 Scene(화면)이 생성될 때 어떤 설정(UISceneConfiguration)을 쓸지 결정합니다.
- 여기서는 "Default Configuration"이라는 기본 설정을 씁니다.
func application(_:didDiscardSceneSessions:)
- 사용자가 열었던 Scene을 닫았을 때 호출됩니다.
- 닫힌 화면(Scene)과 관련된 리소스를 정리할 때 사용합니다.
- 기본 템플릿에서는 비워져 있어요.
📌 왜 두 번 써 있나?
지금 붙여주신 코드에는 동일한 AppDelegate.swift 내용이 두 번 반복되어 있습니다.
아마 복사/붙여넣기 과정에서 중복된 것 같아요. 실제로는 한 번만 존재해야 합니다.
✅ 요약
- 이 코드는 iOS 앱 실행의 기본 틀을 제공하는 AppDelegate.swift.
- 앱이 실행 → Scene(윈도우/화면) 생성 → Scene 닫힘 과정을 담당.
- 현재 상태는 Xcode가 자동 생성한 기본 템플릿이며, 직접 기능을 추가하기 전의 초기 상태.
//
// SceneDelegate.swift
// 930
//
// Created by Induk-cs-9 on 2025/09/30.
//
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}
다음 코드는 UIKit + 멀티-씬(iOS 13+) 환경에서 한 “화면 단위(=Scene)”의 생명주기를 관리하는 SceneDelegate 기본 템플릿입니다. 한 줄씩보단, 역할→메서드별 시점→실전에서 무엇을 넣는지 순서로 정리해 드릴게요.
SceneDelegate의 역할 한눈에
- AppDelegate: 앱 전체(푸시, 백그라운드 진입, 공통 설정 등)의 관문.
- SceneDelegate: 하나의 창(Window)/화면(Scene) 에 대한 생명주기 관리.
- iPad나 iPhone(iOS 13+)에서 여러 창을 띄울 수 있는데, 각 창마다 SceneDelegate 인스턴스가 별도로 생깁니다.
핵심 속성
var window: UIWindow?- 이 Scene이 사용할 UI 창.
- 스토리보드를 쓰는 경우: 시스템이 알아서 만들고 연결합니다(Info.plist의 Application Scene Manifest 설정 기반).
- 스토리보드 없이 코드로 시작하면, willConnectTo에서 직접 생성·연결해야 합니다(예시 아래 참고).
메서드별 시점과 용도
1) scene(_:willConnectTo:options:)
- 장면이 처음 연결될 때 단 한 번 호출.
- 여기서 UI를 구성합니다.
- 스토리보드 사용 시: 템플릿 그대로 둬도 됨(자동 연결).
- 코드로 시작 시: 여기서 window를 만들고 rootViewController를 지정.
코드 UI 시작 예시(스토리보드 미사용 시)
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } let window = UIWindow(windowScene: windowScene) window.rootViewController = UINavigationController(rootViewController: YourRootVC()) self.window = window window.makeKeyAndVisible() }- 잊기 쉬운 포인트: makeKeyAndVisible() 안 하면 검은 화면이 나옵니다.
또한 connectionOptions에는 유니버설 링크/URL 열기, 푸시로 진입 같은 “처음 연결 시 전달된 컨텍스트”가 들어오므로, 첫 화면 라우팅에 활용합니다.
2) sceneDidDisconnect(_:)
- 이 Scene이 시스템에 의해 해제될 때 (완전히 사라질 때) 호출.
- 장면이 사라지며 메모리 정리·리소스 해제 시 사용.
- 나중에 같은 세션이 다시 연결될 수도 있음(사용자/시스템 동작에 따라).
3) sceneDidBecomeActive(_:)
- Scene이 active(전면 상호작용 가능 상태) 로 진입했을 때.
- 일시정지했던 타이머 재개, 애니메이션 재시작, 센서 접근 재개 등 화면이 살아났을 때의 작업.
4) sceneWillResignActive(_:)
- Scene이 inactive 로 가기 직전(전화/알림, 멀티태스킹 전환 등 일시 중단 가능성).
- 게임 일시정지, 중요한 작업의 커밋/세이브 포인트 남기기 등 잠깐 멈춤 준비.
5) sceneWillEnterForeground(_:)
- 백그라운드 → 포어그라운드 전환 직전.
- 백그라운드 동안 바뀐 데이터 반영 준비, UI 업데이트 예약 등.
6) sceneDidEnterBackground(_:)
- 포어그라운드 → 백그라운드 전환 직후.
- 데이터 저장, 스냅샷/상태 보존, 공유 리소스 해제 등 반드시 백업이 필요한 로직을 넣습니다.
(앱이 종료돼도 복구 가능하도록 필요한 최소 상태를 디스크에 저장)
AppDelegate와의 역할 분담(요약)
- AppDelegate: 푸시 등록, 백그라운드 작업(앱 전체), 전역 설정(Firebase, 로깅 초기화 등).
- SceneDelegate: 각 창(화면)의 UI 구성/상태 보존, 활성/비활성 전환 대응.
- 멀티-씬이 아닌 단일 창 앱이라도 iOS 13+ 타겟이면 Scene 구조가 기본이므로 위 훅들을 쓰게 됩니다.
자주 겪는 문제 & 팁
- 검은 화면만 보임
- 스토리보드 미사용인데 willConnectTo에서 window 생성/makeKeyAndVisible() 누락.
- 루트 화면이 매번 초기화됨
- 상태 보존을 sceneDidEnterBackground에서 디스크에 저장하고, willConnectTo에서 복원하는 로직을 추가하세요.
- URL/유니버설 링크 최초 진입 분기
- willConnectTo의 connectionOptions를 확인해 초기 라우팅을 처리하고,
- 이미 실행 중 장면에서의 URL 열기는 scene(_:openURLContexts:)(필요 시 구현)로 처리합니다.
- 여러 창(iPad) 지원
- 각 Scene마다 SceneDelegate가 따로 동작. 전역 싱글턴을 남발하기보다 Scene 단위 의존성 주입을 고려하세요.
한 줄 요약
- 이 파일은 “한 화면(Scene)”의 생명주기를 관리하는 델리게이트입니다.
- UI 최초 구성은 willConnectTo,
상태 저장은 sceneDidEnterBackground,
재개/일시중지는 sceneDidBecomeActive/sceneWillResignActive 에 넣는 것이 정석입니다.
다음 코드는 UIKit + 멀티-씬(iOS 13+) 환경에서 한 “화면 단위(=Scene)”의 생명주기를 관리하는 SceneDelegate 기본 템플릿입니다. 한 줄씩보단, 역할→메서드별 시점→실전에서 무엇을 넣는지 순서로 정리해 드릴게요.
SceneDelegate의 역할 한눈에
- AppDelegate: 앱 전체(푸시, 백그라운드 진입, 공통 설정 등)의 관문.
- SceneDelegate: 하나의 창(Window)/화면(Scene) 에 대한 생명주기 관리.
- iPad나 iPhone(iOS 13+)에서 여러 창을 띄울 수 있는데, 각 창마다 SceneDelegate 인스턴스가 별도로 생깁니다.
핵심 속성
var window: UIWindow?- 이 Scene이 사용할 UI 창.
- 스토리보드를 쓰는 경우: 시스템이 알아서 만들고 연결합니다(Info.plist의 Application Scene Manifest 설정 기반).
- 스토리보드 없이 코드로 시작하면, willConnectTo에서 직접 생성·연결해야 합니다(예시 아래 참고).
메서드별 시점과 용도
1) scene(_:willConnectTo:options:)
- 장면이 처음 연결될 때 단 한 번 호출.
- 여기서 UI를 구성합니다.
- 스토리보드 사용 시: 템플릿 그대로 둬도 됨(자동 연결).
- 코드로 시작 시: 여기서 window를 만들고 rootViewController를 지정.
코드 UI 시작 예시(스토리보드 미사용 시)
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } let window = UIWindow(windowScene: windowScene) window.rootViewController = UINavigationController(rootViewController: YourRootVC()) self.window = window window.makeKeyAndVisible() }- 잊기 쉬운 포인트: makeKeyAndVisible() 안 하면 검은 화면이 나옵니다.
또한 connectionOptions에는 유니버설 링크/URL 열기, 푸시로 진입 같은 “처음 연결 시 전달된 컨텍스트”가 들어오므로, 첫 화면 라우팅에 활용합니다.
2) sceneDidDisconnect(_:)
- 이 Scene이 시스템에 의해 해제될 때 (완전히 사라질 때) 호출.
- 장면이 사라지며 메모리 정리·리소스 해제 시 사용.
- 나중에 같은 세션이 다시 연결될 수도 있음(사용자/시스템 동작에 따라).
3) sceneDidBecomeActive(_:)
- Scene이 active(전면 상호작용 가능 상태) 로 진입했을 때.
- 일시정지했던 타이머 재개, 애니메이션 재시작, 센서 접근 재개 등 화면이 살아났을 때의 작업.
4) sceneWillResignActive(_:)
- Scene이 inactive 로 가기 직전(전화/알림, 멀티태스킹 전환 등 일시 중단 가능성).
- 게임 일시정지, 중요한 작업의 커밋/세이브 포인트 남기기 등 잠깐 멈춤 준비.
5) sceneWillEnterForeground(_:)
- 백그라운드 → 포어그라운드 전환 직전.
- 백그라운드 동안 바뀐 데이터 반영 준비, UI 업데이트 예약 등.
6) sceneDidEnterBackground(_:)
- 포어그라운드 → 백그라운드 전환 직후.
- 데이터 저장, 스냅샷/상태 보존, 공유 리소스 해제 등 반드시 백업이 필요한 로직을 넣습니다.
(앱이 종료돼도 복구 가능하도록 필요한 최소 상태를 디스크에 저장)
AppDelegate와의 역할 분담(요약)
- AppDelegate: 푸시 등록, 백그라운드 작업(앱 전체), 전역 설정(Firebase, 로깅 초기화 등).
- SceneDelegate: 각 창(화면)의 UI 구성/상태 보존, 활성/비활성 전환 대응.
- 멀티-씬이 아닌 단일 창 앱이라도 iOS 13+ 타겟이면 Scene 구조가 기본이므로 위 훅들을 쓰게 됩니다.
자주 겪는 문제 & 팁
- 검은 화면만 보임
- 스토리보드 미사용인데 willConnectTo에서 window 생성/makeKeyAndVisible() 누락.
- 루트 화면이 매번 초기화됨
- 상태 보존을 sceneDidEnterBackground에서 디스크에 저장하고, willConnectTo에서 복원하는 로직을 추가하세요.
- URL/유니버설 링크 최초 진입 분기
- willConnectTo의 connectionOptions를 확인해 초기 라우팅을 처리하고,
- 이미 실행 중 장면에서의 URL 열기는 scene(_:openURLContexts:)(필요 시 구현)로 처리합니다.
- 여러 창(iPad) 지원
- 각 Scene마다 SceneDelegate가 따로 동작. 전역 싱글턴을 남발하기보다 Scene 단위 의존성 주입을 고려하세요.
한 줄 요약
- 이 파일은 “한 화면(Scene)”의 생명주기를 관리하는 델리게이트입니다.
- UI 최초 구성은 willConnectTo,
상태 저장은 sceneDidEnterBackground,
재개/일시중지는 sceneDidBecomeActive/sceneWillResignActive 에 넣는 것이 정석입니다.
올려주신 ViewController.swift는 iOS 앱에서 하나의 화면(뷰 컨트롤러)을 담당하는 기본 뼈대 코드예요. 새로운 프로젝트를 만들면 자동으로 생성되는 파일이고, 앱의 첫 화면을 담당하는 클래스라고 보면 됩니다. 하나씩 풀어서 설명해 드릴게요.
📌 파일 정보
// // ViewController.swift // 930 // // Created by Induk-cs-9 on 2025/09/30. //- 파일명: ViewController.swift
- 프로젝트명: 930
- 작성자/생성일자: Induk-cs-9, 2025/09/30
📌 클래스 정의
import UIKit class ViewController: UIViewController { ... }- import UIKit
→ iOS UI를 만들기 위한 기본 프레임워크를 가져옵니다. 버튼, 화면 전환 등 UI 관련 요소를 쓸 수 있게 해줍니다. - class ViewController: UIViewController
→ ViewController는 UIViewController를 상속받은 클래스입니다.
→ 즉, iOS 화면을 담당하는 컨트롤러 객체로서, 뷰(화면 요소)를 관리합니다.
→ MVC(Model-View-Controller) 구조에서 Controller 역할.
📌 생명주기 메서드
override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. }- viewDidLoad()
→ 뷰 컨트롤러의 화면이 메모리에 로드된 직후(처음 생성될 때 한 번) 호출됩니다.
→ 보통 여기에서 초기화 코드를 작성합니다.- UI 요소 속성 설정
- 데이터 불러오기
- 네트워크 통신 준비 등
- super.viewDidLoad()
→ 부모 클래스(UIViewController)의 viewDidLoad()도 실행시켜 기본 동작을 보장합니다. - // Do any additional setup...
→ “추가 작업을 여기에 작성하세요”라는 의미의 기본 주석입니다.
→ 예를 들어 버튼을 만들거나, 배경색을 바꾸고 싶다면 이곳에서 작성합니다.
📌 특징
- 현재는 아무 기능이 없는 빈 화면 상태.
- Xcode 기본 템플릿이라서 실제 동작은 안 하지만, 여기에 코드를 추가하면서 앱의 기능이 구현됩니다.
- 같은 코드가 두 번 반복되어 붙여주셨는데, 실제 프로젝트에는 한 번만 존재해야 합니다.
✅ 정리
- ViewController.swift = 앱의 첫 화면을 담당하는 기본 컨트롤러 클래스.
- viewDidLoad()는 화면이 처음 로드될 때 불리며, UI 초기화나 데이터 준비 코드를 넣는 곳.
- 현재는 아무 기능도 없고, 개발자가 여기에 직접 기능을 추가해야 합니다.









import Foundation
func calcBMI(weight: Double, height: Double) -> String {
// BMI 계산 (kg / m^2)
let bmi = weight / (height * height * 0.0001)
let shortenedBmi = String(format: "%.1f", bmi)
var body = ""
if bmi >= 40 {
body = "3단계 비만"
} else if bmi >= 30 {
body = "2단계 비만"
} else if bmi >= 25 {
body = "1단계 비만"
} else if bmi >= 18.5 {
body = "정상"
} else {
body = "저체중"
}
return "BMI:\(shortenedBmi), 판정:\(body)"
}
var x = calcBMI(weight: 60.0, height: 170.0)
print(x)

지금 보여주신 소스는 Swift에서 함수(Function)가 “일급 객체(first-class citizen)”라는 것을 보여주는 예제예요.
즉, 함수 자체를 값처럼 변수/상수에 저장하고, 다른 함수에 전달하거나 반환할 수 있다는 걸 확인하는 코드예요.
🔎 코드 흐름 설명
func up(num: Int) -> Int { return num + 1 } func down(num: Int) -> Int { return num - 1 }- up: 전달받은 정수에 +1 해서 반환
- down: 전달받은 정수에 -1 해서 반환
let toUp = up- up 함수 자체를 변수처럼 할당.
- 이때 toUp은 (Int) -> Int 타입의 함수가 됨.
print(up(num:10)) // 결과: 11 print(toUp(10)) // 결과: 11- up(num: 10)처럼 argument label(num:)을 써서 호출 가능.
- 하지만 toUp(10)처럼, 변수에 저장한 함수 호출 시에는 argument label을 쓰지 않음.
(Swift에서 함수 참조를 변수에 담으면, 파라미터 이름(label) 이 빠지고 타입 시그니처만 남습니다.)
let toDown = down- down 함수도 똑같이 변수에 저장 가능.
- toDown(10) → 9를 반환.
✅ 정리
- 이 소스는 “Swift에서 함수는 값처럼 변수에 담을 수 있다”는 일급 객체 개념을 보여줌.
- 함수 타입도 다른 타입(Int, String 등)과 똑같이 취급 가능.
- toUp과 toDown 같은 변수는 Int → Int 함수 타입을 가지게 되고, 그대로 호출 가능.
👉 만약 이 코드를 확장하면, let actions: [(Int) -> Int] = [up, down] 같은 식으로 함수 배열을 만들어 루프 돌면서 여러 함수를 적용할 수도 있어요.지금 보여주신 소스는 Swift에서 함수(Function)가 “일급 객체(first-class citizen)”라는 것을 보여주는 예제예요.
즉, 함수 자체를 값처럼 변수/상수에 저장하고, 다른 함수에 전달하거나 반환할 수 있다는 걸 확인하는 코드예요.
🔎 코드 흐름 설명
func up(num: Int) -> Int { return num + 1 } func down(num: Int) -> Int { return num - 1 }- up: 전달받은 정수에 +1 해서 반환
- down: 전달받은 정수에 -1 해서 반환
let toUp = up- up 함수 자체를 변수처럼 할당.
- 이때 toUp은 (Int) -> Int 타입의 함수가 됨.
print(up(num:10)) // 결과: 11 print(toUp(10)) // 결과: 11- up(num: 10)처럼 argument label(num:)을 써서 호출 가능.
- 하지만 toUp(10)처럼, 변수에 저장한 함수 호출 시에는 argument label을 쓰지 않음.
(Swift에서 함수 참조를 변수에 담으면, 파라미터 이름(label) 이 빠지고 타입 시그니처만 남습니다.)
let toDown = down- down 함수도 똑같이 변수에 저장 가능.
- toDown(10) → 9를 반환.
✅ 정리
- 이 소스는 “Swift에서 함수는 값처럼 변수에 담을 수 있다”는 일급 객체 개념을 보여줌.
- 함수 타입도 다른 타입(Int, String 등)과 똑같이 취급 가능.
- toUp과 toDown 같은 변수는 Int → Int 함수 타입을 가지게 되고, 그대로 호출 가능.
👉 만약 이 코드를 확장하면, let actions: [(Int) -> Int] = [up, down] 같은 식으로 함수 배열을 만들어 루프 돌면서 여러 함수를 적용할 수도 있어요.지금 보여주신 소스는 Swift에서 함수(Function)가 “일급 객체(first-class citizen)”라는 것을 보여주는 예제예요.
즉, 함수 자체를 값처럼 변수/상수에 저장하고, 다른 함수에 전달하거나 반환할 수 있다는 걸 확인하는 코드예요.
🔎 코드 흐름 설명
func up(num: Int) -> Int { return num + 1 } func down(num: Int) -> Int { return num - 1 }- up: 전달받은 정수에 +1 해서 반환
- down: 전달받은 정수에 -1 해서 반환
let toUp = up- up 함수 자체를 변수처럼 할당.
- 이때 toUp은 (Int) -> Int 타입의 함수가 됨.
print(up(num:10)) // 결과: 11 print(toUp(10)) // 결과: 11- up(num: 10)처럼 argument label(num:)을 써서 호출 가능.
- 하지만 toUp(10)처럼, 변수에 저장한 함수 호출 시에는 argument label을 쓰지 않음.
(Swift에서 함수 참조를 변수에 담으면, 파라미터 이름(label) 이 빠지고 타입 시그니처만 남습니다.)
let toDown = down- down 함수도 똑같이 변수에 저장 가능.
- toDown(10) → 9를 반환.
✅ 정리
- 이 소스는 “Swift에서 함수는 값처럼 변수에 담을 수 있다”는 일급 객체 개념을 보여줌.
- 함수 타입도 다른 타입(Int, String 등)과 똑같이 취급 가능.
- toUp과 toDown 같은 변수는 Int → Int 함수 타입을 가지게 되고, 그대로 호출 가능.
👉 만약 이 코드를 확장하면, let actions: [(Int) -> Int] = [up, down] 같은 식으로 함수 배열을 만들어 루프 돌면서 여러 함수를 적용할 수도 있어요.

func up(num: Int) -> Int {
return num + 1
}
func down(num: Int) -> Int {
return num - 1
}
let toUp = up
print(up(num:10))
print(toUp(10))
let toDown = down
func upDown(Fun: (Int) -> Int, value: Int) {
let result = Fun(value)
print("결과 = \(result)")
}
print(type(of: upDown)) // ((Int) -> Int, Int) -> ()
upDown(Fun:toUp, value: 10) //toUp(10)
upDown(Fun:toDown, value: 10) //toDown(10)
**고차 함수(Higher-order function)**를 많이 활용하는 언어들은 보통 **함수를 값처럼 다루는 것(일급 객체)**을 지원하는 함수형 프로그래밍 언어들이에요. 다만 “많이 사용한다”의 기준을 언어 철학과 실제 프로그래밍 스타일을 기준으로 정리해 드릴게요.
📌 고차 함수를 많이 사용하는 언어 (순서대로)
1. Haskell
- 순수 함수형 프로그래밍 언어.
- 모든 것이 함수 중심으로 되어 있음 → 고차 함수는 기본기.
- 예:
-
-- map: 리스트의 각 원소에 함수 적용 map (*2) [1,2,3] -- 결과: [2,4,6] -- filter: 조건을 만족하는 원소만 선택 filter (>2) [1,2,3,4] -- 결과: [3,4]
- Haskell에서는 반복문(for/while)이 거의 없고, map / filter / fold 같은 고차 함수를 기본으로 씁니다.
2. Scala
- JVM 위에서 돌아가는 함수형 + 객체지향 혼합 언어.
- Java보다 훨씬 람다와 고차 함수 사용이 자연스러움.
- 예:
-
val nums = List(1,2,3,4) val doubled = nums.map(_ * 2) // [2,4,6,8] val evens = nums.filter(_ % 2 == 0) // [2,4] val sum = nums.reduce(_ + _) // 10
3. JavaScript
- 웹 개발에서 가장 흔히 접하는 실용적인 함수형 스타일 언어.
- 배열 메서드(map, filter, reduce 등)를 거의 모든 곳에서 씀.
- 예:
-
const nums = [1,2,3,4]; const doubled = nums.map(x => x * 2); // [2,4,6,8] const evens = nums.filter(x => x % 2 === 0); // [2,4] const sum = nums.reduce((a,b) => a+b, 0); // 10
4. Python
- 원래 절차적/객체지향 중심이지만, 람다와 고차 함수 지원.
- 특히 map, filter, reduce (functools), 그리고 list comprehension.
- 예:
-
nums = [1,2,3,4] doubled = list(map(lambda x: x*2, nums)) # [2,4,6,8] evens = list(filter(lambda x: x%2==0, nums)) # [2,4] from functools import reduce sum_all = reduce(lambda a,b: a+b, nums) # 10
5. Swift
- 함수가 일급 객체 → 고차 함수 적극 지원.
- map, filter, reduce, compactMap, flatMap 자주 사용.
- 예:
-
let nums = [1,2,3,4] let doubled = nums.map { $0 * 2 } // [2,4,6,8] let evens = nums.filter { $0 % 2 == 0 } // [2,4] let sum = nums.reduce(0, +) // 10
6. Kotlin
- Android 개발에 많이 쓰는 언어, Java보다 함수형 지원이 훨씬 강력.
- 예:
-
val nums = listOf(1,2,3,4) val doubled = nums.map { it * 2 } // [2,4,6,8] val evens = nums.filter { it % 2 == 0 } // [2,4] val sum = nums.reduce { acc, i -> acc + i } // 10
📊 정리 (많이 사용하는 정도 순서)
- Haskell → 순수 함수형, 고차 함수 필수
- Scala → 함수형+OOP 혼합, 강력한 컬렉션 함수
- JavaScript → 실용적으로 map/filter/reduce 일상적 사용
- Python → 지원은 하지만 list comprehension도 자주 씀
- Swift → iOS 개발에서 컬렉션 처리에 고차 함수 상시 사용
- Kotlin → Android 개발에서 적극 활용, Java 대체 언어
✅ 결론:
- 함수형 언어일수록 고차 함수 사용이 기본 문법이고,
- **실용 언어(JavaScript, Python, Swift, Kotlin)**에서도 컬렉션 다룰 때 거의 반드시 쓰이는 핵심 도구예요.

좋습니다 👍
클로저(Closure) 는 "함수가 자신이 생성될 당시의 환경(변수·상태) 를 캡처해서 나중에도 쓸 수 있는 기능"을 말해요.
언어에 따라 클로저 활용도가 다르기 때문에, 많이 쓰는 정도 → 예제 코드로 순서 정리해 드릴게요.
📌 클로저 많이 사용하는 언어 순서 & 예제
1. JavaScript (가장 대표적)
- 클로저는 JS 동작 원리의 핵심.
- 이벤트 핸들러, 비동기 콜백, 모듈 패턴 등에 항상 쓰임.
function makeCounter() { let count = 0; return function() { // 클로저 count++; return count; } } const counter = makeCounter(); console.log(counter()); // 1 console.log(counter()); // 2
2. Swift
- 함수형 문법과 iOS 개발 특성상 클로저 사용이 매우 빈번.
- 고차함수(map, filter, reduce) + UI 이벤트 핸들러에서 필수.
let numbers = [1, 2, 3, 4] let doubled = numbers.map { (num: Int) -> Int in return num * 2 } print(doubled) // [2,4,6,8] func makeCounter() -> () -> Int { var count = 0 return { count += 1 return count } } let counter = makeCounter() print(counter()) // 1 print(counter()) // 2
3. Python
- 람다 + 클로저 조합을 지원. 데코레이터나 함수 팩토리 구현에서 많이 사용.
def make_counter(): count = 0 def counter(): nonlocal count # 바깥 스코프 변수 캡처 count += 1 return count return counter c = make_counter() print(c()) # 1 print(c()) # 2
4. Kotlin
- 람다와 함께 클로저 자연스럽게 사용. Android 개발에서 이벤트 처리, DSL 문법 등에 활용.
fun makeCounter(): () -> Int { var count = 0 return { count += 1 count } } val counter = makeCounter() println(counter()) // 1 println(counter()) // 2
5. Scala
- 함수형 언어답게 클로저를 지원하고, 컬렉션 처리에서 고차함수와 함께 자주 사용.
def makeCounter(): () => Int = { var count = 0 () => { count += 1; count } } val counter = makeCounter() println(counter()) // 1 println(counter()) // 2
6. Ruby
- 블록/Proc/Lambda 형태로 클로저 구현. 반복문, DSL 등에서 자주 쓰임.
def make_counter count = 0 return Proc.new { count += 1 } end counter = make_counter puts counter.call # 1 puts counter.call # 2
📊 정리 (사용 빈도 순서)
- JavaScript → 웹/비동기/이벤트에서 클로저가 사실상 필수
- Swift → iOS 개발에서 클로저가 표준 문법처럼 사용됨
- Python → 데코레이터, 팩토리 패턴 등에서 핵심 활용
- Kotlin → 안드로이드 개발에서 람다+클로저 조합 흔함
- Scala → 함수형 스타일로 자주 쓰지만 실무는 다소 제한적
- Ruby → 블록/Proc 덕분에 활용 많지만 최근은 감소 추세
✅ 요약:
- JavaScript와 Swift는 클로저 없이는 프로그래밍이 힘들 정도로 핵심적.
- Python/Kotlin은 함수형 스타일이나 패턴 구현에서 필수.
- Scala/Ruby는 함수형·DSL 문법 쓸 때 자연스럽게 활용.
좋습니다 👍
클로저(Closure) 는 "함수가 자신이 생성될 당시의 환경(변수·상태) 를 캡처해서 나중에도 쓸 수 있는 기능"을 말해요.
언어에 따라 클로저 활용도가 다르기 때문에, 많이 쓰는 정도 → 예제 코드로 순서 정리해 드릴게요.
📌 클로저 많이 사용하는 언어 순서 & 예제
1. JavaScript (가장 대표적)
- 클로저는 JS 동작 원리의 핵심.
- 이벤트 핸들러, 비동기 콜백, 모듈 패턴 등에 항상 쓰임.
function makeCounter() { let count = 0; return function() { // 클로저 count++; return count; } } const counter = makeCounter(); console.log(counter()); // 1 console.log(counter()); // 2
2. Swift
- 함수형 문법과 iOS 개발 특성상 클로저 사용이 매우 빈번.
- 고차함수(map, filter, reduce) + UI 이벤트 핸들러에서 필수.
let numbers = [1, 2, 3, 4] let doubled = numbers.map { (num: Int) -> Int in return num * 2 } print(doubled) // [2,4,6,8] func makeCounter() -> () -> Int { var count = 0 return { count += 1 return count } } let counter = makeCounter() print(counter()) // 1 print(counter()) // 2
3. Python
- 람다 + 클로저 조합을 지원. 데코레이터나 함수 팩토리 구현에서 많이 사용.
def make_counter(): count = 0 def counter(): nonlocal count # 바깥 스코프 변수 캡처 count += 1 return count return counter c = make_counter() print(c()) # 1 print(c()) # 2
4. Kotlin
- 람다와 함께 클로저 자연스럽게 사용. Android 개발에서 이벤트 처리, DSL 문법 등에 활용.
fun makeCounter(): () -> Int { var count = 0 return { count += 1 count } } val counter = makeCounter() println(counter()) // 1 println(counter()) // 2
5. Scala
- 함수형 언어답게 클로저를 지원하고, 컬렉션 처리에서 고차함수와 함께 자주 사용.
def makeCounter(): () => Int = { var count = 0 () => { count += 1; count } } val counter = makeCounter() println(counter()) // 1 println(counter()) // 2
6. Ruby
- 블록/Proc/Lambda 형태로 클로저 구현. 반복문, DSL 등에서 자주 쓰임.
def make_counter count = 0 return Proc.new { count += 1 } end counter = make_counter puts counter.call # 1 puts counter.call # 2
📊 정리 (사용 빈도 순서)
- JavaScript → 웹/비동기/이벤트에서 클로저가 사실상 필수
- Swift → iOS 개발에서 클로저가 표준 문법처럼 사용됨
- Python → 데코레이터, 팩토리 패턴 등에서 핵심 활용
- Kotlin → 안드로이드 개발에서 람다+클로저 조합 흔함
- Scala → 함수형 스타일로 자주 쓰지만 실무는 다소 제한적
- Ruby → 블록/Proc 덕분에 활용 많지만 최근은 감소 추세
✅ 요약:
- JavaScript와 Swift는 클로저 없이는 프로그래밍이 힘들 정도로 핵심적.
- Python/Kotlin은 함수형 스타일이나 패턴 구현에서 필수.
- Scala/Ruby는 함수형·DSL 문법 쓸 때 자연스럽게 활용.
스위프트에서 클로저는 정말 많이 쓰이는데, 크게 나누면 컬렉션 처리(map, filter, reduce), 비동기 처리(Completion Handler), UI 이벤트 처리에서 가장 자주 등장합니다. 각각 예를 들어드릴게요.
1️⃣ 컬렉션 처리 – map, filter, reduce
스위프트 컬렉션은 고차함수를 제공하고, 여기서 클로저를 거의 항상 사용합니다.
let numbers = [1, 2, 3, 4, 5] // map: 각 요소를 2배로 변환 let doubled = numbers.map { $0 * 2 } // [2, 4, 6, 8, 10] // filter: 짝수만 걸러냄 let evens = numbers.filter { $0 % 2 == 0 } // [2, 4] // reduce: 모든 요소 합산 let sum = numbers.reduce(0) { $0 + $1 } // 15👉 이런 경우, {$0, $1} 같은 간단한 표현식 클로저가 가장 흔히 쓰입니다.
iOS 개발자라면 거의 매일 보게 되는 패턴이에요.
2️⃣ 비동기 처리 – Completion Handler
네트워크 요청, 파일 읽기, 애니메이션 종료 처리 등에 콜백으로 클로저를 자주 사용합니다.
func fetchData(completion: @escaping (String) -> Void) { // 네트워크 요청 가정 DispatchQueue.global().async { let data = "서버에서 받은 데이터" DispatchQueue.main.async { completion(data) // 요청 끝나면 클로저 실행 } } } fetchData { result in print("결과: \(result)") }👉 여기서 클로저는 **“작업이 끝나면 실행할 코드”**를 담고 있어,
비동기 프로그래밍의 핵심 역할을 합니다.
3️⃣ UI 이벤트 처리 – 버튼 액션
UIKit/SwiftUI에서 이벤트 핸들러로도 클로저를 많이 씁니다.
UIKit 예시:
let button = UIButton(type: .system) button.setTitle("누르기", for: .normal) // UIAction에 클로저 전달 button.addAction(UIAction { _ in print("버튼 눌림!") }, for: .touchUpInside)SwiftUI 예시:
Button("누르기") { print("SwiftUI 버튼 눌림!") }👉 이벤트가 발생했을 때 실행할 코드를 클로저로 직접 전달하는 방식이라
UI 프로그래밍에서 매우 자연스럽게 쓰입니다.
✅ 정리
스위프트에서 클로저를 가장 많이 사용하는 대표적인 경우는:
- 컬렉션 처리 (map, filter, reduce) – 데이터 변환/가공
- 비동기 Completion Handler – 네트워크, 애니메이션, 타이머 등
- UI 이벤트 처리 – 버튼 액션, 제스처, SwiftUI 뷰 빌더
iOS 앱을 만들 때 Swift에서는 **구조체(struct)**와 클래스(class) 둘 다 쓸 수 있는데, 언제 무엇을 선택하느냐가 중요한 설계 포인트입니다.
📌 Swift에서 구조체 vs 클래스의 차이 핵심
구분구조체 (struct)클래스 (class)타입 값 타입 (Value type) 참조 타입 (Reference type) 메모리 복사 변수/상수에 대입하면 복사본 생성 변수/상수에 대입하면 같은 인스턴스 참조 상속 ❌ 불가능 ✅ 가능 Equatable/Hashable 기본 제공 (속성 기반 비교 쉬움) 직접 구현 필요 성능 작은 데이터, 불변(immutable) 성격일 때 효율적 공유/상속 구조가 필요할 때 유리 UIKit/SwiftUI 연동 주로 struct (SwiftUI View) UIKit 객체 대부분 class (UIView, UIViewController 등)
📌 언제 구조체(struct)를 쓰는 게 좋은가?
👉 데이터 모델처럼 "값"을 표현할 때
- 단순히 데이터를 담고 전달하는 역할
- 값이 바뀌면 "새로운 값"으로 취급하는 게 자연스러울 때
- 동시성/스레드 환경에서 안전하게 쓰고 싶을 때 (복사되니까 공유 문제 적음)
예시:
struct User { let id: Int var name: String } var user1 = User(id: 1, name: "Alice") var user2 = user1 // 값 복사 user2.name = "Bob" print(user1.name) // Alice (영향 없음) print(user2.name) // Bob👉 SwiftUI에서 View를 만들 때 struct를 쓰는 이유도 여기에 있어요.
struct는 값 타입이라 변경에 안전하고, 새로운 뷰로 쉽게 교체 가능.
📌 언제 클래스(class)를 쓰는 게 좋은가?
👉 참조/공유/상속이 필요한 경우
- 여러 곳에서 같은 인스턴스를 공유해야 할 때
- UIKit에서 제공하는 API 대부분이 클래스 기반 (UIViewController, UIView 등)
- 객체의 수명(lifecycle) 관리가 필요한 경우
- 상속을 활용해야 하는 경우
예시:
class Dog { var name: String init(name: String) { self.name = name } } var dog1 = Dog(name: "Choco") var dog2 = dog1 // 같은 참조 dog2.name = "Cookie" print(dog1.name) // Cookie (dog1, dog2가 같은 객체를 가리킴)👉 UIKit 앱 개발에서는 거의 대부분 class를 써야 합니다.
뷰, 뷰컨트롤러, 앱 델리게이트 같은 것들이 다 클래스이기 때문이에요.
📌 iOS 앱에서 실제 패턴
- 데이터 모델 → struct
- User, Post, Coordinate 같은 순수 데이터 모델
- JSON 디코딩/인코딩할 때 (Codable)도 구조체가 많이 쓰임.
- UI/컨트롤러 → class
- UIKit의 UIView, UIViewController
- 참조가 필요하고, 상태 공유가 자연스러운 경우.
- SwiftUI → struct
- View는 모두 struct로 정의. 값이 변경되면 새로운 뷰로 갱신하는 철학.
✅ 결론
- struct → 값 의미, 데이터 모델, 불변성 강조, 안전한 복사
- class → 참조 의미, UIKit 객체, 상태 공유, 상속 필요


class Man {
var age : Int = 0
var weight : Double = 0.0
}
class Man {
var age : Int?
var weight : Double?
}
=> 옵셔널 ? 은 기본적으로 초기값이 있음 오류 안남
근데 별로 안씀
올려주신 Swift 코드:
class Man { var age : Int var weight : Double }여기서 에러가 나는 이유는 클래스의 저장 프로퍼티(age, weight)가 기본값이 없기 때문이에요.
Swift에서 class나 struct의 저장 프로퍼티는 반드시
- 선언 시 기본값을 주거나,
- init 생성자에서 초기화해야 합니다.
📌 에러 해결 방법 (모두 정리)
1. 기본값(Default Value) 지정
프로퍼티 선언 시 바로 초기값을 넣는 방법.
class Man { var age: Int = 0 var weight: Double = 0.0 }
2. 생성자(Initializer) 추가
초기값을 직접 전달받도록 init 생성자를 정의.
class Man { var age: Int var weight: Double init(age: Int, weight: Double) { self.age = age self.weight = weight } } // 사용 예시 let man = Man(age: 25, weight: 70.5)
3. Optional 타입으로 선언
값이 아직 없을 수 있다는 의미를 주는 방법.
class Man { var age: Int? var weight: Double? } // 사용 예시 let man = Man() man.age = 25 man.weight = 70.5
4. 암시적 추출 옵셔널(Implicitly Unwrapped Optional)
값이 반드시 나중에 세팅될 것임을 보장할 때.
class Man { var age: Int! var weight: Double! } let man = Man() man.age = 25 man.weight = 70.5⚠️ 하지만 잘못 쓰면 nil 접근 시 런타임 에러가 발생할 수 있어 주의해야 합니다.
✅ 정리
- 데이터가 항상 있어야 한다면 → 기본값(방법 1)이나 init(방법 2)
- 값이 없을 수도 있다면 → 옵셔널(방법 3)
- 값이 무조건 나중에 세팅될 걸 보장한다면 → 암시적 옵셔널(방법 4)
class Man {
var age : Int
var weight : Double
func init(){ // ❌ 잘못된 부분
age = 1
weight = 3.5
}
}
init은 함수가 아님
Swift에서 생성자는 func 키워드를 붙이지 않습니다.
init 키워드만 단독으로 써야 합니다.
저장 프로퍼티 초기화 문제
age, weight는 초기값이 없기 때문에 반드시 init에서 초기화해야 합니다.
init 문법을 올바르게 쓰지 않아서 에러가 난 거예요.
✅ 올바른 코드 작성 방법
1. 기본 이니셜라이저 작성
swift
코드 복사
class Man {
var age: Int
var weight: Double
init() {
age = 1
weight = 3.5
}
}
2. 매개변수를 받는 이니셜라이저
swift
코드 복사
class Man {
var age: Int
var weight: Double
init(age: Int, weight: Double) {
self.age = age
self.weight = weight
}
}
// 사용 예시
let man = Man(age: 20, weight: 65.0)
3. 기본값을 직접 지정
swift
코드 복사
class Man {
var age: Int = 1
var weight: Double = 3.5
}
👉 이 경우엔 init()을 작성하지 않아도 됩니다. (Swift가 자동 생성)
⚡ 정리
func init() → ❌
init() { ... } → ✅
Swift에서는 생성자(constructor)는 특별한 함수이므로 func를 붙이지 않습니다.
저장 프로퍼티를 초기화하려면 1) init에서 설정하거나, 2) 기본값을 지정해야 합니다.
class Man {
var age : Int
var weight : Double
func init(){ // ❌ 잘못된 부분
age = 1
weight = 3.5
}
}
init은 함수가 아님
Swift에서 생성자는 func 키워드를 붙이지 않습니다.
init 키워드만 단독으로 써야 합니다.
저장 프로퍼티 초기화 문제
age, weight는 초기값이 없기 때문에 반드시 init에서 초기화해야 합니다.
init 문법을 올바르게 쓰지 않아서 에러가 난 거예요.
✅ 올바른 코드 작성 방법
1. 기본 이니셜라이저 작성
swift
코드 복사
class Man {
var age: Int
var weight: Double
init() {
age = 1
weight = 3.5
}
}
2. 매개변수를 받는 이니셜라이저
swift
코드 복사
class Man {
var age: Int
var weight: Double
init(age: Int, weight: Double) {
self.age = age
self.weight = weight
}
}
// 사용 예시
let man = Man(age: 20, weight: 65.0)
3. 기본값을 직접 지정
swift
코드 복사
class Man {
var age: Int = 1
var weight: Double = 3.5
}
👉 이 경우엔 init()을 작성하지 않아도 됩니다. (Swift가 자동 생성)
⚡ 정리
func init() → ❌
init() { ... } → ✅
Swift에서는 생성자(constructor)는 특별한 함수이므로 func를 붙이지 않습니다.
저장 프로퍼티를 초기화하려면 1) init에서 설정하거나, 2) 기본값을 지정해야 합니다.
class Man {
var age : Int
var weight : Double
func init(){ // ❌ 잘못된 부분
age = 1
weight = 3.5
}
}
init은 함수가 아님
Swift에서 생성자는 func 키워드를 붙이지 않습니다.
init 키워드만 단독으로 써야 합니다.
저장 프로퍼티 초기화 문제
age, weight는 초기값이 없기 때문에 반드시 init에서 초기화해야 합니다.
init 문법을 올바르게 쓰지 않아서 에러가 난 거예요.
✅ 올바른 코드 작성 방법
1. 기본 이니셜라이저 작성
swift
코드 복사
class Man {
var age: Int
var weight: Double
init() {
age = 1
weight = 3.5
}
}
2. 매개변수를 받는 이니셜라이저
swift
코드 복사
class Man {
var age: Int
var weight: Double
init(age: Int, weight: Double) {
self.age = age
self.weight = weight
}
}
// 사용 예시
let man = Man(age: 20, weight: 65.0)
3. 기본값을 직접 지정
swift
코드 복사
class Man {
var age: Int = 1
var weight: Double = 3.5
}
👉 이 경우엔 init()을 작성하지 않아도 됩니다. (Swift가 자동 생성)
⚡ 정리
func init() → ❌
init() { ... } → ✅
Swift에서는 생성자(constructor)는 특별한 함수이므로 func를 붙이지 않습니다.
저장 프로퍼티를 초기화하려면 1) init에서 설정하거나, 2) 기본값을 지정해야 합니다.