앱에서 녹음 기능을 구현하기 위해 AVAudioRecorder 에 대해 알아보려고 한다.
AVAudioRecorder
AVAudioRecorder는 애플의 AVFoundation 프레임워크에 포함된 클래스로, 기기의 마이크를 통해 들어오는 오디오 신호를 실제 파일로 저장할 때 사용하는 "녹음기 객체"다.
*주요 역할
1. 연결 : 마이크와 앱 사이의 통로를 열어 소리를 받아온다.
2. 변환 : 아날로그 소리 신호를 우리가 지정한 디지털 포맷(AAC, PCM 등)으로 변환한다.
3. 저장 : 변환된 데이터를 기기 내부(Document 폴더 등)에 파일 형태로 기록한다.
권한설정
Info.plist 에서 Privacy - Microphone Usage Description 권한을 추가해준다.

AudioManager
import AVFoundation
@Observable
class AudioManager {
var audioRecorder: AVAudioRecorder? // 녹음을 담당하는 객체
var audioPlayer: AVAudioPlayer? // 재생을 담당하는 객체
var isRecording = false // 현재 녹음 중인지 상태값
var recordedFileURL: URL? // 녹음된 파일이 저장된 경로
// [1] 마이크 권한 요청
func requestPermission() {
AVAudioApplication.requestRecordPermission { granted in
print("마이크 권한 허용 여부: \(granted)")
}
}
// [2] 녹음 시작
func startRecording() {
let session = AVAudioSession.sharedInstance()
do {
// 녹음 세션 설정: 재생(play)과 녹음(record)을 동시에 지원하며, 소리를 스피커로 출력하도록 설정
try session.setCategory(.playAndRecord, mode: .default, options: .defaultToSpeaker)
try session.setActive(true)
// 저장 경로 설정: 앱 내 'Documents' 폴더에 my_recording.m4a 이름으로 저장
let documentPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
recordedFileURL = documentPath.appendingPathComponent("my_recording.m4a")
// 녹음 설정 (포맷, 샘플 레이트, 채널 등)
let settings: [String: Any] = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC), // AAC 포맷
AVSampleRateKey: 44100, // 44.1kHz 샘플링
AVNumberOfChannelsKey: 1, // 모노 녹음
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
// Recorder 초기화 및 녹음 시작
audioRecorder = try AVAudioRecorder(url: recordedFileURL!, settings: settings)
audioRecorder?.prepareToRecord()
audioRecorder?.record()
isRecording = true
} catch {
print("녹음 시작 실패: \(error.localizedDescription)")
}
}
// [3] 녹음 중단
func stopRecording() {
audioRecorder?.stop()
isRecording = false
}
// [4] 녹음 파일 재생
func startPlaying() {
guard let url = recordedFileURL else { return }
do {
// 재생 시에는 세션을 재생(playback) 전용 모드로 변경하여 음질 최적화
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayer?.play()
} catch {
print("재생 실패: \(error.localizedDescription)")
}
}
}
핵심은 녹음 시작 메서드 func startRecording() 인데 녹음이 어떤 과정을 거치는지 보겠다.
1. 녹음 세션 설정 : 재생(play)과 녹음(record)을 동시에 지원하며, 소리를 스피커로 출력하도록 세션을 설정해준다.
2. 저장 경로 설정 : 앱 내 'Documents' 폴더에 my_recording.m4a 이름으로 녹음본을 저장해준다.
3. 세밀한 녹음 설정 : 포맷, 샘플 레이트, 채널 등을 설정하는데 각각 이렇게 된다.
4. Recorder 초기화 및 녹음 시작
View
import SwiftUI
struct RecordingView: View {
// AudioManager 인스턴스 생성
@State private var audioManager = AudioManager()
var body: some View {
VStack(spacing: 50) {
// 현재 상태 표시
Text(audioManager.isRecording ? "녹음 중..." : "대기 중")
.font(.title)
.bold()
.foregroundColor(audioManager.isRecording ? .red : .primary)
HStack(spacing: 40) {
// 녹음 및 중지 버튼
Button(action: {
if audioManager.isRecording {
audioManager.stopRecording()
} else {
audioManager.startRecording()
}
}) {
VStack {
Image(systemName: audioManager.isRecording ? "stop.circle.fill" : "circle.fill")
.resizable()
.frame(width: 80, height: 80)
.foregroundColor(.red)
Text(audioManager.isRecording ? "중지" : "녹음")
}
}
// 재생 버튼
Button(action: {
audioManager.startPlaying()
}) {
VStack {
Image(systemName: "play.circle.fill")
.resizable()
.frame(width: 80, height: 80)
// 파일이 없거나 녹음 중일 때는 비활성화 색상(gray) 처리
.foregroundColor(audioManager.recordedFileURL == nil || audioManager.isRecording ? .gray : .blue)
Text("재생")
}
}
// 녹음 중이거나 파일이 없으면 버튼 비활성화
.disabled(audioManager.recordedFileURL == nil || audioManager.isRecording)
}
}
.padding()
// 뷰가 나타날 때 마이크 권한 확인
.onAppear {
audioManager.requestPermission()
}
}
}
#Preview {
RecordingView()
}
간단한 녹음 예제를 구현해보았다.
🍎 참고
https://developer.apple.com/documentation/avfaudio/avaudiorecorder