
root view controller(시험)
OS 앱의 첫 번째 화면을 관리하는 뷰 컨트롤러를 의미
보통 앱이 실행되면, root view controller가 화면에 처음 표시됨
이 뷰 컨트롤러는 다른 뷰 컨트롤러들을 관리하거나 전환하는 역할을 함
Action Segue vs Manual Segue 비교
특성 Action Segue Manual Segue
| 연결 방법 | 코드에서 특정 이벤트(버튼 클릭 등)로 트리거 | 스토리보드에서 화면 간 직접 연결 |
| 트리거 방식 | 코드 내에서 performSegue로 호출 | 스토리보드에서 직접 설정된 트리거 |
| 사용 예시 | 버튼을 눌러 다른 화면으로 이동할 때 | 버튼이나 특정 UI 요소를 드래그하여 연결 |
| 유연성 | 코드에서 조건에 맞게 세밀한 제어 가능 | 트리거가 정해져 있어 유연성이 적음 |
| 구현 위치 | @IBAction 함수 내에서 사용 | 스토리보드에서 연결 설정 |
| 사용 상황 | 코드로 뷰 컨트롤러 간의 전환을 다룰 때 | 화면 전환을 스토리보드에서 시각적으로 설정할 때 |
(시험에 나오진 않음)



idedentity inspector시험나옴
func prepare(for segue: UIStoryboardSegue, sender: Any?)는 화면 전환(segue)이 일어나기 직전에 호출되는 메소드
주로 다음 화면으로 데이터를 넘겨줄 때 사용
언제 호출되나요?
- 스토리보드에서 segue로 두 화면(ViewController)을 연결했을 때
- 화면 전환이 일어나기 직전에 자동으로 호출
- 수동이든 자동이든 performSegue()를 호출하면 이 메소드가 실행됨
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// segue.identifier로 어떤 segue인지 확인 가능
// segue.destination으로 이동할 화면 접근
}


DetailViewController.swift
import UIKit // 사용자 인터페이스 구성 요소를 사용하기 위한 프레임워크
import WebKit // 웹 페이지를 보여주기 위해 WKWebView를 사용
// 영화 상세 정보를 보여주는 화면(ViewController)
class DetailViewController: UIViewController {
// 영화 제목을 표시할 UILabel (스토리보드에서 연결됨)
@IBOutlet weak var nameLabel: UILabel!
// 웹 페이지를 표시할 WKWebView (스토리보드에서 연결됨)
@IBOutlet weak var webView: WKWebView!
// 이전 화면에서 전달받을 영화 제목 변수 (기본값: "미션임파서블")
var movieName = "미션임파서블"
// 뷰가 메모리에 올라왔을 때 호출되는 생명주기 메서드
override func viewDidLoad() {
super.viewDidLoad()
// UILabel과 네비게이션 바 타이틀에 영화 제목 표시
nameLabel.text = movieName
navigationItem.title = movieName
// 영화 이름을 포함한 네이버 검색 URL 생성
let urlKorString =
"https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=" + movieName
// URL에 한글이 포함되어 있을 수 있으므로 퍼센트 인코딩 처리
let urlString = urlKorString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
// 문자열을 URL 타입으로 변환, 실패 시 함수 종료
guard let url = URL(string: urlString) else { return }
// URL 요청 객체 생성
let request = URLRequest(url: url)
// WKWebView를 통해 웹 페이지 로드
webView.load(request)
}
// MARK: - Table view data source
// 현재 이 클래스는 UITableView를 사용하지 않으므로 비어 있음
}
ViewController.swift
//
// ViewController.swift
// Moviekdh
//
// Created by 소프트웨어컴퓨터 on 2025/05/07.
//
import UIKit // 사용자 인터페이스 요소를 사용하기 위한 프레임워크
let movie = ["야당","야당1","야당","야당3","야당4"] // 영화 이름 배열 (현재 사용되지 않음)
// 영화 데이터를 디코딩하기 위한 구조체 정의
struct MovieData: Codable {
let boxOfficeResult: BoxOfficeResult
}
// 박스오피스 결과를 담는 구조체
struct BoxOfficeResult: Codable {
let dailyBoxOfficeList: [DailyBoxOfficeList]
}
// 개별 영화의 박스오피스 정보를 담는 구조체
struct DailyBoxOfficeList: Codable {
let movieNm: String // 영화 제목
let audiCnt: String // 어제의 관객 수
let audiAcc: String // 누적 관객 수
let rank: String // 영화 순위
}
// ViewController 클래스 정의 (박스오피스 데이터를 보여주는 화면)
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var table: UITableView! // 영화 정보를 보여줄 테이블 뷰
var movieData: MovieData? // 영화 데이터를 저장할 변수
var movieURL = "https://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=2bc95506177a89ebc75d86551353ab57&targetDt=" // 영화 데이터 API URL
// 화면이 로드될 때 호출되는 메서드
override func viewDidLoad() {
super.viewDidLoad()
// 테이블 뷰의 델리게이트와 데이터 소스를 설정
table.delegate = self
table.dataSource = self
// 어제 날짜를 URL에 추가
movieURL = movieURL + makeYesterdayString()
// 영화 데이터를 가져오는 메서드 호출
getDate()
}
// 어제 날짜를 "yyyyMMdd" 형식으로 반환하는 함수
func makeYesterdayString() -> String {
let y = Calendar.current.date(byAdding:.day, value:-1, to: Date())! // 하루 전 날짜 계산
let dateF = DateFormatter()
dateF.dateFormat = "yyyyMMdd" // 날짜 포맷 설정
let day = dateF.string(from: y) // 날짜를 문자열로 변환
return day
}
// 영화 데이터를 API에서 가져오는 함수
func getDate() {
guard let url = URL(string: movieURL) else { return } // URL 변환 실패 시 종료
let session = URLSession(configuration: .default) // URLSession을 이용해 데이터 요청
let task = session.dataTask(with: url) { data, response, error in
if error != nil {
print(error!) // 에러 발생 시 출력
return
MyTableViewCell.swift
//
// MyTableViewCell.swift
// Moviekdh
//
// Created by 소프트웨어컴퓨터 on 2025/05/07.
//
import UIKit // 사용자 인터페이스 관련 클래스들을 사용할 수 있게 해주는 프레임워크
// UITableViewCell을 상속받은 커스텀 셀 클래스
class MyTableViewCell: UITableViewCell {
// 영화 제목, 어제의 관객 수, 누적 관객 수를 표시할 UILabel들
@IBOutlet weak var audiAccumulate: UILabel! // 누적 관객 수
@IBOutlet weak var movieName: UILabel! // 영화 제목
@IBOutlet weak var audiCount: UILabel! // 어제의 관객 수
// 셀이 메모리로 로드될 때 호출되는 초기화 메서드
override func awakeFromNib() {
super.awakeFromNib()
// 셀의 초기 설정 코드가 들어갈 수 있지만, 현재는 기본적인 초기화만 수행됨
}
// 셀이 선택된 상태일 때 호출되는 메서드
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// 선택된 상태에서 셀의 스타일을 설정할 수 있음
// 예를 들어 선택되었을 때 셀 배경색을 바꾸는 등의 작업을 할 수 있음
}
}
- ViewController.swift:
- 영화 목록을 테이블 뷰에 표시합니다.
- API에서 데이터를 가져와 MovieData 형태로 파싱한 후, 이를 **MyTableViewCell**에 표시합니다.
- 사용자가 특정 영화를 선택하면, 해당 영화의 제목을 **DetailViewController**에 전달하여 세부 정보를 보여주기 위한 세그웨이를 트리거합니다.
- MyTableViewCell.swift:
- 영화 정보를 보여주는 커스텀 셀입니다.
- 각 셀은 영화 제목, 어제의 관객 수, 누적 관객 수 등을 표시하는 **UILabel**들로 구성됩니다.
- ViewController에서 데이터를 받아와 이 셀에 표시합니다.
- DetailViewController.swift:
- ViewController에서 선택된 영화의 상세 정보를 보여주는 화면입니다.
- 영화 제목을 movieName 변수로 받아서 웹뷰에 관련된 정보를 표시하거나, 추가적인 영화 정보를 제공할 수 있습니다.
관계 요약:
- ViewController.swift는 영화 목록을 테이블 뷰로 표시하고, 선택된 영화를 **DetailViewController**로 전달합니다.
- **MyTableViewCell**은 ViewController에서 받은 영화 정보를 화면에 표시하는 역할을 합니다.
- **DetailViewController**는 선택된 영화의 상세 정보를 표시합니다.
🎯 목표: MVC 구조로 리팩토링
MVC (Model-View-Controller)는 앱 구조를 깔끔하게 나눠주는 디자인 패턴입니다.
- Model: 데이터 구조와 로직 (ex: MovieData, 네트워크 통신)
- View: UI 요소 (ex: 스토리보드, UILabel, UITableViewCell 등)
- Controller: 뷰와 모델을 연결하는 중간 관리자 (ex: ViewController, DetailViewController)
✅ 1. Model 분리
📁 Model/Movie.swift
import Foundation
struct MovieData: Codable {
let boxOfficeResult: BoxOfficeResult
}
struct BoxOfficeResult: Codable {
let dailyBoxOfficeList: [DailyBoxOfficeList]
}
struct DailyBoxOfficeList: Codable {
let movieNm: String
let audiCnt: String
let audiAcc: String
let rank: String
}
✅ 2. Service(네트워크) 분리
📁 Service/MovieService.swift
import Foundation
class MovieService {
static let shared = MovieService()
private init() {}
func fetchMovies(for date: String, completion: @escaping (MovieData?) -> Void) {
let urlString = "https://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=2bc95506177a89ebc75d86551353ab57&targetDt=\(date)"
guard let url = URL(string: urlString) else {
completion(nil)
return
}
let task = URLSession.shared.dataTask(with: url) { data, _, error in
guard let data = data, error == nil else {
completion(nil)
return
}
do {
let decoded = try JSONDecoder().decode(MovieData.self, from: data)
completion(decoded)
} catch {
print("JSON 디코딩 오류:", error)
completion(nil)
}
}
task.resume()
}
}
✅ 3. Controller 간결화
📁 Controller/ViewController.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var table: UITableView!
var movieData: MovieData?
override func viewDidLoad() {
super.viewDidLoad()
table.delegate = self
table.dataSource = self
fetchMovies()
}
func fetchMovies() {
let dateString = makeYesterdayString()
MovieService.shared.fetchMovies(for: dateString) { [weak self] data in
guard let self = self else { return }
DispatchQueue.main.async {
self.movieData = data
self.table.reloadData()
}
}
}
func makeYesterdayString() -> String {
let y = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMdd"
return dateFormatter.string(from: y)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let dest = segue.destination as? DetailViewController,
let indexPath = table.indexPathForSelectedRow {
dest.movieName = movieData?.boxOfficeResult.dailyBoxOfficeList[indexPath.row].movieNm ?? ""
}
}
}'Swift' 카테고리의 다른 글
| iOS 프로그래밍 실무 11주차 (1) | 2025.05.14 |
|---|---|
| iOS프로그래밍 실무 10주차 (1) | 2025.05.07 |
| iOS프로그래밍 실무 9주차 (0) | 2025.05.06 |
| iOS프로그래밍 실무 7주차 (0) | 2025.04.16 |
| iOS프로그래밍 실무 6주차 (0) | 2025.04.09 |




















