Spring 클론코딩 프로젝트 콘텐츠 DetailPage( 감상 가능한 곳, 유튜브(youtube) 예고편, 겔러리)
🎬 감상가능한 곳 타임리프
<!-- 감상가능한 곳 719 이하-->
<attr sel="section.css-l1ynz5" th:if="${movie.watch} != null">
<attr sel="ul.css-1ohwri2-VisualUl-PartnerStackableUl" th:remove="all-but-first">
<attr sel="li.css-wj6fn0" th:each="wat : ${#strings.arraySplit(movie.watch,',')}">
<attr sel="a.css-1wacncs-InnerPartOfListWithImage" th:href="${wat}"
th:title="${#strings.contains(wat,'aHR0cHM6Ly93d3cubmV0ZmxpeC5jb20vdGl0b')} or ${#strings.contains(wat,'netflix')}?
'넷플릭스' : (${#strings.contains(wat,'aHR0cHM6Ly93YXRjaGEuY29tL3dhd')} or ${#strings.contains(wat,'https://watcha.com/watch/')}?
'왓챠' : (${#strings.contains(wat,'disneyplus')} ? '디즈니플러스' :
(${#strings.contains(wat,'aHR0cHM6Ly93d3cud2F2dmUuY29tL3BsYXllci92b2Q')} or ${#strings.contains(wat,'wavve')} ?
'웨이브' : (${#strings.contains(wat,'aHR0cHM6Ly93d3cudHZpbmcuY29tL2N')} or ${#strings.contains(wat,'tiving')}?
'티빙' : (${#strings.contains(wat,'megabox')} ? '메가박스' : 'CGV')
))))
">
<attr sel="div.css-1njml0y-ProfilePhotoImage"
th:style="'background-image:url(' +
(${#strings.contains(wat,'aHR0cHM6Ly93d3cubmV0ZmxpeC5jb20vdGl0b')} or ${#strings.contains(wat,'netflix')}?
'https://an2-glx.amz.wtchn.net/images/ex_netflix_logo_square.png' : (${#strings.contains(wat,'aHR0cHM6Ly93YXRjaGEuY29tL3dhd')} or ${#strings.contains(wat,'https://watcha.com/watch/')}?
'https://an2-glx.amz.wtchn.net/images/ex_watcha_logo_square.png' : (${#strings.contains(wat,'disneyplus')} ? 'https://an2-img.amz.wtchn.net/image/v2/ryWIr0pNWgEBU-qIsDRsYw.png?jwt=ZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd0lqb2lMM1l5TDNOMGIzSmxMM1ZwYldGblpTOHhOalF5TURZME16SXlPVEUxT0RJNE9EazFJbjAuVEM5ZjBaTnBlUmM5MklUTWdVakxmM3BieElmaTFHLTNWc0d2RUxqa3FDSQ' :
(${#strings.contains(wat,'aHR0cHM6Ly93d3cud2F2dmUuY29tL3BsYXllci92b2Q')} or ${#strings.contains(wat,'wavve')}?
'https://an2-glx.amz.wtchn.net/images/ex_wavve_logo_square.png' : (${#strings.contains(wat,'aHR0cHM6Ly93d3cudHZpbmcuY29tL2N')} or ${#strings.contains(wat,'tiving')} ?
'https://an2-img.amz.wtchn.net/image/v2/AmxtezC90nGQwOmwj0MCPA.png?jwt=ZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd0lqb2lMM1l5TDNOMGIzSmxMM1ZwYldGblpTOHhOalV3TXpRMk9UQXhNVE0xTlRBNU16TTRJbjAudWd0X0VwOHg1ZDBnZTBTRjhiNkhrUG52Qzd5cndhRnl6bEt2dEZzVGhzTQ' :
(${#strings.contains(wat,'megabox')} ? '/image/megabox_icon.png' : '/image/cgv_icon.png')
))))) +');'"/>
<attr sel="div.css-17vuhtq" th:text="${#strings.contains(wat,'aHR0cHM6Ly93d3cubmV0ZmxpeC5jb20vdGl0b')} or ${#strings.contains(wat,'netflix')}?
'넷플릭스' : (${#strings.contains(wat,'aHR0cHM6Ly93YXRjaGEuY29tL3dhd')} or ${#strings.contains(wat,'https://watcha.com/watch/')}?
'왓챠' : (${#strings.contains(wat,'disneyplus')} ? '디즈니플러스' :
(${#strings.contains(wat,'aHR0cHM6Ly93d3cud2F2dmUuY29tL3BsYXllci92b2Q')} or ${#strings.contains(wat,'wavve')}?
'웨이브' : (${#strings.contains(wat,'aHR0cHM6Ly93d3cudHZpbmcuY29tL2N')} or ${#strings.contains(wat,'tiving')}?
'티빙' : (${#strings.contains(wat,'megabox')} ? '메가박스' : 'CGV')
))))
"/>
<!-- 넷플릭스: aHR0cHM6Ly93d3cubmV0ZmxpeC5jb20vdGl0b // https://an2-glx.amz.wtchn.net/images/ex_netflix_logo_square.png-->
<!-- 왓챠: aHR0cHM6Ly93YXRjaGEuY29tL3dhd // https://an2-glx.amz.wtchn.net/images/ex_watcha_logo_square.png-->
<!-- 디즈니플러스: disneyplus // https://an2-img.amz.wtchn.net/image/v2/ryWIr0pNWgEBU-qIsDRsYw.png?jwt=ZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd0lqb2lMM1l5TDNOMGIzSmxMM1ZwYldGblpTOHhOalF5TURZME16SXlPVEUxT0RJNE9EazFJbjAuVEM5ZjBaTnBlUmM5MklUTWdVakxmM3BieElmaTFHLTNWc0d2RUxqa3FDSQ-->
<!-- 웨이브: aHR0cHM6Ly93d3cud2F2dmUuY29tL3BsYXllci92b2Q // https://an2-glx.amz.wtchn.net/images/ex_wavve_logo_square.png-->
<!-- 티빙: aHR0cHM6Ly93d3cudHZpbmcuY29tL2N // https://an2-img.amz.wtchn.net/image/v2/AmxtezC90nGQwOmwj0MCPA.png?jwt=ZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd0lqb2lMM1l5TDNOMGIzSmxMM1ZwYldGblpTOHhOalV3TXpRMk9UQXhNVE0xTlRBNU16TTRJbjAudWd0X0VwOHg1ZDBnZTBTRjhiNkhrUG52Qzd5cndhRnl6bEt2dEZzVGhzTQ-->
</attr>
</attr>
</attr>
</attr>
tb_movie 테이블의 mov_watch 컬럼에서 해당 movieIdx 값을 통해 해당하는 링크와 이미지 이름을 주기위해 타임리프에서 splt과 삼항연산자를 이용하여 구현하였다.
th:title="${#strings.contains(wat,'aHR0cHM6Ly93d3cubmV0ZmxpeC5jb20vdGl0b')} or ${#strings.contains(wat,'netflix')}? '넷플릭스' :
1. {#strings.contains(wat,'aHR0cHM6Ly93d3cubmV0ZmxpeC5jb20vdGl0b' 이 부분은 넷플릭스의 고유 주소 값이다.
2. netflix 가 포함되어도 넷플릭스인걸 알 수 있기 때문에 타임리프에서 or 조건을 사용해서 1번과 2번이 포함되면 출력하게 하였다.
3. 동일한 방식으로 이미지와 이름 링크를 삼항연산을 통해 해당하는 컬럼의 정보를 받아와 처리
🎬 감상 가능한 곳 출력 결과
🎬 감상 가능한 곳을 클릭시 해당 콘텐츠 정보에 맞는 링크에 맞게 이동하게 된다.
🎬 겔러리, 예고편 유튜브 썸네일
감상 가능한 곳과 유사하게 구현하였다. 데이터 크롤링한 양식에 따라 split을 사용하여 나누고 타임리프에 출력하게 하였다. 다만 youtube 예고편은 썸네일이 따로 크롤링을 안한 상태여서 찾는데 오랜 시간이 걸렸다.
🎬 유튜브 예고편 영상, 썸네일, 링크 타임리프
<!-- 영상 -->
<attr sel="section.video" th:if="${movie.video} != null">
<attr sel="ul.css-wq135y-VisualUl-VideoHorizontalUl" th:remove="all-but-first">
<attr sel="li.css-1xgzykb-VideoListItem" th:each="video : ${#strings.arraySplit(movie.video,'|')}">
<attr sel="a.css-18apgv4" th:href="${#strings.arraySplit(video,',')[0]}"/>
<attr sel="div.css-1fucs4t-StyledText" th:if="${#lists.size(#strings.arraySplit(video,','))} > 1"
th:text="${#strings.arraySplit(video,',')[1]}" />
<attr sel="span.css-bhgne5-StyledBackground" th:style="${#lists.size(#strings.arraySplit(video,','))} > 1? 'background-image: url(https://img.youtube.com/vi/' + ${#strings.arraySplit(#strings.arraySplit(video,',')[0],'v=')[1]} + '/0.jpg)'
:'background-image: url(https://img.youtube.com/vi/' + ${#strings.arraySplit(video,'v=')[1]} + '/0.jpg)'"/>
</attr>
</attr>
</attr>
영화 예고편 컬럼은 ' |' 기준 split을 하였고 1개 이상의 예고편이 있으면 다시 ',' 로 스플릿 후
'background-image: url(https://img.youtube.com/vi/' + ${#strings.arraySplit(#strings.arraySplit(video,',')[0],'v=')[1]} + '/0.jpg
형으로 유튜브에서 썸네일을 저장하여 코들르 수정하였더니 잘 나왔다.