본문 바로가기

Project/MovieClip

배우의 소셜 미디어 계정을 가져오는 방법 🤔

 

 

🎬 iOS에서 배우의 소셜 미디어 정보를 표시하는 방법

 

📌 1. TMDb API를 통해 소셜 미디어 데이터 가져오기

TMDb API에서는 배우의 ID를 이용해 페이스북, 인스타그램, 트위터, 유튜브 계정 정보를 가져올 수 있습니다.
아래의 API 요청을 통해 배우의 소셜 미디어 ID를 얻을 수 있습니다.

/// 🚗 peopleID를 통해 사람의 외부 소셜네트워크 확인 
func getPeopleExternalIDs(peopleID: Int) async throws -> ExternalID {
    let url = URL(string: "\(Constants.baseURL)/person/\(peopleID)/external_ids")!
    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.timeoutInterval = 10
    request.allHTTPHeaderFields = [
        "accept": "application/json",
        "Authorization": "Bearer \(Constants.API_KEY)"
    ]

    let (data, response) = try await URLSession.shared.data(for: request)

    guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
        throw APIError.failedToGetData
    }

    let peopleExternalIDs = try JSONDecoder().decode(ExternalID.self, from: data)

    return peopleExternalIDs

}

 

🔹 TMDB API 응답 데이터 예시

✅ tiktok_id와 같이 null인 걸 보니 존재하는 소셜 미디어 ID만 필터링하여 UI에 표시해야 합니다.

{
  "id": 53650,
  "freebase_mid": "/m/0c35b1",
  "freebase_id": "/en/anthony_mackie",
  "imdb_id": "nm1107001",
  "tvrage_id": null,
  "wikidata_id": "Q511554",
  "facebook_id": "OfficialAnthonyMackiePage",
  "instagram_id": "anthonymackie",
  "tiktok_id": null,
  "twitter_id": "AnthonyMackie",
  "youtube_id": null
}

 

✅ 응답 데이터에 대해 필요로한 소셜 미디어만 추출 (페이스북, 인스타그램, 트위터, 유튜브)

// MARK: - Welcome
struct ExternalID: Codable {
    let id: Int
    let facebookID, instagramID, twitterID: String?
    let youtubeID: String?

    enum CodingKeys: String, CodingKey {
        case id
        case facebookID = "facebook_id"
        case instagramID = "instagram_id"
        case twitterID = "twitter_id"
        case youtubeID = "youtube_id"
    }
}

 

 

📌 2. PeopleDetailViewController에서 소셜 데이터 가져오기

PeopleDetailViewController에서 배우의 상세 정보와 소셜 미디어 데이터를 함께 가져올 것입니다.

class PeopleDetatilViewController: UIViewController {
    
    // MARK: - Variable
    private let peopleID: Int
    
    // ✅ 배우 절보 저장
    private var peopleDetail: PeopleDetailInfoWelcome?
    private var peopleDetailHeaderView: PeopleDetailHeaderView?
    private var socialLinks: ExternalID?    // ✅ 소셜 데이터 저장
    
    ...

    // MARK: - Init
    init(peopleID: Int) {
        self.peopleID = peopleID
        super.init(nibName: nil, bundle: nil)
    }
    
    // MARK: - Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .black
        view.addSubview(peopleTableView)
         
        ...
        
        // ✅ 높이 자동 조절 설정
        peopleTableView.estimatedRowHeight = 100  // 임의의 예상 높이 설정
        
        setupTableViewDelegate()        
        fetchedPeopleDetailInfo()
    }
    
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        peopleTableView.frame = view.bounds
    }
    
    
    // MARK: - Function
    private func fetchedPeopleDetailInfo() {
        Task {
            do {
                let peopleInfo = try await NetworkManager.shared.getPeopleDetailInfo(peopleID: peopleID)
                let socialLinks = try await NetworkManager.shared.getPeopleExternalIDs(peopleID: peopleID)
                
                
                DispatchQueue.main.async {
                    
                    self.peopleDetail = peopleInfo
                    self.socialLinks = socialLinks
                    
                    guard let peopleDetail = self.peopleDetail else {
                        print("❌ no peopleDetail")
                        return
                    }
                    self.configureDetailHeaderView()    // 헤더뷰 생성
                    
                    self.peopleDetailHeaderView?.configure(with: peopleDetail, socialLinks: socialLinks)
                    self.peopleTableView.reloadData()
                }
            } catch {
                print("❌ 데이터 로드 실패: \(error)")
            }
        }
    } 
    
    ...
    
    private func configureDetailHeaderView() {
        let headerView = PeopleDetailHeaderView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 250))
        peopleTableView.tableHeaderView = headerView
        guard let peopleInfo = peopleDetail,
              let socialLinks = socialLinks
        else { return }
        headerView.configure(with: peopleInfo, socialLinks: socialLinks)
    }
}

 

  • 배우의 상세 정보(peopleInfo)와 소셜 미디어 정보(socialLinks)를 비동기 API 요청을 통해 가져옵니다.
  • 가져온 데이터를 PeopleDetailHeaderView로 전달하여 UI를 업데이트합니다.

 

📌 3. PeopleDetailHeaderView에서 소셜 미디어 버튼 추가

이제 소셜 미디어 버튼을 **가로 방향의 UIStackView**를 이용하여 동적으로 추가합니다.

1️⃣ configureSocialButtons 함수: 존재하는 소셜 미디어만 추가

private func configureSocialButtons(socialLinks: ExternalID) {

    var hasSocialMedia: Bool = false     // ✅ 소셜 미디어 버튼 추가 여부 확인

    if let facebookID = socialLinks.facebookID {
        addSocialButton(icon: "FacebookLogo", url: "https://www.facebook.com/\(facebookID)")
        hasSocialMedia = true
    }

    if let instagramID = socialLinks.instagramID {
        addSocialButton(icon: "InstagramLogo", url: "https://www.instagram.com/\(instagramID)")
        hasSocialMedia = true
    }

    if let twitterID = socialLinks.twitterID {
        addSocialButton(icon: "TwitterLogo", url: "https://twitter.com/\(twitterID)")
        hasSocialMedia = true
    }

    if let youtubeID = socialLinks.youtubeID {
        addSocialButton(icon: "YoutubeLogo", url: "https://www.youtube.com/\(youtubeID)")
        hasSocialMedia = true
    }

    // ✅ 소셜 미디어가 하나도 없는 경우 안내 문구 추가
    if !hasSocialMedia {
        let infoLabel = UILabel()
        infoLabel.text = "No Social Media"
        infoLabel.font = .systemFont(ofSize: 16, weight: .bold)
        infoLabel.textColor = .lightGray
        infoLabel.textAlignment = .center
        socialStackView.addArrangedSubview(infoLabel)
    }
}

 

 

소셜 미디어 ID가 존재하는 경우만 버튼을 추가하고,
모든 소셜 미디어가 없으면 "No Social Media" 문구를 추가합니다.

 

2️⃣ addSocialButton 함수: 소셜 버튼 생성 및 이벤트 추가

// ✅ 소셜 미디어 버튼 추가 메서드
private func addSocialButton(icon: String, url: String) {

    let button = UIImageView()
    let image = UIImage(named: icon)
    button.image = image   // ✅ 로고 이미지 설정
    button.contentMode = .scaleAspectFit
    button.isUserInteractionEnabled = true

    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapSocialButton(_:)))
    button.addGestureRecognizer(tapGesture)
    button.accessibilityHint = url // ✅ URL 저장

    socialStackView.addArrangedSubview(button) // ✅ 스택뷰에 추가
}

 

UIImageView를 생성하여 소셜 미디어 로고를 설정
제스처 (UITapGestureRecognizer)를 추가하여 버튼을 클릭할 수 있도록 구현
✔ 버튼이 눌리면 didTapSocialButton(_:) 메서드가 실행됨

 

3️⃣ didTapSocialButton 함수: 버튼 클릭 시 해당 사이트로 이동

@objc private func didTapSocialButton(_ sender: UITapGestureRecognizer) {
    guard let button = sender.view as? UIImageView,
          let urlString = button.accessibilityHint,
          let url = URL(string: urlString) else { return }
    UIApplication.shared.open(url)
}

 


✅ didTapSocialButton(_:) 함수 분석

🔹 1. button = sender.view as? UIImageView의 의미

  • sender는 UITapGestureRecognizer(탭제스처) 객체
  • sender.view제스처가 추가된 뷰를 의미 (UIImageView가 제스처를 가진 상태)
  • as? UIImageView를 사용해서 해당 뷰가 UIImageView 타입이면 button 변수에 할당
  • 만약 UIImageView가 아니라면 nil을 반환하고, guard문에서 탈출(return)

💡 즉, UIImageView(소셜 아이콘 버튼)를 탭한 경우에만 동작하도록 하기 위함!

 

🔹 2. button.accessibilityHint란?

  • accessibilityHintUIKit에서 접근성을 제공하는 프로퍼티로, 화면을 읽어주는 VoiceOver 기능에서 사용
  • 하지만, 이걸 커스텀 데이터 저장 용도로도 사용 가능
  • 여기서는 accessibilityHint를 사용하여 소셜 네트워크의 URL을 저장하는 역할
  • 버튼을 클릭하면 button.accessibilityHint를 통해 저장된 URL을 가져와 브라우저에서 실행
  • 예시:
button.accessibilityHint = "https://www.facebook.com/username"

 

🔹 3. UIApplication.shared.open(url) 동작

 

  • iOS 시스템에서 Safari 또는 해당 앱을 통해 해당 URL을 실행
  • 예를 들어 https://www.facebook.com/username이면 Safari에서 열리고,
    instagram://user?username=instagram_id 같은 경우 Instagram 앱에서 실행

 

UIApplication.shared.open(url)

 

🛠 최종적으로 didTapSocialButton(_:) 함수의 동작 흐름

  1. 사용자가 소셜 미디어 버튼(UIImageView)을 탭
  2. UITapGestureRecognizer가 동작하며 sender.view를 가져옴
  3. sender.view가 UIImageView인지 확인 후, button 변수에 할당
  4. button.accessibilityHint에 저장된 URL 값을 가져옴
  5. URL(string: urlString)을 통해 유효한 URL인지 확인
  6. UIApplication.shared.open(url)을 실행하여 웹 브라우저 또는 해당 앱에서 URL을 실행

🚀 정리 및 핵심 포인트

✅ TMDb API를 이용하여 배우의 소셜 미디어 정보를 가져옴
PeopleDetailViewController에서 배우의 상세 정보 및 SNS 정보를 가져와 UI에 전달
PeopleDetailHeaderView에서 존재하는 소셜 미디어만 버튼으로 표시하고, 없으면 안내 문구 추가
UITapGestureRecognizer를 사용하여 버튼 클릭 시 해당 SNS 페이지로 이동