24.02.05 유튜브 API 사용하기

KSang·2024년 2월 11일
0

TIL

목록 보기
51/101

https://console.cloud.google.com/welcome/new?supportedpurview=project
구글 클라우드 서비스에서 프로젝트를 생성하고 유튜브 API3 키 를 받으면 유튜브 API를 쓸 수 있다.

Interface

유튜브 api 문서는 https://developers.google.com/youtube/v3?hl=ko 이곳에서 참조 탭을 누르면 확인 할 수 있다.

검색에서 리스트를 누르고

문서를 보면

이런식으로 데이터를 요청할때 넣어야 할 값들을 확인 할 수 있다.

요청 인터페이스를 만들었는데

interface YoutubeSearchService {

    @GET("search")
    suspend fun searchResult (
        @Query("forContentOwner") forContentOwner: String? = null, // 콘텐츠 소유자 동영상 검색 아래는 내 동영상
        @Query("forMine") forMine: String? = null, // 위랑 아래랑 둘중하나 혹은 0
        @Query("channelId") channelId: String? = null, //
        @Query("eventType") eventType: String? = null, // completed - 완료된 브로드캐스트, live , upcoming - 예정된 방송
        @Query("maxResults") maxResults: Int? = 50,
        @Query("part") part: String = "snippet",
        @Query("order") order: String = "relevance", //date – 리소스를 만든 날짜를 기준, rating – 높은 평가부터 낮은 평가순, relevance – 검색어와의 관련성을 기준, title – 제목알파벳순, viewCount – 리소스가 조회수가 높은 순
        @Query("regionCode") regionCode: String = "kr", // 국가에서 볼 수 있는 동영상
        @Query("pageToken") pageToken: String? = null,
        @Query("relevanceLanguage") relevanceLanguage: String = "ko", // 언어랑 관련성 높은 영상
        @Query("q") query: String = "react", // 검색어
        @Query("videoDuration") videoDuration: String = "any", // long – 20분보다 긴 동영상, medium – 4분에서 20분 사이의 동영상, short – 4분 미만의 동영상
        @Query("type") type: String = "video", // channel, playlist, video
        @Query("videoType") videoType: String = "any", // any – 모든 동영상을 반환합니다, episode - 프로그램의 에피소드만 검색합니다., movie - 영화만 검색합니다
        @Query("videoSyndicated") videoSyndicated: String = "true", // any – 배급 여부에 관계 없이 모든 동영상을 반환합니다.,true – 배급된 동영상만 검색합니다. 외부에서 재생할 수 있는 동영상
    ) : SearchApiResponse

이렇게 서버에 다양한 방식으로 요청 할 수 있다.

이제 데이터를 받을 모델을 만들자

DTO

문서의 오른쪽을 보면 api호출되는 데이터를 실험해 볼 수 있다.

여기에 값을 입력하면 json형식으로 서버에서 데이터를 보내게 되는데

http://json.parser.online.fr/ 를 이용하면 편하게 구조를 볼 수 있다.

여기서 보여주는 kind etag등에 맞춰서 모델을 만들어 보았다.

data class GenericApiResponse<T>(
    val etag: String?,
    val items: List<T>?,
    val kind: String?,
    val regionCode: String?,
    val nextPageToken: String?,
    val prevPageToken: String?,
    val pageInfo: PageInfo?
)
data class PageInfo(
    val resultsPerPage: Int?,
    val totalResults: Int?
)

리스폰 하는 데이터가 굉장히 많았는데

대부분의 정보를 하나로 받아둘 엔티티를 만들어 줘야 한다

data class VideoEntity(
    val id: String?,
    val publishedAt: String?,
    val channelId: String?,
    val title: String?,
    val description: String?,
    val thumbnailHigh: String?,
    val thumbnailMedium: String?,
    val thumbnailLow: String?,
    val channelTitle: String?,
    val tags: List<String>?,
    val categoryId: String?,
    val liveBroadcastContent: String?,
    val defaultLanguage: String?,
    val localizedTitle: String?,
    val localizedDescription: String?,
    val defaultAudioLanguage: String?,
    val duration: String?,
    val dimension: String?,
    val definition: String?,
    val caption: String?,
    val licensedContent: Boolean?,
    val projection: String?,
    val viewCount: String?,
    val likeCount: String?,
    val favoriteCount: String?,
    val commentCount: String?,
    val player: String?,
    val topicDetails: List<String>?,
)

이제 레포지토리를 만들어서 이 모델에 맞게 데이터를 변경 시켜줘야한다.

class ApiRepositoryImpl @Inject constructor(
    private val remoteDataSource: YoutubeSearchService,
) : ApiRepository {
    ...
    override suspend fun getPopularVideo()
            : List<VideoEntity>? = remoteDataSource.getPopularVideo().let {
        nextPageToken = it.nextPageToken
        it.items?.map { item ->
            convertVideoEntity(item)
        }
    }
    
    private fun convertVideoEntity(item: ItemResponse): VideoEntity {
        return VideoEntity(
            id = item.id ?: "",
            publishedAt = item.snippet?.publishedAt ?: "",
            channelId = item.snippet?.channelId ?: "",
            title = item.snippet?.title ?: "",
            description = item.snippet?.description ?: "",
            thumbnailHigh = item.snippet?.thumbnails?.high?.url ?: "",
            thumbnailMedium = item.snippet?.thumbnails?.medium?.url ?: "",
            thumbnailLow = item.snippet?.thumbnails?.default?.url ?: "",
            channelTitle = item.snippet?.channelTitle ?: "",
            tags = item.snippet?.tags?.toList(),
            categoryId = item.snippet?.categoryId ?: "",
            liveBroadcastContent = item.snippet?.liveBroadcastContent ?: "",
            defaultLanguage = item.snippet?.defaultLanguage ?: "",
            localizedTitle = item.snippet?.localized?.title ?: "",
            localizedDescription = item.snippet?.localized?.description ?: "",
            defaultAudioLanguage = item.snippet?.defaultAudioLanguage ?: "",
            duration = item.contentDetails?.duration ?: "",
            dimension = item.contentDetails?.dimension ?: "",
            definition = item.contentDetails?.definition ?: "",
            caption = item.contentDetails?.caption ?: "",
            licensedContent = item.contentDetails?.licensedContent,
            projection = item.contentDetails?.projection ?: "",
            viewCount = item.statistics?.viewCount ?: "",
            likeCount = item.statistics?.likeCount ?: "",
            favoriteCount = item.statistics?.favoriteCount ?: "",
            commentCount = item.statistics?.commentCount ?: "",
            player = item.player?.embedHtml ?: "",
            topicDetails = item.topicDetails?.topicCategories?.toList()
        )
    }

이렇게 하면 서버의 데이터를 사용하기 쉽게 변환 시키며 데이터를 사용할 수 있다.

사용 설명서

이제 팀원들이 보고 사용할 수 있게 설명서를 작성해줬다.

레포지토리의 함수의 기능을 설명하고 받아오는 데이터 모델의 정보를 적어서

각자의 뷰에 맞게 필요한 데이터만을 들고 갈 수 있게 했다.

interface ApiRepository {
    suspend fun searchResult(query: String): List<SearchEntity>?
    suspend fun getPopularVideo(): List<VideoEntity>?
    suspend fun getContentDetails(idList: List<String>): List<VideoEntity>?
    suspend fun getChannelDetails(idList: List<String>): List<ChannelEntity>?
    suspend fun getComments(videoId: String): List<CommentEntity>?
}

searchResult 검색어를 입력하면 검색 결과를 불러옴

getPopularVideo 호출시 동영상 인기순으로 불러옴

getContentDetails 검색이든 인기동영상이든 불러온 데이터의 비디오 아이디를 입력하면 상세한 정보가지고옴

getChannelDetails 채널의 아이디를 입력하면 채널의 상세한 정보를 가지고옴

getComments 비디오 아이디 입력 시 영상의 댓글을 가지고옴

SearchEntity.kt

idString영상의 id
publishedAtString게시일
channelIdString올린 채널 아이디
titleString영상의 제목
descriptionString영상 상세설명
thumbnailHighString큰 사이즈썸네일
thumbnailMediumString중간 사이즈 썸네일
thumbnailLowString작은 사이즈 썸네일
channelTitleString채널명
liveBroadcastContentString생방송 중인지 표시

VideoEntity.kt

idString영상의 id
publishedAtString게시일
channelIdString올린 채널 아이디
titleString영상의 제목
descriptionString영상 상세설명
thumbnailHighString큰 사이즈썸네일
thumbnailMediumString중간 사이즈 썸네일
thumbnailLowString작은 사이즈 썸네일
channelTitleString채널명
tagsList영상 태그
categoryIdString카테고리 id
liveBroadcastContentString생방송 중인지 표시
defaultLanguageString영상의 기본 언어
localizedTitleString로컬라이즈된 제목
localizedDescriptionString로컬라이즈된 설명
defaultAudioLanguageString기본 음성 언어
durationString영상 길이
dimensionString비디오의 차원, 2d, 3d
definitionString비디오 화질, “hd”고화질, “sd”표준화질
captionString자막이 사용 가능 여부
licensedContentBoolean라이선스된 콘텐츠인지 확인
projectionString비디오의 투영 방식, 일반적인 비디오는 "rectangular" , 360도 비디오는 "360" 값을 가짐
viewCountString조회 수
likeCountString좋아요 수
favoriteCountString사용자에 의해 "즐겨찾기"로 추가된 횟수,일반적으로 외부에 공개 안돼서 0만 뜸
commentCountString댓글 수
playerString동영상 플레이어 Url
topicDetailsList비디오와 연관된 주제의 id 목록, id는 키 값이니까 주의

0개의 댓글