
출처 : smileHan - iOS 프로그래밍기초
GPT : 무드등 iOS앱을 만드려고해 앱스토어에서 인기있는 앱들을 참고하여 사전계획서를 작성해줘
무드등 앱은 사용자가 다양한 색상과 밝기를 조절하여 원하는 분위기를 연출할 수 있도록 돕는 앱입니다. 사용자는 자신의 기분이나 상황에 맞게 조명을 설정할 수 있으며, 추가적인 기능으로 타이머, 알람, 음악 재생 등을 제공할 수 있습니다.
색상 조절: 다양한 색상 옵션을 제공하여 사용자가 원하는 분위기를 쉽게 설정할 수 있도록 합니다. 예를 들어, 부드러운 파스텔 색상부터 강렬한 원색까지 선택할 수 있습니다.
밝기 조절: 화면 밝기를 조정할 수 있는 기능을 추가하여, 사용자가 원하는 밝기를 설정할 수 있도록 합니다.
타이머 및 알람: 사용자가 설정한 시간에 자동으로 조명이 켜지거나 꺼지도록 하는 기능을 추가합니다.
음악 재생: 사용자가 선택한 음악을 배경으로 재생할 수 있는 기능을 제공하여, 더욱 몰입감 있는 경험을 제공합니다.
디자인 및 사용자 경험 직관적인 UI: 사용자가 쉽게 조작할 수 있도록 직관적인 인터페이스를 설계합니다. 슬라이더를 통해 색상과 밝기를 조절할 수 있도록 하며, 미리보기 기능을 추가하여 사용자가 선택한 색상을 즉시 확인할 수 있도록 합니다.
테마 및 배경: 다양한 테마를 제공하여 사용자가 자신의 취향에 맞게 앱을 꾸밀 수 있도록 합니다.
예를 들어, 자연, 도시, 우주 등의 테마를 제공할 수 있습니다.
소셜 미디어 활용: 인스타그램, 페이스북 등 소셜 미디어 플랫폼을 통해 앱의 기능과 사용 사례를 홍보합니다.
사용자들이 자신의 무드등 설정을 공유할 수 있는 캠페인을 진행합니다.
리뷰 및 피드백: 초기 사용자들로부터 피드백을 받아 앱을 개선하고, 긍정적인 리뷰를 통해 신뢰성을 높입니다.
GPT : 스토리보드 기반으로 소스코드를 작성해줘
import UIKit
import AVFoundation
class ViewController: UIViewController {
@IBOutlet weak var colorView: UIView!
@IBOutlet weak var brightnessSlider: UISlider!
@IBOutlet weak var timerLabel: UILabel!
@IBOutlet weak var playMusicButton: UIButton!
var timer: Timer?
var remainingTime: Int = 0
var audioPlayer: AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
func setupUI() {
colorView.layer.cornerRadius = 20
colorView.backgroundColor = .white
brightnessSlider.value = 1.0
timerLabel.text = "타이머 없음"
}
@IBAction func changeColor(_ sender: Any) {
let picker = UIColorPickerViewController()
picker.delegate = self
present(picker, animated: true)
}
@IBAction func changeBrightness(_ sender: UISlider) {
colorView.alpha = CGFloat(sender.value)
}
@IBAction func setTimer(_ sender: Any) {
let alert = UIAlertController(title: "타이머 설정", message: "몇 분 후에 종료할까요?", preferredStyle: .alert)
alert.addTextField { textField in
textField.keyboardType = .numberPad
}
alert.addAction(UIAlertAction(title: "설정", style: .default, handler: { [weak self] _ in
if let text = alert.textFields?.first?.text, let minutes = Int(text) {
self?.startTimer(minutes: minutes)
}
}))
alert.addAction(UIAlertAction(title: "취소", style: .cancel))
present(alert, animated: true)
}
func startTimer(minutes: Int) {
remainingTime = minutes * 60
timerLabel.text = "남은 시간: \(minutes)분"
timer?.invalidate()
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
guard let self = self else { return }
if self.remainingTime > 0 {
self.remainingTime -= 1
self.timerLabel.text = "남은 시간: \(self.remainingTime / 60)분 \(self.remainingTime % 60)초"
} else {
self.timer?.invalidate()
self.colorView.backgroundColor = .black
self.timerLabel.text = "타이머 종료"
}
}
}
@IBAction func playMusic(_ sender: UIButton) {
if let path = Bundle.main.path(forResource: "background_music", ofType: "mp3") {
let url = URL(fileURLWithPath: path)
do {
audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayer?.play()
} catch {
print("음악 재생 오류: \(error.localizedDescription)")
}
}
}
}
extension ViewController: UIColorPickerViewControllerDelegate {
func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) {
colorView.backgroundColor = viewController.selectedColor
}
}


import UIKit // UIKit 프레임워크를 임포트하여 UI 관련 기능을 사용할 수 있도록 함
// ViewController 클래스 정의 (UIViewController를 상속받음)
class ViewController: UIViewController {
// ✅ viewDidLoad: 뷰가 메모리에 로드될 때 한 번만 실행됨
override func viewDidLoad() {
super.viewDidLoad() // 부모 클래스의 viewDidLoad() 실행 (필수)
print("viewDidLoad") // 콘솔에 "viewDidLoad" 출력 (뷰가 처음 로드될 때 확인용)
}
// 🟡 viewWillAppear: 화면이 나타나기 직전에 호출됨 (화면이 갱신될 때마다 실행)
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) // 부모 클래스의 viewWillAppear 실행 (필수)
print("viewWillAppear") // 콘솔에 "viewWillAppear" 출력 (화면이 나타나기 전 확인용)
}
// 🟢 viewDidAppear: 화면이 완전히 나타난 후 호출됨
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated) // 부모 클래스의 viewDidAppear 실행 (필수)
print("viewDidAppear") // 콘솔에 "viewDidAppear" 출력 (화면이 나타난 후 확인용)
}
}

import UIKit // UIKit 프레임워크를 가져와 UI 관련 기능을 사용
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// 앱이 실행될 때 최초로 호출되는 메서드
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 앱이 실행된 후 초기 설정을 수행할 수 있는 지점
// 예: Firebase 초기화, 푸시 알림 설정, 초기 데이터 로드
return true // 정상적으로 실행되었음을 반환
}
// MARK: UISceneSession 라이프사이클
// 새로운 씬(Scene) 세션이 생성될 때 호출됨
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// 새로운 씬을 생성할 때 사용할 설정을 선택하는 메서드
// "Default Configuration"이라는 이름의 설정을 사용하여 씬을 생성
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
// 사용자가 씬 세션을 삭제했을 때 호출됨
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// 앱이 실행 중이 아닐 때 삭제된 세션이 있다면, 이 메서드가 호출됨
// 예를 들어, 멀티태스킹에서 앱을 종료했을 때 해당 씬의 데이터를 정리하는 용도로 사용
}
}
import UIKit // UIKit 프레임워크 가져오기 (UI 관련 기능 사용)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow? // 앱의 메인 윈도우를 관리하는 변수
// 🔹 씬이 처음 연결될 때 호출됨 (앱 실행 시 최초 실행)
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// 씬이 정상적으로 UIWindowScene인지 확인 후 실행
guard let _ = (scene as? UIWindowScene) else { return }
// 만약 코드 기반 UI 설정이 필요하다면 여기서 window를 직접 생성할 수 있음
}
// 🔹 씬이 시스템에 의해 해제될 때 호출됨 (앱이 백그라운드로 전환되거나 세션이 삭제될 때)
func sceneDidDisconnect(_ scene: UIScene) {
// 씬과 관련된 리소스를 해제하는 작업 수행
// 앱이 완전히 종료된 것이 아닐 수도 있으며, 이후 다시 연결될 수도 있음
}
// 🔹 씬이 활성화될 때 호출됨 (앱이 실행 중이거나 백그라운드에서 다시 돌아올 때)
func sceneDidBecomeActive(_ scene: UIScene) {
// 앱이 활성 상태로 전환됨
// 예: 일시 중지된 작업 재개, UI 업데이트
}
// 🔹 씬이 비활성화될 때 호출됨 (전화가 오거나, 홈 화면으로 나갈 때)
func sceneWillResignActive(_ scene: UIScene) {
// 앱이 곧 비활성화됨 (사용자가 앱을 떠날 가능성이 있음)
// 예: 중요한 데이터 저장, 타이머 중지
}
// 🔹 씬이 백그라운드에서 포그라운드로 전환될 때 호출됨 (앱이 다시 활성화될 준비를 함)
func sceneWillEnterForeground(_ scene: UIScene) {
// 백그라운드에서 복귀할 때 수행할 작업
// 예: UI 업데이트, 데이터 동기화
}
// 🔹 씬이 포그라운드에서 백그라운드로 전환될 때 호출됨 (앱이 종료되거나 백그라운드로 들어갈 때)
func sceneDidEnterBackground(_ scene: UIScene) {
// 앱이 백그라운드로 전환됨
// 예: 데이터를 저장하거나, 실행 중인 작업을 종료
}
}

UINavigationController
뷰 컨트롤러 간의 계층적 네비게이션을 관리
리스트에서 항목을 선택하면 상세 화면으로 이동하거나, 여러 단계를 거쳐 정보를 입력하는등의 작업에 사용
UITabBarController
뷰 컨트롤러 간의 평행 네비게이션을 관리
앱의 주요 기능을 각각의 탭으로 나누고 사용자가 원하는 탭을 선택하여 해당 기능을 이용할 수 있게 하는 데 사용
UISplitViewController
마스터-디테일 인터페이스를 관리
iPad와 같은 큰 화면에서 사용되며, 한 화면에 두 개의 관련된 뷰 컨트롤러를 동시에 표시하는 데 사용

import UIKit
// ViewController 클래스는 UIViewController를 상속받아 화면을 관리하는 역할을 함
class ViewController: UIViewController {
// viewDidLoad() 메서드는 뷰가 메모리에 로드된 후 한 번만 실행됨
override func viewDidLoad() {
super.viewDidLoad() // 부모 클래스의 viewDidLoad() 메서드를 호출하여 기본 설정을 수행
// view는 UIViewController가 기본적으로 제공하는 속성으로, 현재 화면의 루트 뷰를 나타냄
// 즉, 이 ViewController가 관리하는 메인 화면 자체를 의미함
view.backgroundColor = UIColor.darkGray // 화면의 배경색을 어두운 회색으로 설정
}
}
GPT : 0부터 255사이의 랜덤한 숫자를 구하는 코드
let randomValue = Int.random(in: 0...255)
print(randomValue)
import Foundation
let randomValue = Int(arc4random_uniform(256)) // 0부터 255까지 랜덤
print(randomValue)
import UIKit
let randomColor = UIColor(
red: CGFloat.random(in: 0...255) / 255.0,
green: CGFloat.random(in: 0...255) / 255.0,
blue: CGFloat.random(in: 0...255) / 255.0,
alpha: 1.0
)
print(randomColor) // 랜덤한 색상이 출력됨

import UIKit
import AVFoundation // 오디오를 다루기 위한 프레임워크 추가
class ViewController: UIViewController {
var colorChangeTimer: Timer?
var audioPlayer: AVAudioPlayer!
override func viewDidLoad() {
super.viewDidLoad()
// 배경 음악 재생 설정
if let soundURL = Bundle.main.url(forResource: "bgm", withExtension: "mp3") {
do {
audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
audioPlayer.play()
} catch {
print("음악 파일 로드 또는 재생 중 에러 발생: \(error)")
}
}
// 1초마다 반복되는 타이머 생성
colorChangeTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
// 랜덤한 빨간색, 초록색, 파란색 값을 생성
let red = CGFloat(arc4random_uniform(256)) / 255.0
let green = CGFloat(arc4random_uniform(256)) / 255.0
let blue = CGFloat(arc4random_uniform(256)) / 255.0
self.view.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: 1.0)
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// ViewController가 사라질 때 타이머를 중지하고 nil로 설정하여 메모리 누수를 방지
colorChangeTimer?.invalidate()
colorChangeTimer = nil
// 음악 재생 중지
audioPlayer.stop()
}
}
Horizontally in Container -> 0으로 설정시 정가운데 위치(상,하)
Vertically in Container -> 0으로 설정시 정가운데 위치(좌,우)

📌Auto Layout = 화면 크기에 맞게 UI를 자동 정리하는 시스템
📌 규칙(Constraints)을 정하면, 모든 기기에서 UI가 알아서 배치됨
📌 화면 크기가 변해도 요소들이 엉키지 않도록 도와줌
| 방법 | 장점 👍 | 단점 👎 |
|---|---|---|
| 스토리보드에서 Constraints 설정 | - 시각적으로 배치를 쉽게 조정 가능 🖼️ - 직관적인 인터페이스 제공 (마우스로 드래그 & 클릭) - iOS 기본 기능으로 별도 코드 없이 설정 가능 | - 복잡한 레이아웃일 경우 관리가 어려움 ⚠️ - 코드 기반 개발보다 유연성이 낮음 - 여러 화면 크기 대응 시 Preview만으로는 한계가 있음 |
| 코드로 NSLayoutConstraint 사용 | - 동적으로 레이아웃을 변경할 때 유리함 🛠️ - 복잡한 UI에서도 깔끔한 관리 가능 - 버전 충돌 걱정 없음 (스토리보드는 Xcode 업데이트 시 충돌 가능) | - 코드가 길어질 수 있음 📜 - 처음 배우기 어려울 수 있음 - 직관성이 낮아 유지보수가 힘들 수 있음 |
| 코드로 Auto Layout Anchor 사용 (추천!) | - 코드가 간결하고 가독성이 좋음 ✨ - NSLayoutConstraint보다 더 쉽게 설정 가능 - 런타임에서 동적으로 조정 가능 | - 스토리보드만큼 직관적이지 않음 🔍 - 마우스로 바로 확인하기 어려움 |
| Stack View 사용 | - 내부 요소들의 크기와 정렬을 자동으로 조절함 📏 - 코드 없이도 쉽게 적용 가능 - 반응형 레이아웃을 만들기 쉬움 | - 복잡한 배치에서는 한계가 있음 🚧 - 유연성이 부족하여 세밀한 제어가 어렵음 |
| SwiftUI 사용 | - 코드가 간결하고 직관적임 💡 - 미리보기(Preview) 기능이 강력함 - 선언형 문법으로 UI 코드가 깔끔함 | - iOS 13 이상에서만 사용 가능 🚫 - UIKit 기반 프로젝트와 호환성이 낮음 |
텍스트 입력 및 표시
사용자가 원하는 메시지를 입력하고, LED 전광판 스타일로 화면에 표시
텍스트 스타일링
글자 크기 조절 텍스트 색상 및 배경 색상 선택 텍스트 폰트 변경
애니메이션 효과
텍스트 스크롤, 방향 설정 (좌우, 상하), 어플가이드, 스크롤 속도 조절, 텍스트, 깜박임 효과, 이모티콘 및 아이콘 추가, 텍스트와 함께 다양한 이모티콘 및 아이콘을 추가하여 표현력 강화
다국어 지원
여러 언어로 메시지 입력 및 표시 가능
저장 및 공유: 제작한 전광판 디자인을 이미지나 GIF로 저장 SNS나 메신저를 통해 공유
사용자 친화적인 인터페이스
직관적인 디자인으로 누구나 쉽게 사용할 수 있도록 구성
실시간 미리보기
설정 변경 시 즉시 화면에 반영되어 사용자 편의성 향상
다양한 테마 제공
여러 가지 배경 및 텍스트 테마를 제공하여 사용자 선택 폭 확대
전광판 LED Scroller
사용자 친화적인 인터페이스와 다양한 기능 제공
글씨 크기 조정, 스크롤 속도 및 방향 설정, 색상 선택 등이 가능
모두의응원 LED 전광판
다양한 텍스트 스타일링과 애니메이션 효과 제공
이모티콘 추가 및 다국어 지원으로 글로벌 사용자 타겟
LED 전광판 - 네온사인 - 응원간판: 글꼴 크기 조정, 다양한 텍스트 및 배경 색상, 스크롤 및 깜박임 속도 조정 등의 기능 제공
1주차 : 시장 조사 및 기획
2~3주차 : UI/UX 디자인 및 프로토타입 제작
4~6주차 : 앱 개발 및 기능 구현
7주차 : 테스트 및 버그 수정
8주차 : 앱스토어 등록 및 마케팅 준비
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
@IBOutlet weak var textField: UITextField!
@IBAction func displayText(_ sender: UIButton) {
label.text = textField.text
startScrolling()
}
override func viewDidLoad() {
super.viewDidLoad()
}
func startScrolling() {
UIView.animate(withDuration: 10, delay: 0, options: [.curveLinear, .repeat], animations: {
self.label.center.x -= self.view.bounds.width
}, completion: nil)
}
}