# developeracademy-postech/2026-c4-m13-noma architecture

> Architecture diagram of the GitHub repository developeracademy-postech/2026-c4-m13-noma, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-15). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/developeracademy-postech/2026-c4-m13-noma
- Repository: https://github.com/developeracademy-postech/2026-c4-m13-noma

## Overview

NOMA is a macOS app for job-seeking Korean learners to practice formal interview speech and receive feedback. The user enters through onboarding and microphone permission, starts interview practice, speaks answers that are transcribed and analyzed, and reviews a saved summary; practice also includes spoken questions, playback, and generated follow-up questions. The graph separates navigation, practice orchestration, speech/AI services, and learning records. Edges reflect the excerpts, SOURCE INDEX references, or README; several UI-to-store interactions and persistence details are not shown in the sampled source.

Main entry points: [`NOMA/Application/Routing/AppRootView.swift`](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Application/Routing/AppRootView.swift) (App root), [`NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift`](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift) (Practice reducer), [`NOMA/Models/PracticeRecord.swift`](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Models/PracticeRecord.swift) (Practice records), [`NOMA/Features/PracticeSummary/PracticeSummaryView.swift`](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/PracticeSummary/PracticeSummaryView.swift) (Practice summary)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_navigation["App navigation"]
  node_root["App root<br/>[AppRootView.swift]"]
  node_router["Route state<br/>[AppRouter.swift]"]
  node_onboarding["AI onboarding"]
  node_permission["Mic permission"]
  node_home["Home<br/>[HomeView.swift]"]
  node_intelligence_status["AI availability"]
end

subgraph group_practice["Interview practice"]
  node_practice_view["Practice screen"]
  node_practice_store["Practice store"]
  node_reducer["Practice reducer"]
  node_session["Session state"]
end

subgraph group_speech_ai["Speech and AI"]
  node_audio_capture["Audio capture"]
  node_transcription["Speech transcription"]
  node_question_speech["Question speech"]
  node_audio_playback["Audio playback"]
  node_sentence_feedback["Sentence feedback"]
  node_followup["Follow-up generation"]
end

subgraph group_learning["Learning records"]
  node_analysis_loading["Analysis loading"]
  node_summary["Practice summary"]
  node_history["Learning history"]
  node_records[("Practice records")]
  node_memo["Memo window"]
end

node_user(("Learner"))

node_user -->|"opens app"| node_root
node_root -->|"shows home"| node_home
node_root -->|"binds routes"| node_router
node_root -->|"checks availability"| node_intelligence_status
node_root -->|"routes to"| node_onboarding
node_root -->|"routes to"| node_permission
node_root -->|"routes to"| node_practice_view
node_root -->|"routes to"| node_analysis_loading
node_root -->|"routes to"| node_summary
node_root -->|"routes to"| node_history
node_root -->|"creates store"| node_practice_store
node_root -->|"injects reducer"| node_reducer
node_root -->|"injects recorder"| node_audio_capture
node_root -->|"injects player"| node_audio_playback
node_root -->|"injects speaker"| node_question_speech
node_root -->|"injects transcriber"| node_transcription
node_root -->|"injects feedback"| node_sentence_feedback
node_root -->|"injects generator"| node_followup
node_reducer -->|"records audio"| node_audio_capture
node_reducer -->|"transcribes stream"| node_transcription
node_reducer -->|"speaks question"| node_question_speech
node_reducer -->|"controls playback"| node_audio_playback
node_reducer -->|"generates feedback"| node_sentence_feedback
node_reducer -->|"requests follow-up"| node_followup
node_reducer -->|"updates session"| node_session
node_practice_view -.->|"uses store"| node_practice_store
node_analysis_loading -.->|"continues to"| node_summary
node_summary -->|"reads record"| node_records
node_home -->|"shows history"| node_records
node_history -.->|"browses records"| node_records
node_root -->|"opens window"| node_memo
node_root -->|"configures model"| node_records

click node_root "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Application/Routing/AppRootView.swift"
click node_router "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Application/Routing/AppRouter.swift"
click node_onboarding "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/Onboarding/OnboardingView.swift"
click node_permission "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/Permission/PermissionView.swift"
click node_home "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/Home/HomeView.swift"
click node_practice_view "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/InterviewPractice/InterviewPracticeView.swift"
click node_practice_store "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/InterviewPractice/InterviewPracticeStore.swift"
click node_reducer "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift"
click node_session "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Models/PracticeSession.swift"
click node_audio_capture "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/AudioRecording/AVAudioRecordingService.swift"
click node_transcription "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/SpeechTranscribing/SpeechTranscriptionService.swift"
click node_question_speech "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/QuestionSpeaking/AVSpeechSynthesizerService.swift"
click node_audio_playback "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/AudioPlaying/AVAudioPlayerService.swift"
click node_sentence_feedback "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/InterviewFeedbackGenerating/FoundationModelsFeedbackService.swift"
click node_followup "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/FollowUpQuestionGenerating/FollowUpQuestionGeneratingService.swift"
click node_analysis_loading "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/PracticeSummary/AnswerAnalysisLoadingView.swift"
click node_summary "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/PracticeSummary/PracticeSummaryView.swift"
click node_history "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/LearningHistory/LearningHistoryView.swift"
click node_records "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Models/PracticeRecord.swift"
click node_memo "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/InterviewPractice/MemoWindowView.swift"
click node_intelligence_status "https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/AppleIntelligenceStatus/AppleIntelligenceStatus.swift"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_root,node_router,node_onboarding,node_permission,node_home,node_intelligence_status toneBlue
class node_practice_view,node_practice_store,node_reducer,node_session toneAmber
class node_audio_capture,node_transcription,node_question_speech,node_audio_playback,node_sentence_feedback,node_followup toneMint
class node_analysis_loading,node_summary,node_history,node_records,node_memo toneRose
class node_user toneIndigo
```

## Components

### App navigation

- [App root](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Application/Routing/AppRootView.swift): `NOMA/Application/Routing/AppRootView.swift`
- [Route state](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Application/Routing/AppRouter.swift): `NOMA/Application/Routing/AppRouter.swift`
- [AI onboarding](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/Onboarding/OnboardingView.swift): `NOMA/Features/Onboarding/OnboardingView.swift`
- [Mic permission](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/Permission/PermissionView.swift): `NOMA/Features/Permission/PermissionView.swift`
- [Home](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/Home/HomeView.swift): `NOMA/Features/Home/HomeView.swift`
- [AI availability](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/AppleIntelligenceStatus/AppleIntelligenceStatus.swift): `NOMA/Services/AppleIntelligenceStatus/AppleIntelligenceStatus.swift`

### Interview practice

- [Practice screen](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/InterviewPractice/InterviewPracticeView.swift): `NOMA/Features/InterviewPractice/InterviewPracticeView.swift`
- [Practice store](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/InterviewPractice/InterviewPracticeStore.swift): `NOMA/Features/InterviewPractice/InterviewPracticeStore.swift`
- [Practice reducer](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift): `NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift`
- [Session state](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Models/PracticeSession.swift): `NOMA/Models/PracticeSession.swift`

### Speech and AI

- [Audio capture](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/AudioRecording/AVAudioRecordingService.swift): `NOMA/Services/AudioRecording/AVAudioRecordingService.swift`
- [Speech transcription](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/SpeechTranscribing/SpeechTranscriptionService.swift): `NOMA/Services/SpeechTranscribing/SpeechTranscriptionService.swift`
- [Question speech](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/QuestionSpeaking/AVSpeechSynthesizerService.swift): `NOMA/Services/QuestionSpeaking/AVSpeechSynthesizerService.swift`
- [Audio playback](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/AudioPlaying/AVAudioPlayerService.swift): `NOMA/Services/AudioPlaying/AVAudioPlayerService.swift`
- [Sentence feedback](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/InterviewFeedbackGenerating/FoundationModelsFeedbackService.swift): `NOMA/Services/InterviewFeedbackGenerating/FoundationModelsFeedbackService.swift`
- [Follow-up generation](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Services/FollowUpQuestionGenerating/FollowUpQuestionGeneratingService.swift): `NOMA/Services/FollowUpQuestionGenerating/FollowUpQuestionGeneratingService.swift`

### Learning records

- [Analysis loading](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/PracticeSummary/AnswerAnalysisLoadingView.swift): `NOMA/Features/PracticeSummary/AnswerAnalysisLoadingView.swift`
- [Practice summary](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/PracticeSummary/PracticeSummaryView.swift): `NOMA/Features/PracticeSummary/PracticeSummaryView.swift`
- [Learning history](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/LearningHistory/LearningHistoryView.swift): `NOMA/Features/LearningHistory/LearningHistoryView.swift`
- [Practice records](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Models/PracticeRecord.swift): `NOMA/Models/PracticeRecord.swift`
- [Memo window](https://github.com/developeracademy-postech/2026-c4-m13-noma/blob/develop/NOMA/Features/InterviewPractice/MemoWindowView.swift): `NOMA/Features/InterviewPractice/MemoWindowView.swift`

### Other components

- **Learner**

## Connections

- Learner → App root: opens app
- App root → Home: shows home (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Route state: binds routes (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → AI availability: checks availability (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → AI onboarding: routes to (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Mic permission: routes to (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Practice screen: routes to (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Analysis loading: routes to (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Practice summary: routes to (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Learning history: routes to (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Practice store: creates store (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Practice reducer: injects reducer (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Audio capture: injects recorder (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Audio playback: injects player (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Question speech: injects speaker (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Speech transcription: injects transcriber (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Sentence feedback: injects feedback (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- App root → Follow-up generation: injects generator (evidence: `NOMA/Application/Routing/AppRootView.swift`)
- Practice reducer → Audio capture: records audio (evidence: `NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift`)
- Practice reducer → Speech transcription: transcribes stream (evidence: `NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift`)
- Practice reducer → Question speech: speaks question (evidence: `NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift`)
- Practice reducer → Audio playback: controls playback (evidence: `NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift`)
- Practice reducer → Sentence feedback: generates feedback (evidence: `NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift`)
- Practice reducer → Follow-up generation: requests follow-up (evidence: `NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift`)
- Practice reducer → Session state: updates session (evidence: `NOMA/Features/InterviewPractice/InterviewPracticeReducer.swift`)
- Practice screen → Practice store: uses store
- Analysis loading → Practice summary: continues to
- Practice summary → Practice records: reads record (evidence: `NOMA/Features/PracticeSummary/PracticeSummaryView.swift`)
- Home → Practice records: shows history (evidence: `NOMA/Features/Home/HomeView.swift`)
- Learning history → Practice records: browses records
- App root → Memo window: opens window (evidence: `NOMA/Application/NOMAApp.swift`)
- App root → Practice records: configures model (evidence: `NOMA/Application/NOMAApp.swift`)
