iOS

[iOS] 무드등 앱 개발 및 Swift 문법 복습 2

챎 님 2025. 3. 19. 16:31
더보기

이 포스트는 한성현 교수님의 iOS 프로그래밍 실무 수업을 듣고 작성하였습니다.

어제 작성한 포스트에서 추가로 문법 복습을 더 해 보겠습니다.

문법 복습에 들어가기 전에, 간단한 무드등 앱을 만들며 XCode 와 가까워지는 시간을 가져 보겠습니다.

앱 개발 이전에 먼저, 뤼튼에서 설계 계획서 및 특정 기한까지 만들 수 있는 계획에 대해 질문해 보았습니다.

위와 같은 질문을 한 뒤 답안을 포스팅 해 보겠습니다.

 


무드등 iOS 앱 사전 계획서
1. 앱 개요
앱 이름: 예) "Mood Light"


목표: 사용자가 다양한 조명 효과를 통해 분위기를 조성하고, 개인 맞춤형 조명 설정을 제공.
2. 주요 기능
조명 색상 선택: 사용자가 원하는 색상을 선택할 수 있는 색상 팔레트 제공.
조명 효과: 다양한 조명 효과 (예: 깜빡임, 페이드 인/아웃, 색상 변경 등) 구현.
타이머 기능: 특정 시간에 조명이 자동으로 켜지거나 꺼지도록 설정할 수 있는 기능.
음악 연동: 사용자가 음악에 맞춰 조명이 변화하도록 설정할 수 있는 기능.
사용자 설정 저장: 사용자가 선호하는 조명 설정을 저장하고 불러오는 기능.
위치 기반 설정: 위치에 따라 자동으로 조명 설정을 변경하는 기능 (예: 집, 사무실 등).
3. UI/UX 디자인
직관적인 인터페이스: 사용자가 쉽게 조작할 수 있도록 직관적인 버튼과 슬라이더 디자인.
색상 선택기: 사용자 친화적인 색상 선택 도구 제공.
미리보기 기능: 사용자가 선택한 조명 효과를 미리 볼 수 있는 기능.
4. 기술 스택
프로그래밍 언어: Swift
개발 도구: Xcode
라이브러리: CoreGraphics, CoreAnimation (애니메이션 효과 구현을 위해)
5. 시장 조사
경쟁 앱 분석:
인기 앱 목록: "Philips Hue", "LIFX", "Twinkly"
각 앱의 주요 기능 및 사용자 리뷰 분석
차별화 포인트: 사용자 맞춤형 경험과 직관적인 UI로 경쟁 우위 확보.
6. 마케팅 전략
소셜 미디어 캠페인: Instagram, Facebook을 통해 제품 홍보.
블로그 및 리뷰: 조명 관련 블로그와 유튜브 채널을 통해 앱 리뷰 요청.
프로모션: 출시 초기 무료 체험 제공.
7. 일정 계획
개발 단계:
기획 및 디자인 (1개월)
프로토타입 개발 (2개월)
베타 테스트 (1개월)
출시 준비 (1개월)
총 개발 기간: 약 5개월
8. 예산
개발 인력: 개발자, 디자이너, 마케팅 담당자 인건비 등
기타 비용: 서버 비용, 마케팅 비용 등


1. 기획 및 디자인 (1개월)
기간: 2025년 1월 1일 ~ 2025년 1월 31일
앱의 기능 정의 및 요구 사항 분석
UI/UX 디자인 초안 작성
경쟁 앱 분석 및 벤치마킹
2. 프로토타입 개발 (2개월)
기간: 2025년 2월 1일 ~ 2025년 3월 31일
기본 기능 구현 (조명 색상 선택, 조명 효과 등)
초기 UI/UX 디자인 적용
내부 테스트 및 피드백 반영
3. 베타 테스트 (1개월)
기간: 2025년 4월 1일 ~ 2025년 4월 30일
외부 사용자 초청하여 베타 테스트 실시
사용자 피드백 수집 및 버그 수정
기능 개선 및 최종 조정
4. 출시 준비 (1개월)
기간: 2025년 5월 1일 ~ 2025년 5월 30일
앱 스토어 등록 준비 (스크린샷, 설명 작성 등)
마케팅 자료 준비 (프로모션 계획 수립)
최종 테스트 및 배포 준비
최종 출시
출시일: 2025년 5월 30일

 


뤼튼을 간단히 사용해 보았으니, XCode 에 접속해 보았습니다.

위 사진에서는 여러 가지 정보를 볼 수 있지만, 가장 중요한 Bundle identifier 입니다.

이는 식별할 수 있는 코드로 App Store 에 이 식별자와 같은 앱이 있다면, 업로드되지 않습니다.

 

이제 간단히 코드를 작성해 보며, 앱을 개발해 보겠습니다.

 

``` ViewController.swift

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        print("viewDidLoad")
    }
    override func viewWillAppear(_ animated: Bool) {
        print("viewDidLoad")
    }
    override func viewWillDisappear(_ animated: Bool) {
        print("viewDidAppear")
    }
}

이렇게 작성해 보았습니다.

뤼튼에게 주석을 달아 설명해 달라고 질문하였고, 답변을 달아 보겠습니다.

import UIKit // UIKit 프레임워크를 임포트하여 사용자 인터페이스 요소를 사용할 수 있게 함.

class ViewController: UIViewController { // UIViewController를 상속받은 ViewController 클래스 정의

    override func viewDidLoad() {
        super.viewDidLoad() // 부모 클래스의 viewDidLoad() 호출하여 초기화 작업 수행
        print("viewDidLoad") // 뷰가 메모리에 로드되었음을 콘솔에 출력
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated) // 부모 클래스의 viewWillAppear() 호출
        print("viewWillAppear") // 뷰가 화면에 나타나기 직전에 호출되며 콘솔에 출력
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated) // 부모 클래스의 viewWillDisappear() 호출
        print("viewWillDisappear") // 뷰가 화면에서 사라지기 직전에 호출되며 콘솔에 출력
    }
}

즉, 위 코드는 뷰 화면에 나타나고 사라지는 모션이 생길 때 호출되며, 콘솔에 print 문이 출력되는 코드임을 의미합니다.

 

앱은 실행 모드와 상태를 가집니다.

  • Forground Mode
    • Active : 앱이 전경에 있고 이벤트를 받고 있음. 일반적으로 사용자와 상호작용하는 동안 앱은 이 상태에 있음.
    • Inactive : 앱이 전경에 있지만 이벤트를 받고 있지 않음.
  • Background Mode
    • Running : 앱이 백그라운드에 있지만 여전히 코드를 실행. 사용자가 다른 앱으로 전환하거나 홈 화면으로 돌아갔을 때 앱은 일시적으로 이 상태에 머물게 됨.
    • Suspend : 앱이 백그라운드에 있지만 코드를 실행하지 않음. 시스템은 앱을 이 상태로 자동으로 전환하며 필요에 따라 메모리를 회수하기 위해 앱을 종료시킬 수 있음.

 

 

이제 정말 무드등처럼 색이 특정 초마다 바뀌는 앱의 코드를 작성해 보겠습니다.

import UIKit

class ViewController: UIViewController {
    
    var colorChangeTimer: Timer?

    override func viewDidLoad() {
        super.viewDidLoad()
        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)
            colorChangeTimer?.invalidate()
            colorChangeTimer = nil
    }
}

간단하게 무드등 결과를 보여드리겠습니다.

 

이와 같이 여러 색이 출력됩니다.

 

다음으로는 BGM 을 깔아 보겠습니다.

미리 다운 받았던 음악을

추가해 줍니다.

그 후, 코드를 작성하여 보겠습니다.

 

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()
  }
}

이렇게 코드를 작성하면, 음악이 나오게 됩니다.

 

 

다음은 스위치를 버튼을 눌렀을 때 음악을 멈추고, 배경색을 고정하는 코드를 만들어 보겠습니다.

import UIKit

import AVFoundation  // 오디오를 다루기 위한 프레임워크 추가

class ViewController: UIViewController {
    
    var colorChangeTimer: Timer?
    var audioPlayer: AVAudioPlayer!
    
    
    @IBOutlet weak var musicSwitch: UISwitch!
    override func viewDidLoad() {
        super.viewDidLoad()
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture))
        view.addGestureRecognizer(tapGesture)
        NotificationCenter.default.addObserver(self, selector:
                                                #selector(applicationWillEnterForeground),
                                               name: UIApplication.willEnterForegroundNotification, object: nil)
    }
    @objc func applicationWillEnterForeground() {
        startTimerAndMusic()
    }
    @objc func handleTapGesture() {
        stopTimerAndMusic()
        colorChangeTimer = nil
        audioPlayer = nil
        let alert = UIAlertController(title: "알림", message: "앱을 종료해주세요.", preferredStyle: .alert)
        let okAction = UIAlertAction(title: "확인", style: .default, handler: nil)
        alert.addAction(okAction)
        present(alert, animated: true, completion: nil)
    }
    
    @IBAction func switchDidChange(_ sender: UISwitch) {
        if sender.isOn {
            startTimerAndMusic()
        }else {
            stopTimerAndMusic()}
    }
    
    func startTimerAndMusic() {
        // 배경 음악 재생 설정
        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
            // 생성된 랜덤 색상을 사용하여 ViewController의 배경색 설정
            self.view.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: 1.0)
        }
    }
    func stopTimerAndMusic() {
        // 타이머와 음악 재생 중지
        colorChangeTimer?.invalidate()
        colorChangeTimer = nil
        audioPlayer.stop()
    }
}

이렇게 하고 액션과 아울렛을 지정해 주면, 가운데 위치한 버튼을 통해 조정을 할 수 있습니다.

 

 

 

 

'iOS' 카테고리의 다른 글

[iOS] Table View  (0) 2025.04.02
[iOS] 함수와 클래스 및 상속  (0) 2025.03.26
[iOS] Swift 문법 복습  (0) 2025.03.18
[iOS] 생성형 AI 및 오픈 API 활용  (0) 2025.03.05
[iOS] 클로저 Closure  (0) 2024.12.11