UIButton에 감각적인 터치 피드백 넣기: Swift 비동기 처리 실습
앱 개발을 처음 시작할 때, 가장 많이 접하게 되는 주제 중 하나는 버튼을 눌렀을 때의 반응 처리다. 단순히 기능을 수행하는 것을 넘어, 사용자에게 눌렸다는 피드백을 소리나 시각적으로 제공하는 것은 훌륭한 사용자 경험(UX)을 위한 핵심 포인트이다.
오늘은 어제 프로젝트를 토대로, 버튼을 눌렀을 때 투명도를 낮췄다가 다시 복원하는 시각적 효과를 구현해보았다. 이를 통해 Swift에서 UI 반응 처리, 비동기 처리, 그리고 DispatchQueue의 기본 사용법까지 배울 수 있다🧚🏻.
🧪 목표
- 사용자가 버튼을 누르면 해당 음계의 소리가 재생된다.
- 동시에 버튼의 투명도를 0.5로 낮춰 눌림 효과를 준다.
- 0.2초 뒤 원래의 투명도(1.0)로 복원해준다.
- 중간중간 로그를 찍어 비동기 흐름을 확인한다.
이 과정을 통해 앱은 단순한 오디오 재생을 넘어서 시각적인 인터랙션까지 포함된 고급 사용자 경험을 제공하게 된다.
🧱 기본 앱 구조
Xylophone 앱은 각 버튼마다 음계(C, D, E, …)에 맞는 .wav 파일이 연결되어 있고, 버튼을 누르면 해당 소리를 재생하게 되어 있다.
📄 초기 코드 예시
@IBAction func keyPressed(_ sender: UIButton) {
playSound(soundName: sender.currentTitle!)
}
🛠️ 버튼 눌림 효과 추가
여기서 기능을 확장하여, 버튼을 눌렀을 때 시각적인 피드백을 주는 기능을 구현해보자.
✅ 정답 코드
먼저 Angela Yu 강의에서 제시한 정답 코드는 다음과 같다.
@IBAction func keyPressed(_ sender: UIButton) {
playSound(soundName: sender.currentTitle!)
sender.alpha = 0.5
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
sender.alpha = 1.0
}
}
이 코드는 다음 순서대로 동작한다:
- 버튼의 currentTitle 값을 가져와 해당 소리를 재생.
- sender.alpha = 0.5로 버튼을 반투명하게 설정.
- DispatchQueue.main.asyncAfter로 0.2초 후 버튼 투명도를 복원.
아주 간단하면서도 효율적인 코드다. 특히 메인 큐에서 UI 변경을 처리하는 것은 iOS 개발의 중요한 규칙이다.
👨💻 내가 작성한 코드: 학습 중심의 설계
아래는 내가 작성한 코드다.
@IBAction func keyPressed(_ sender: UIButton) {
if let title = sender.currentTitle {
playSound(soundName: title)
}
sender.alpha = 0.5
print("Start")
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(200)) {
sender.alpha = 1
print("End")
}
}
🔍 내 코드 vs 정답 코드: 비교 분석
항목 | 내 코드 | 정답 코드 | 차이점 설명 |
옵셔널 처리 | if let으로 안전하게 처리 | !로 강제 언래핑 | 내 코드는 앱 크래시 방지 가능 |
투명도 복원 | alpha = 1 | alpha = 1.0 | 의미는 같으나 1.0이 CGFloat 타입 표현에 더 적절 |
시간 설정 | .milliseconds(200) | 0.2 | 내 코드는 명시적이고, 정답은 간결함 |
디버깅 로그 | print("Start") / print("End") 포함 | 없음 | 나같은 초보자에게 학습 효과와 흐름 이해에 도움(?)ㅎㅎ |
🧠 핵심 개념 정리
1. alpha 속성
- UIView의 투명도를 나타내는 속성.
- 1.0: 완전히 불투명, 0.0: 완전 투명.
- 버튼 클릭 시 0.5로 낮춰 눌림 효과를 줄 수 있다.
2. DispatchQueue.main.asyncAfter
- 일정 시간 후에 비동기로 코드를 실행하는 기능.
- sleep()과 다르게 앱이 멈추지 않음.
- main 큐를 사용하는 이유: UI 변경은 반드시 메인 스레드에서만 가능하기 때문.
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
// 여기에 0.2초 뒤 실행할 코드 작성
}
🧰 AVAudioPlayer 사용 팁
정답 코드에서는 try!를 사용하고 있다:
player = try! AVAudioPlayer(contentsOf: url!)
하지만 실제 개발 환경에서는 try!는 위험할 수 있다. 파일이 없거나 문제가 발생하면 앱이 즉시 크래시 되기 때문이다.
따라서 다음과 같은 예외 처리 방식이 추천된다:
do {
player = try AVAudioPlayer(contentsOf: url)
player.play()
} catch {
print("Error: \(error)")
}
이 작은 예제 하나에도 UI 처리, 비동기 로직, 사용자 피드백 설계 등 다양한 iOS 개발 개념이 녹아 있다. 앞으로 앱에 다양한 효과를 넣고 싶을 때는, 이런 패턴을 반복 응용하면 된다.
정답과 다르다고 주눅 들지 말자. 오히려 코드를 안전하고 논리적으로 작성할 수 있다면 그것이 진짜 성장이다.
구글링, 문서 보기, StackOverflow 탐색은 이제부터 진짜 개발자의 무기라는 것🖤.
'IT' 카테고리의 다른 글
Swift 코드 가독성을 바꾸는 switch 문 핵심정리 (1) | 2025.06.12 |
---|---|
Swift 조건문 실습으로 알아보는 인터페이스와 로직 연결 (0) | 2025.06.11 |
Swift AVFoundation 제대로 활용하기: 실로폰 앱 개발 기록 (0) | 2025.06.09 |
디자이너가 앱을 직접 만들며 깨달은 iOS Auto Layout의 본질 (4) | 2025.06.08 |
Swift에서 UIButton과 UIImageView 활용법 (2) | 2025.06.07 |
댓글
이 글 공유하기
다른 글
-
Swift 코드 가독성을 바꾸는 switch 문 핵심정리
Swift 코드 가독성을 바꾸는 switch 문 핵심정리
2025.06.12 -
Swift 조건문 실습으로 알아보는 인터페이스와 로직 연결
Swift 조건문 실습으로 알아보는 인터페이스와 로직 연결
2025.06.11 -
Swift AVFoundation 제대로 활용하기: 실로폰 앱 개발 기록
Swift AVFoundation 제대로 활용하기: 실로폰 앱 개발 기록
2025.06.09 -
디자이너가 앱을 직접 만들며 깨달은 iOS Auto Layout의 본질
디자이너가 앱을 직접 만들며 깨달은 iOS Auto Layout의 본질
2025.06.08