
최근에 회사 깃허브 코드를 뒤적거리다가 내가 0년차 시절에 개발했던 코드를 발견했다. 그 시절 내 가 작성한 코드가 궁금하기도 하고, 이런 것을 기록해두면 좋을 것 같아서 당시에 작업했던 코드와 간단한 설명을 작성해볼까 한다.

사실 나는 프론트엔드 개발자로 회사에 입사를 했다. 컴공 전공도 아니라서 여느 컴공전공자와 비교하면 아주아주 많이 부족하다. 그 부족함은 사실 지금도 마찬가지라고 생각하지만, 유일하게 내가 잘할 수 있는 것은 무엇인가를 배움에 있어서 학습 속도가 그래도 빠른편이다. 애초에 코딩에 코도 몰랐던 사람이라서 어떤 것을 받아들이고 실행하는데 빠른게 큰 장점이다. 처음 회사에 입사했을때 10년차 개발자 두분과 3년차 (IOS, 풀스택)이 가능한 개발자 총 3분이 있으셨고, 당시 회사 웹페이지는 플라스크 프레임웍을 사용해서 웹페이지가 돌아가고 있었다. 그래서 나도 당현하게 js code가 아닌 python code와 api, postSQL(DB), DB을 사용하기 위해한 환경설정 셋팅, VPN 설정 등 아주 저 세상 이세상 왔다갔다하며 정신없이 배우고 회사의 개발환경을 따라가야했다.

사실 이 이말은 주니어 개발자가 아주아주 많이 듣는말이다. 이 말을 듣는 주니어 개발자 대부분은 나처럼 생하지 않을까? 언어가 도구? 그것도 도구를 잘 사용할줄 아는 사람이 다른 도구를 사용하는 것이지....
하지만, 정작 내가 언어는 도구에 불과하다 라는 것을 몸소 증명해야 하는 입장이 되었을때는.. 그 도구를 사용해서 결과물을 만들어야 했다. 물론 훌륭한 선입 개발자 분들께서 책도 선물로 주시고, 여러 레퍼런스도 공부할 수 있게 알려주셨기에 빠르게 개발을 할 수 있었다.
고객이 우리 웹페이지를 이용해서 온라인채널에 상품을 판매한다면, 해당 고객의 상품 정보를 바탕으로 온라인 채널의 상세페이지에서 상품을 구매하는 사람에게 어떻게 상품이 보여지는지 확인할 수 있는 프리뷰 상세페이지를 만들어야 했다.
2주안에 기획하고, 백엔드 부터 프론트까지 전반적인 업무를 내가 주도해서 진행해야했고, 선임개발자 한분이 서포트 해주는 방식으로 개발을 진행해야 했다.
처음에는 2주안에 내가? 이것을? 개발해야한다고? ... 아 난 이제 짤리는 것인가? 싶었다.
왜냐하면, 당시에 입사한지 1달 정도 되었을때고, 백부터 프론트, DB까지 전반적으로 모두 알아야 개발이 가능하기 때문이다. 물론 서포트해주시는 훌륭한 선임개발자 분이 있으시만...그분도 바쁘시다....
그럼 내가 가장 자신있는 분야인 프론트 페이지 부터 빠르게 개발을 진행해야 했다. 현재 구현되고 있는 개발환경에 react가 돌아갈 수 있게끔 설정해서 진행을 해볼까 싶었는데... 지금 이 거대한 코드정글에 내가 리엑트를 심어보겠다는 것은 .... 환경설정한 하다가 1주일을 날릴것 같았다....
그래서 생각한 방법이 애초에 만들어야하는 페이지가 이미 만들어져있는 온라인채널에 상세페이지기 때문에 HTML sorce code를 뽑아서 정적파일로 만들어 버리면 되겠다 싶었다. 이게 신의한수이지 안았나 싶다. 지금까지 내가 이 회사에서 일할 수 있게된 이유(지금 와서 생각해보니 당시에 짤리지 않은 이유가 아니지 않나 싶다.)
HTML 소스코드를 뽑아서 구조를 잡고 필요한 부분만 편집해서 3일만에 3개의 정적웹페이지를 html로 만들수 있었다. 이것도 쉽지는 않았다. 소스코드를 데이터를 뽑으면 정말 해당 웹페이지의 html,css 등과 인코딩된 이미지 정보나 각정 정보들이 아주아주 보기 힘들게 들어오기 때문에, 소스코드의 어떤 코드가 보여지는 웹페이지에서 어떤 기능과 디자인을 담당하는 것인지 파악해야 했다.
*코드가 너무 길어서 중간 생략했다.
{% block contents %}
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta http-equiv="Cache-Control" content="no-cache, no-store">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="x-dns-prefetch-control" content="on">
<meta property="og:type" content="article">
<meta name="twitter:card" content="summary_large_image">
<meta name="viewport" content="width=device-width,initial-scale=1.3, minimum-scale=0">
<link rel= "stylesheet" href="Naver/Naver.css">
<style>
body,
p,
h1,
h2,
h3,
h4,
h5,
h6,
ul,
ol,
li,
dl,
dt,
dd,
table,
th,
td,
form,
fieldset,
legend,
input,
textarea,
button,
select {
margin: 0;
padding: 0;
}
body,
input,
textarea,
select,
button,
table {
font-family: Helvetica, '나눔고딕', 'Nanum Gothic', '나눔스퀘어', 'Nanum Square', 'Apple SD Gothic Neo', 'Malgun Gothic', '맑은 고딕', Dotum, '돋움', sans-serif;
font-size: 12px;
line-height: 1.5em;
}
body {
position: relative;
background-color: #ffffff;
}
img,
fieldset {
border: 0;
}
ul,
ol {
list-style: none;
}
em,
address {
font-style: normal;
}
a,
a:hover,
a:active,
a:focus {
text-decoration: none;
}
table {
border-collapse: collapse;
}
hr {
display: none !important;
}
button {
border: none;
background-color: transparent;
cursor: pointer;
}
img {
vertical-align: top;
}
.blind,
.u_skip {
overflow: hidden;
position: absolute;
top: 0;
left: 0;
clip: rect(0 0 0 0);
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
border: 0;
}
/* SE 3.0 이하 대응 코드 */
/* SE 뷰어영역 */
.detail_viewer .se_textView span {
vertical-align: baseline;
}
/* SE 상품 태그(태깅 상품 툴팁 내용 -> product_tagging.css) */
.detail_viewer .se_point_tag_tooltip .se_point_tag_button {
background: /*savepage-url=img/svg/icon/icon_plus_squared_31x31_white.svg*/ url() no-repeat;
background-size: auto;
}
.detail_viewer .se_point_tag_tooltip.is-active .se_point_tag_button {
background: /*savepage-url=img/svg/icon/icon_x_squared_31x31_black.svg*/ url() no-repeat;
background-size: auto;
}
/* 센터 상품조회/수정 미리보기 > 미지원 첨부파일 */
.detail_viewer .editor_preview {
width: 298px;
height: 108px;
border: 1px solid #ededed;
background-color: #fafafa;
text-align: center;
}
.detail_viewer .editor_preview .preview_txt {
padding-top: 26px;
font-family: '나눔고딕', 'Nanum Gothic','굴림', Gulim, sans-serif;
font-size: 18px;
color: #1088ed;
letter-spacing: -1px;
}
.detail_viewer .editor_preview .preview_txt_depth {
margin-top: 2px;
font-family: '나눔고딕', 'Nanum Gothic', '굴림', Gulim, sans-serif;
font-size: 13px;
color: #848992;
letter-spacing: -1px;
}
.detail_viewer .editor_preview .ico {
display: inline-block;
width: 22px;
height: 22px;
margin: -2px 5px 0 0;
background: /*savepage-url=https://img-shop.pstatic.net/storefarm/front/common/point_ico.png*/ url() 0 0 no-repeat;
vertical-align: top;
}
</style>
<title>Smart Store</title>
<script charset="utf-8" data-savepage-src="https://static-resource-smartstore.pstatic.net/smartstore/p/static/20220105191207/js/0.5c1a8ea7.chunk.js"></script>
<script charset="utf-8" data-savepage-src="https://static-resource-smartstore.pstatic.net/smartstore/p/static/20220105191207/js/1.46c2759e.chunk.js"></script>
<script charset="utf-8" data-savepage-src="https://static-resource-smartstore.pstatic.net/smartstore/p/static/20220105191207/js/2.9ba08edb.chunk.js"></script>
<script charset="utf-8" data-savepage-src="https://static-resource-smartstore.pstatic.net/smartstore/p/static/20220105191207/js/16.2abe24a9.chunk.js"></script>
<style type="text/css" id="s1421-0">._17oierHrKR{position:relative;min-width:1320px}._17oierHrKR ._19QB6iPgUU{margin:0 auto}._17oierHrKR ._19QB6iPgUU:after{display:table;clear:both;content:''}._17oierHrKR ._1XbSLEY_rb,._17oierHrKR ._3ZEeXLwPLs{position:relative}._17oierHrKR ._1GkFIIZx08{clear:both}.layout_wide ._17oierHrKR ._3ZEeXLwPLs,.layout_wide ._17oierHrKR ._1GkFIIZx08{width:1280px;margin:0 auto}.layout_divide ._17oierHrKR ._19QB6iPgUU{width:1280px;padding-top:50px}.layout_divide ._17oierHrKR ._1XbSLEY_rb{float:left;width:210px}.layout_divide ._17oierHrKR ._3ZEeXLwPLs,.layout_divide ._17oierHrKR ._1GkFIIZx08{float:right;width:1020px}
</style>
<style type="text/css" id="s1373-0">._14Ezl7R3c-{position:relative;background-color:#fff}.skin_black ._14Ezl7R3c-{background-color:#2f2f2f}.skin_gray ._14Ezl7R3c-{background-color:#666668}.skin_blue ._14Ezl7R3c-{background-color:#6b90dc}.skin_brown ._14Ezl7R3c-{background-color:#654f43}.skin_green ._14Ezl7R3c-{background-color:#5dcb73}.skin_cyan ._14Ezl7R3c-{background-color:#20c5b0}.skin_pink ._14Ezl7R3c-{background-color:#ff9dc5}.skin_hotpink ._14Ezl7R3c-{background-color:#fc5296}.skin_orangered ._14Ezl7R3c-{background-color:#e96061}.skin_red ._14Ezl7R3c-{background-color:#ee4a44}.skin_violet ._14Ezl7R3c-{background-color:#af7de7}.skin_yellow ._14Ezl7R3c-{background-color:#fcdf33}.skin_orange ._14Ezl7R3c-{background-color:#f79a49}.skin_ivory ._14Ezl7R3c-{background-color:#eae1d8}._14Ezl7R3c-:before{position:absolute;top:36px;right:0;left:0;background-color:rgba(0,0,0,0.07);height:1px;content:''}._14Ezl7R3c- ._1G2E7OXbG3{width:1280px;margin:0 auto}.error ._14Ezl7R3c-:before{content:none}
</style>
<ul class="_3tAzii7AAC">
<li class="_3PSm5YaiyP">
<div class="_10YmOw_HhF">무이자할부</div>
<div class="_2yGarV8XbC">카드 자세히보기<div class="_1FiytDqWF3"><a href="javascript:void(0)" role="button" class="_1_kvkzWIXh N=a:pcs.card" aria-haspopup="true"><span class="blind">카드 자세히보기</span></a></div></div></li></ul><div class="_2aYX1XhVN_"></div><div class="bd_3gWGS" style="margin: 16px 0px;"><div class="bd_38mf4">
<input id="SUMMARY_TEXTOPTION4003702881" type="text" class="bd_3u0ss" maxlength="21" value=""><label for="SUMMARY_TEXTOPTION4003702881" class="bd_14mgg">상품정보 일정 선택</label></div></div><div class="bd_2dy3Y" style="margin: 16px 0px;"><div class="bd_3hLoi"><a href="javascript:void(0)" role="button" class="bd_1fhc9 N=a:pcs.opopen" aria-expanded="false" aria-haspopup="listbox">상품선택하기<span class="bd_25oXD"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="8" viewBox="0 0 14 8" fill="#acb2bc" fill-rule="evenodd" class="bd_b8GzE"><path d="M13 2v1h-1v1h-1v1h-1v1H9v1H8v1H6V7H5V6H4V5H3V4H2V3H1V2H0V0h1v1h1v1h1v1h1v1h1v1h1v1h2V5h1V4h1V3h1V2h1V1h1V0h1v2h-1z"></path></svg></span></a></div></div><div class="bd_3pIR3 bd_2GgKt"></div><div class="bd_1ziSi bd_xMsL8 bd_7h93m" style="margin-top: 26px;"><strong class="bd_28JKM">총 상품 금액</strong><div class="bd_CVTqI" style="margin: 4px 0px 0px 6px;"><button type="button" class="bd_32dL8 N=a:pcs.price" aria-haspopup="true" aria-expanded="false"><svg xmlns="http://www.w3.org/2000/svg" width="6" height="8" class="bd_3GYLw"><path fill="#5f5f5f" fill-rule="evenodd" d="M5 3v1H4v2H2V4h1V3h1V1H2v1H0V1h1V0h4v1h1v2H5zM4 8H2V7h2v1z"></path></svg> <span class="blind">도움말</span></button><div class="bd_y5n6u bd_2ZJCl bd_2K79u" style="display: none;"><i class="bd_1XGXQ"></i><button type="button" class="bd_3gqWB"><svg xmlns="http://www.w3.org/2000/svg" width="11" height="11" viewBox="0 0 17 17" class="bd_K4Ce9"><path fill-rule="evenodd" d="M16.272 0L8.5 7.772.728 0 0 .728 7.772 8.5 0 16.272.728 17 8.5 9.228 16.272 17l.728-.728L9.228 8.5 17 .728 16.272 0z"></path></svg><span class="blind">닫기</span></button></div></div><div class="bd_3XvVU"><em class="bd_1hU3G">총 수량 0개</em><strong class="bd_1Ukv5 bd_2WCtq"><span class="bd_32Qz_">0</span>원</strong></div></div><div class="XqRGHcrncz"><div class="_3YA58cPPsy"><div class="OgETmrvExa N=a:pcs.buy"><a href="javascript:void(0)" class="_2-uvQuRWK5"><span class="blind">구매하기</span></a></div></div><div class="_3YA58cPPsy"><div class="_39-ECjV6I9 N=a:pcs.talk"><a href="javascript:void(0)" role="button" class="H4-2Au4vay"><span class="blind">톡톡문의</span></a></div><div class="_3Dy-2NaoiG N=a:pcs.fav"><a href="javascript:void(0)" role="button" class="_8ToEZI8a1P" aria-pressed="false"><span class="_1F0dbkDlNA"><span class="blind">찜하기</span></span><em class="_1c-2nfzJqH">0</em></a></div><div class="C_muF3UG0- N=a:pcs.cart"><a href="javascript:void(0)" role="button" class="_3g6Aiz5G_O"><span class="blind">장바구니</span></a></div></div></div><div class="aJuhuTnqSk"><span class="_3xupw7lyht">쇼핑할 때 필독</span><a href="https://ips.smartstore.naver.com/main/rules/safety/tip" target="_blank" class="Cmxi1kYHdo N=a:pcs.safe">안전거래TIP</a></div><div class="_1-AmbOd6-s"><span class="_2rrRsP1ieh">상품정보에 문제가 있나요?</span><a href="javascript:void(0)" class="_2milcSBYyV">신고하기</a></div></fieldset></div></div>
<!--//! babylife 상세페이지 상단 상품리뷰 박스 -->
<!--//상세페이지 바디 시작 부분 상단 메뉴바 -->
<div class="_27jmWaPaKy" style="margin-top: 40px; margin-bottom: 29px;">
<ul class="_1YrqjEd5tF" role="menubar">
<li class="_1k5R-niA93" role="presentation"><a href="javascript:void(0)" class="_11xjFby3Le N=a:tab.detail" role="menuitem" aria-current="true">상세정보</a></li><li class="_1k5R-niA93" role="presentation"><a href="javascript:void(0)" class="_11xjFby3Le N=a:tab.review" role="menuitem" aria-current="false">리뷰<span class="_3HJHJjSrNK"></span></a></li><li class="_1k5R-niA93" role="presentation"><a href="javascript:void(0)" class="_11xjFby3Le N=a:tab.qna" role="menuitem" aria-current="false">Q&A<span class="_3HJHJjSrNK">0</span></a></li><li class="_1k5R-niA93" role="presentation"><a href="javascript:void(0)" class="_11xjFby3Le N=a:tab.refund" role="menuitem" aria-current="false">반품/교환정보</a></li></ul><div class="_2S4dTJHMqp">코디탭을 눌러서 코디상품을 확인하세요.<a class="_2AGkJxm1d2" href="javascript:void(0)" role="button"><span class="blind">닫기</span></a></div></div>
<div class="_13jaAjXOM3" id="_productTabContainer" style="display: none;"><div class="_2h6D_-8NAA"><div class="XYLPnZFSI9"><div class="_5h5vi-6bDY">
<img data-savepage-src="https://shop-phinf.pstatic.net/20200215_207/1581768516931RKtMp_JPEG/19128351478281797_984669196.jpg?type=f100" src=" " data-src="https://shop-phinf.pstatic.net/20200215_207/1581768516931RKtMp_JPEG/19128351478281797_984669196.jpg?type=f100" alt="대표이미지" class="_3y7kKUn1at"></div>
<div class="u-R1aXGG7g"><strong class="_3BdmszQRsm"><span class="blind">상품 가격</span><span class="_1qLf5D2rPc">18,000</span>원</strong></div></div><button type="button" class="_2JBRFJUexk"><span class="blind">구매하기</span></button><div class="_26N7rExkKO"><div class="qW1BN12tZb"><div class="_2sYhI4p9jg"><div class="bd_3gWGS" style="margin: 16px 0px;"><div class="bd_38mf4"><input id="TABBAR_TEXTOPTION4003702881" type="text" class="bd_3u0ss" maxlength="21" value=""><label for="TABBAR_TEXTOPTION4003702881" class="bd_14mgg">투어일 (2000-00-00)을 입력해주세요.</label></div></div><div class="bd_2dy3Y" style="margin: 16px 0px;"><div class="bd_3hLoi"><a href="javascript:void(0)" role="button" class="bd_1fhc9 N=a:pcs.opopen" aria-expanded="false" aria-haspopup="listbox">선셋세일링 상품선택하기<span class="bd_25oXD"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="8" viewBox="0 0 14 8" fill="#acb2bc" fill-rule="evenodd" class="bd_b8GzE"><path d="M13 2v1h-1v1h-1v1h-1v1H9v1H8v1H6V7H5V6H4V5H3V4H2V3H1V2H0V0h1v1h1v1h1v1h1v1h1v1h1v1h2V5h1V4h1V3h1V2h1V1h1V0h1v2h-1z"></path></svg></span></a></div></div><div class="bd_3pIR3 bd_2GgKt bd_2veb0"></div></div><div class="_2sYhI4p9jg"><div class="bd_1ziSi bd_xMsL8 bd_7h93m"><strong class="bd_28JKM">총 상품 금액</strong><div class="bd_CVTqI" style="margin: 4px 0px 0px 6px;"><button type="button" class="bd_32dL8 N=a:pcs.fprice" aria-haspopup="true" aria-expanded="false"><svg xmlns="http://www.w3.org/2000/svg" width="6" height="8" class="bd_3GYLw"><path fill="#5f5f5f" fill-rule="evenodd" d="M5 3v1H4v2H2V4h1V3h1V1H2v1H0V1h1V0h4v1h1v2H5zM4 8H2V7h2v1z"></path></svg> <span class="blind">도움말</span></button><div class="bd_y5n6u bd_2ZJCl bd_2K79u" style="display: none;"><i class="bd_1XGXQ"></i><button type="button" class="bd_3gqWB"><svg xmlns="http://www.w3.org/2000/svg" width="11" height="11" viewBox="0 0 17 17" class="bd_K4Ce9"><path fill-rule="evenodd" d="M16.272 0L8.5 7.772.728 0 0 .728 7.772 8.5 0 16.272.728 17 8.5 9.228 16.272 17l.728-.728L9.228 8.5 17 .728 16.272 0z"></path></svg><span class="blind">닫기</span></button></div></div><div class="bd_3XvVU"><em class="bd_1hU3G">총 수량 0개</em><strong class="bd_1Ukv5 bd_2WCtq"><span class="bd_32Qz_">0</span>원</strong></div></div><div class="XqRGHcrncz"><div class="_3YA58cPPsy"><div class="OgETmrvExa N=a:itm.fbuy"><a href="javascript:void(0)" class="_2-uvQuRWK5"><span class="blind">구매하기</span></a></div></div><div class="_3YA58cPPsy"><div class="_39-ECjV6I9 N=a:itm.ftalk"><a href="javascript:void(0)" role="button" class="H4-2Au4vay"><span class="blind">톡톡문의</span></a></div><div class="_3Dy-2NaoiG N=a:itm.ffav"><a href="javascript:void(0)" role="button" class="_8ToEZI8a1P" aria-pressed="false"><span class="_1F0dbkDlNA"><span class="blind">찜하기</span></span><em class="_1c-2nfzJqH">0</em></a></div><div class="C_muF3UG0- N=a:itm.fcart"><a href="javascript:void(0)" role="button" class="_3g6Aiz5G_O"><span class="blind">장바구니</span></a></div></div></div><div class="aJuhuTnqSk"><span class="_3xupw7lyht">쇼핑할 때 필독</span><a href="https://ips.smartstore.naver.com/main/rules/safety/tip" target="_blank" class="Cmxi1kYHdo">안전거래TIP</a></div></div></div></div><button type="button" class="_11s3Ki0GEx"><span class="blind">간편구매닫기</span></button><div class="_27jmWaPaKy _1dDHKD1iiX"><ul class="_1YrqjEd5tF" role="menubar"><li class="_1k5R-niA93" role="presentation"><a href="javascript:void(0)" class="_11xjFby3Le N=a:tab.detail" role="menuitem" aria-current="true">상세정보</a></li><li class="_1k5R-niA93" role="presentation"><a href="javascript:void(0)" class="_11xjFby3Le N=a:tab.review" role="menuitem" aria-current="false">리뷰<span class="_3HJHJjSrNK">2</span></a></li><li class="_1k5R-niA93" role="presentation"><a href="javascript:void(0)" class="_11xjFby3Le N=a:tab.qna" role="menuitem" aria-current="false">Q&A<span class="_3HJHJjSrNK">0</span></a></li><li class="_1k5R-niA93" role="presentation"><a href="javascript:void(0)" class="_11xjFby3Le N=a:tab.refund" role="menuitem" aria-current="false">반품/교환정보</a></li></ul><div class="_2S4dTJHMqp">코디탭을 눌러서 코디상품을 확인하세요.<a class="_2AGkJxm1d2" href="javascript:void(0)" role="button"><span class="blind">닫기</span></a></div></div></div></div>
<!--//! babylife 상세페이지 바디 시작 부분 -->
<div id="INTRODUCE">
<div class="E-N5zuAehq detail_viewer"><div class="_3QY5J8865O"><div class="_1-E6pu5hXf"><strong class="_3t015QAaQ1">직거래 유도 주의 안내</strong><br>스마트스토어를 통해 톡톡 / 상품문의 등을 활용하여 <span class="_2484Ldw4O8">현금결제를 유도하는 경우 사기의 가능성이 있으니 절대 결제하지 마시고</span> <a href="https://pay.naver.com/notice/view?noticeHeader=SAFETY_TRADE&id=200013963" class="_3fydu7qXFO" target="_blank">네이버페이 고객센터로 문의 주시기 바랍니다.</a></div></div><div class="attribute_wrapper"><div class="_34LcIArKnw" style="margin-top: 30px; margin-bottom: 40px;"><strong class="_3ZUdtx9GtU">상품정보<button type="button" class="_3Rx0ryDEsN">신고하기</button></strong><div class="_2E4i2Scsp4 _copyable"><table class="_1_UiXWHt__"><caption class="kOqCtyOcXE"><span class="blind"></span></caption><colgroup><col width="160"><col><col width="160"><col></colgroup><tbody><tr><th scope="row" class="_1iuv6pLHMD">상품번호</th><td colspan="1" class="ABROiEshTD"><b></b></td><th scope="row" class="_1iuv6pLHMD">상품상태</th><td colspan="1" class="ABROiEshTD">신상품</td></tr><tr><th scope="row" class="_1iuv6pLHMD">모델명</th><td colspan="1" class="ABROiEshTD">상품페이지 참조</td><th scope="row" class="_1iuv6pLHMD">원산지</th><td colspan="1" class="ABROiEshTD">국산</td></tr></tbody></table></div><p class="_2wtHBKC0qy">상품정보 관련 문의사항은 <a href="javascript:void(0)" class="_3g3llGDI10">Q&A</a>에 남겨주세요.</p><div class="_3EFpctgsdH"><table class="euyKo2L1GK"><caption class="_1fu3I9aWYz"><span class="blind">상품정보</span></caption><colgroup><col width="160"><col></colgroup><tbody><tr><th scope="row" class="_2NHlAf7nlw">영수증발급</th><td colspan="3" class="_1JIaLFvtK4"><div>신용카드전표, 현금영수증발급</div></td></tr><tr><th scope="row" class="_2NHlAf7nlw">A/S 안내</th><td colspan="3" class="_1JIaLFvtK4"><div></div><div></div></td></tr></tbody></table></div></div></div><div>
<!--//! babylife 상세페이지 메인 사진 정보 시작 -->
<div class="_9F9CWn02VE" style="margin-bottom: 24px;"><div class="editor_wrap se_smartstore_wrap">
<div>
<div id="SEDOC-1582624880582--508142350" class="se_doc_viewer se_body_wrap se_theme_transparent " data-docversion="1.0">
<div class="se_doc_header_start" id="SEDOC-1582624880582--508142350_se_doc_header_start">
</div>
<!-- SE_DOC_HEADER_START -->
<div id="SEDOC-1582624880582--508142350_viewer_head" class="se_viewer_head"></div>
<div class="se_component_wrap">
</div>
<!-- SE_DOC_HEADER_END -->
<div class="se_doc_header_end" id="SEDOC-1582624880582--508142350_se_doc_header_end"></div>
<div class="se_doc_contents_start" id="SEDOC-1582624880582--508142350_se_doc_contents_start"></div>
<!-- SE_DOC_CONTENTS_START -->
<div class="se_component_wrap sect_dsc __se_component_area">
<div class="se_component se_paragraph default">
<div class="se_sectionArea">
<div class="se_editArea">
<div class="se_viewArea se_ff_nanumgothic se_fs_T3 se_align-left">
<div class="se_editView">
<div class="se_textView">
<p class="se_textarea"><!-- SE3-TEXT { --><!-- } SE3-TEXT --></p>
</div>
</div>
</div>
</div>
</div>
</div>
<!--//! babylife 상세페이지 메인 사진 -->
<div class="se_component se_image default">
<div class="se_sectionArea se_align-left">
<div class="se_editArea">
<div class="se_viewArea" style="max-width:858px">
<a onclick="return false;" class="se_mediaArea __se_image_link __se_link" data-linktype="img" data-linkdata="{"imgId":"SEDOC-1582624880582--508142350_image_1_img","src":"https://shop-phinf.pstatic.net/20200225_63/1582624876779ETJD5_JPEG/%B6%F3%BF%EE%C1%F6%BB%E7%C1%F8.jpg","linkUse":"false","link":""}" area-hidden="true">
<img id="SEDOC-1582624880582--508142350_image_1_img" class="se_mediaImage __se_img_el" src="https://ak-d.tripcdn.com/images/fd/tg/g6/M09/16/D0/CggYtFcYcHOAS5cNAB9Jw0UaniI094.jpg?proc=source/trip;namelogo/d_40" width="858" height="371" data-attachment-id="IS6GKMBf0bdl-Oukqz4YaG-ARETQ" alt="mainpage2">
</a>
</div>
</div>
</div>
</div>
<!-- //! babylife 상세페이지 메인 이미지 정보 최하단 이미지 -->
<div class="se_component se_image default">
<div class="se_sectionArea se_align-justify">
<div class="se_editArea">
<div class="se_viewArea">
<a onclick="return false;" class="se_mediaArea __se_image_link __se_link" data-linktype="img" data-linkdata="{"imgId":"SEDOC-1582624880582--508142350_image_3_img","src":"
https://shop-phinf.pstatic.net/20200220_82/1582178175239lAVa7_JPEG/%C1%D6%C0%C7%BB%E7%C7%D7_%BC%B1%BC%C2.jpg","linkUse":"false","link":""}" area-hidden="true">
<img src='https://ak-d.tripcdn.com/images/fd/tg/g6/M09/16/D0/CggYtFcYcHOAS5cNAB9Jw0UaniI094.jpg?proc=source/trip;namelogo/d_40' alt="mainpage" />
</a>
</div>
</div>
</div>
</div>
<div class="se_component se_paragraph default">
<div class="se_sectionArea">
<div class="se_editArea">
<div class="se_viewArea se_ff_nanumgothic se_fs_T3 se_align-left">
<div class="se_editView">
<div class="se_textView">
<p class="se_textarea"><!-- SE3-TEXT { --><!-- } SE3-TEXT --></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- SE_DOC_CONTENTS_END -->
<div class="__se_doc_title_end" id="se_doc_contents_end"></div>
<div id="SEDOC-1582624880582--508142350_se_doc_footer" class="se_doc_footer"></div>
</div>
</div>
</div>
</div>
</div>
<div class="_3tOHzGe72X"></div><div class="product_info_notice"><div class="_2E4i2Scsp4 _copyable" style="margin-top: 30px; margin-bottom: 60px;">
<!--//! babylife 상세페이지 정보 공시 끝부분 -->
<strong class="_4MkjXBK5Ox">상품정보 제공고시</strong>
<table class="_1_UiXWHt__"><caption class="kOqCtyOcXE"><span class="blind">상품정보 제공고시</span></caption><colgroup>
<col width="160"><col></colgroup><tbody><tr><th scope="row" class="_1iuv6pLHMD">서비스 제공 사업자</th><td colspan="1" class="ABROiEshTD"></td></tr><tr><th scope="row" class="_1iuv6pLHMD">법에 의한 인증·허가 등을 받았음을 확인할 수 있는 경우 그에 대한 사항</th><td colspan="1" class="ABROiEshTD">상품상세참조</td></tr><tr><th scope="row" class="_1iuv6pLHMD">이용조건</th><td colspan="1" class="ABROiEshTD">상품상세참조</td></tr><tr><th scope="row" class="_1iuv6pLHMD">취소·중도해약·해지 조건 및 환불기준</th><td colspan="1" class="ABROiEshTD">상품상세참조</td></tr><tr><th scope="row" class="_1iuv6pLHMD">취소·환불방법</th><td colspan="1" class="ABROiEshTD">상품상세참조</td></tr><tr><th scope="row" class="_1iuv6pLHMD">소비자 상담 관련 전화번호</th><td colspan="1" class="ABROiEshTD"></td></tr></tbody></table></div></div><div class="trade_terms_info"><div class="_2E4i2Scsp4 _copyable" style="margin-top: 30px; margin-bottom: 60px;"><strong class="_4MkjXBK5Ox">거래조건에 관한 정보</strong>
<table class="_1_UiXWHt__"><caption class="kOqCtyOcXE"><span class="blind">거래조건에 관한 정보</span></caption><colgroup><col width="345"><col></colgroup><tbody><tr><th scope="row" class="_1iuv6pLHMD">재화등의 배송방법에 관한 정보</th><td colspan="1" class="ABROiEshTD">배송상품 아님</td></tr><tr><th scope="row" class="_1iuv6pLHMD">주문 이후 예상되는 배송기간</th><td colspan="1" class="ABROiEshTD">배송상품 아님</td></tr><tr><th scope="row" class="_1iuv6pLHMD">제품하자·오배송 등에 따른 청약철회 등의 경우 청약철회 등을 할 수 있는 기간 및 통신판매업자가 부담하는 반품비용 등에 관한 정보</th><td colspan="1" class="ABROiEshTD">상품상세 참조</td></tr><tr><th scope="row" class="_1iuv6pLHMD">제품하자가 아닌 소비자의 단순변심, 착오구매에 따른 청약철회 시 소비자가 부담하는 반품비용 등에 관한 정보</th><td colspan="1" class="ABROiEshTD">배송상품 아님</td></tr><tr><th scope="row" class="_1iuv6pLHMD">제품하자가 아닌 소비자의 단순변심, 착오구매에 따른 청약철회가 불가능한 경우 그 구체적 사유와 근거</th><td colspan="1" class="ABROiEshTD">상품상세 참조</td></tr><tr><th scope="row" class="_1iuv6pLHMD">재화등의 교환·반품·보증 조건 및 품질보증기준</th><td colspan="1" class="ABROiEshTD">상품상세 참조</td></tr><tr><th scope="row" class="_1iuv6pLHMD">재화등의 A/S 관련 전화번호</th><td colspan="1" class="ABROiEshTD"></td></tr><tr><th scope="row" class="_1iuv6pLHMD">대금을 환불받기 위한 방법과 환불이 지연될 경우 지연에 따른 배상금을 지급받을 수 있다는 사실 및 배상금 지급의 구체적 조건 및 절차</th><td colspan="1" class="ABROiEshTD">주문취소 및 대금의 환불은 네이버 페이 마이페이지에서 신청할 수 있으며, 전자상거래 등에서의 소비자보호에 관한 법률에 따라 소비자의 청약철회 후 판매자가 재화 등을 반환 받은 날로부터 3영업일 이내에 지급받은 대금의 환급을 정당한 사유 없이 지연하는 때에는 소비자는 지연기간에 대해서 연 15%의 지연배상금을 판매자에게 청구할 수 있습니다.</td></tr><tr><th scope="row" class="_1iuv6pLHMD">소비자피해보상의 처리, 재화등에 대한 불만 처리 및 소비자와 사업자 사이의 분쟁처리에 관한 사항</th><td colspan="1" class="ABROiEshTD">상품상세 참조</td></tr><tr><th scope="row" class="_1iuv6pLHMD">거래에 관한 약관의 내용 또는 확인할 수 있는 방법</th><td colspan="1" class="ABROiEshTD">상품상세 페이지 및 페이지 하단의 이용약관 링크를 통해 확인할 수 있습니다.</td></tr></tbody></table></div></div></div></div>
<!--//! babylife 리뷰 파트 -->
<div id="REVIEW"><div class="_1ukF-rkoyr" style="margin-top: 100px;"><div class="_2gK-Ama9sJ">
<script></script>
<script></script>
<script type="application/javascript" data-savepage-src="https://static-resource-smartstore.pstatic.net/smartstore/p/static/20220105191207/js/main.a4da60d4.js"></script>
<script data-savepage-src="https://ssl.pstatic.net/static.gn/templates/gnb_utf8.nhn?2022011216"></script>
<script data-savepage-src="https://ssl.pstatic.net/spi/js/release/ko_KR/splugin.js?20220112"></script>
<script data-savepage-src="https://editor-static.pstatic.net/v/basic/1.24.0/se.viewer.js?v=20220105191207"></script>
</body>
</html>
{% endblock %}
*js 코드는 위 소스코드를 활용해서 만들었던 코드를 못찾아서 다른 온라인채널 작업했던 소스코드를 가져 왔다.
import { coupang_data } from "./dummy_data";
const representative = document.getElementById("coupang_representative_img"); // 대표이미지
const sideTitle = document.getElementById("coupang_title"); // 상품제목
const sideAdress = document.getElementById("coupang_adress"); // 주소지
const sideDate = document.getElementById("coupang_side_date"); // 사용기간
const sidePrice = document.getElementById("coupang_price"); // 가격
const sidePriceStandard = document.getElementById("coupang_price_standard"); // 가격기준
const sidePromotion = document.getElementById("coupang_promotion"); //이 상품 예약시 혜택
const sidedDescription = document.getElementById("coupang_description"); // 바로사용, 티켓타입, 사용방법, 예약필요, 취소가능
const sideIntroduce = document.getElementById("coupang_introduce"); // 소개글
const sideNotice = document.getElementById("coupang_side_notice");// 알려드리는 말
const date = document.getElementById("coupang_date");// 상단 날짜 (검색 변경)
const productTitle = document.getElementById("coupang_product_title1");// 상품명 ( 상단 선택박스)
const productTitle2 = document.getElementById("coupang_product_title2");// 상품명 ( 상단 선택박스)
const productTitleClass = document.getElementsByClassName("ticket-summary-name");
const productTitleClass2 = document.getElementsByClassName("ticket-summary-name2");
const productPrice1 = document.getElementById("coupang_product_price1"); // 가격 (상단 선택박스)
const productPrice2 = document.getElementById("coupang_product_price2"); // 가격 (상단 선택박스)
const productDate = document.getElementById("coupang_product_date");
const productAddInfo = document.getElementById("coupang_product_addinfo"); // 추가정보 (상단 선택박스)
const productInfo = document.getElementById("coupang_product_info");
// const mainImage = document.getElementById("coupang_main_img"); // 상세페이지 메인사진
const includInfo = document.getElementById("coupang_includ");// 포함사항(사용방법)
const notIncludInfo = document.getElementById("coupang_notincluded");// 불포함사항(사용방법)
const notice = document.getElementById("coupang_notice");//유의사항(사용방법)
const companyInfo = document.getElementById("coupang_company_info"); // 예약안내 (사용방법)
const cancelInfo = document.getElementById("coupang_cancel_info");// 취소수수료안내 (취소환불규정)
const cancelNotice = document.getElementById("coupang_cancel_notice");// 취소 유의사항(취소환불규정)
document.addEventListener("DOMContentLoaded", () => {
fieldDateHandle();
createProductSelect();
});
const fieldDateHandle = () => {
for (const i of coupang_data) {
// console.log(i);
if (i.title === "coupang_representative_img") {
representative.src = i.contents;
}
if (i.title === "coupang_title") {
sideTitle.innerHTML = i.contents;
}
if (i.title === "coupang_adress") {
sideAdress.innerHTML = i.contents;
}
if (i.title === "coupang_side_date") {
sideDate.innerHTML = i.contents;
}
if (i.title === "coupang_price") {
sidePrice.innerHTML = i.contents;
}
if (i.title === "coupang_price_standard") {
sidePriceStandard.innerHTML = i.contents;
}
if (i.title === "coupang_promotion") {
sidePromotion.innerHTML = i.contents;
}
if (i.title === "coupang_description") {
sidedDescription.innerHTML = i.contents;
}
if (i.title === "coupang_introduce") {
sideIntroduce.innerHTML = i.contents;
}
if (i.title === "coupang_side_notice") {
sideNotice.innerHTML = i.contents;
}
if (i.title === "coupang_date") {
date.innerHTML = i.contents;
}
if (i.title === "coupang_product_title1") {
productTitle.innerHTML = i.contents;
}
if (i.title === "coupang_product_price1") {
productPrice1.innerHTML = i.contents;
}
if (i.title === "coupang_product_price2") {
productPrice2.innerHTML = i.contents;
}
if (i.title === "coupang_product_date") {
productDate.innerHTML = i.contents;
}
if (i.title === "coupang_product_info") {
productInfo.innerHTML = i.contents;
}
if (i.title === "coupang_product_addinfo") {
productAddInfo.innerHTML = i.contents;
}
if (i.title === "coupang_includ") {
includInfo.innerHTML = i.contents;
}
if (i.title === "coupang_notincluded") {
notIncludInfo.innerHTML = i.contents;
}
if (i.title === "coupang_notice") {
notice.innerHTML = i.contents;
}
if (i.title === "coupang_company_info") {
companyInfo.innerHTML = i.contents;
}
if (i.title === "coupang_cancel_info") {
cancelInfo.innerHTML = i.contents;
}
if (i.title === "coupang_cancel_notice") {
cancelNotice.innerHTML = i.contents;
}
if (i.title === "coupang_main_img") {
const img = document.createElement("img");
img.src = i.contents;
document.getElementById("coupang_main_img").appendChild(img);
}
}
};
const createProductSelect = () => {
for (const i of coupang_data) {
if (i.title === "coupang_product_title") {
const tBodyTag = document.getElementById("coupang_tbody");
const trTag = document.createElement("TR");
// .className = " ticket-vendor-item";
const tdTag = document.createElement("TD");
// .className = "travel-item-name"
const divTag = document.createElement("DIV");
// .className = "ticket-summary"
const pTag = document.createElement("P");
// .className = "ticket-summary-header"
const spanTag = document.createElement("SPAN");
// .className = "ticket-summary-name"
tBodyTag.appendChild(trTag).setAttribute("class", "ticket-vendor-item");
trTag.appendChild(tdTag).setAttribute("class", "travel-item-name");
tdTag.appendChild(divTag).setAttribute("class", "ticket-summary");
divTag.appendChild(pTag).setAttribute("class", "ticket-summary-header");
pTag.appendChild(spanTag).setAttribute("class", "ticket-summary-name");
// ticket - summary - name;
productTitleClass[0].innerHTML = i.contents;
}
if (i.title === "coupang_product_price2") {
productPrice2.innerHTML = i.contents;
}
if (i.title === "coupang_product_title2") {
productTitle2.innerHTML = i.contents;
}
}
};
코드는 dummy_data라는 파일에서 coupang_data 개체를 가져온다.
getElementById 메소드를 사용하여 웹 페이지의 다양한 요소를 변수에 할당하고.
HTML 문서가 완전히 로드되면 fieldDateHandle 및 createProductSelect 기능을 실행하는 DOMContentLoaded 이벤트 리스너가 추가.
fieldDateHandle 함수는 coupang_data 배열을 반복하고 각 항목의 title 속성을 기반으로 다른 요소의 값을 설정.
루프 내에서 title 속성을 확인하고 innerHTML을 사용하여 해당 요소에 해당 값을 할당한다.
img 요소가 생성되어 id가 "coupang_main_img"인 요소에 추가되는 조건 추가.
createProductSelect 함수도 coupang_data 배열을 반복하고 title 속성을 기반으로 요소의 값을 설정.
HTML 요소(tr, td, div, p, span)를 동적으로 생성하고 해당 속성과 내부 HTML을 설정하여 상품 선택 상자를 생성.
생성된 요소는 DOM의 관련 상위 요소에 추가.
sideTitle.innerHTML = i.contents; 이 부분을 보면,
위쪽에 정해둔게 sideTitle = document.getElementById('coupang_title');니까
document.getElementById('coupang_title').innerHTML = i.contents로 변경이 가능하지 않나?
그런데, i.title이 사실 'coupang_title'이니까 document.getElementById(i.title).innerHTML = i.contents가 되는 거죠.
이게 모든 부분에서 공통이기 때문에 결국 100줄 넘는 코드는
coupang_data.forEach((i) => {
document.getElementById(i.title).innerHTML = i.contents;
});
*3줄로 줄??? 근데 url과 contents 의 예외 처리가 조금 필요할 것 같긴하다.
이제 더미데이터를 받아서 프론트에서 볼 수 있게 하는 API를 !
from flask import request, Blueprint, current_app
from flask_login import login_required
from wtforms import ValidationError
from AX.controllers.channel import ChannelNotFound, ChannelController, ChannelLanguageController
from AX.controllers.product_channel_language import ProductChannelLanguageController
from AX.db import db
from AX.finders.channel import ChannelFinder, ChannelLanguageFinder
from AX.finders.common import CommonTypeFinder
from AX.finders.misc import SupportLanguageFinder
from AX.finders.product_category import ProductCategoryFinder
from AX.schemas.channel import full_channel_schema, channel_management_schema, \
full_channel_language_with_channel_group_schema, SimpleChannelLanguageSchema
from AX.schemas.misc import support_language_schema
from AX.schemas.product_category import simple_product_category_schema
from AX.schemas.util import PageInfo
from AX.utils.response import SuccessAXResponse, ErrorAXResponse
bp = Blueprint("channel", __name__, url_prefix="/channel")
@bp.errorhandler(ValidationError)
@bp.errorhandler(ChannelNotFound)
def error_handler(error):
return ErrorAXResponse(title=str(error), data={}).jsonify()
@login_required
def clone_naver():
"""
클론 페이지 : 네이버
HTTP/1.1 Get
:return:
HTTP/1.1 200 HTML
"""
return render_template("channel/clone_page/naver.jinja2")
@bp.route('/clone_naver', methods=['GET'])
# @login_required
def clone_naver():
"""
Get naver
HTTP/1.1 GET
:params:
:return:
HTTP/1.1 200 JSON
"""
return SuccessAXResponse(
title="Get naver",
data=[
{
"title": "naver_logo",
"contents": "https://shop-phinf.pstatic.net/20210913_107/1631523902315pY7vA_PNG/%C7%D6%C7%C3%B9%F6%BD%BA-BI-%B1%B9%B9%AE-PC90x234.png?type=w345",
},
{
"title": "naver_representative_img",
"contents": "https://res.klook.com/image/upload/activities/t5jgj20rdibzrjeptw5r.jpg",
},
{
"title": "naver_input_first",
"contents": "투어 이용날짜 작성",
},
{
"title": "naver_input_second",
"contents": "투어 코스 선택하기",
},
{
"title": "naver_product_name",
"contents": "우붓 클래식 프라이빗 투어",
},
{
"title": "naver_price",
"contents": "17,100",
},
{
"title": "naver_price_second",
"contents": "17,100",
},
{
"title": "naver_as_info",
"contents": " 023740333 - 예약 후 출발이 확정되면 예약확정 문자를 발송해 드립니다. (최소 3일전까지 출발여부 통보)- 투어 전일 18:00 시 이후 예약건은 톡톡or카카오플러스톡(id:핫플트립)에서 확정여부 확인부탁드립니다.- 이용 당일 미팅 장소에서 구매내역 확인 후 투어 출발합니다.- 각 미팅 장소를 확인한 후 미팅 10분 전까지 꼭 도착 바랍니다.- 지정한 날짜와 코스만 이용할 수 있습니다.- 코스별 시즌 종료 후에는 대체 코스로 운영됩니다.- 이용당일 현장상황에 따라 운영시간, 코스 등이 변동될 수 있습니다.- 기상악화, 천재지변 등의 현지 사정으로 인해 투어가 취소될 수 있습니다.- 최소 출발인원 : 10인- 최소 출발인원 수의 미달로 투어가 취소될 경우, 개별적으로 연락을 드리며 전액 환불됩니다.",
},
{
"title": "naver_service_name",
"contents": "주식회사 엠티엠비코리아",
},
{
"title": "naver_service_number",
"contents": "023740333",
},
{
"title": "naver_as_number",
"contents": "023740333",
},
{
"title": "naver_brend_name",
"contents": "핫플트립",
},
{
"title": "naver_discount",
"contents": "44%",
},
{
"title": "naver_review_count",
"contents": "14",
},
{
"title": "naver_full_price",
"contents": "50,000",
},
{
"title": "naver_manufacturer",
"contents": "주식회사 엠티엠비코리아 / 자회사 (주)엔이에스티제주투어",
},
{
"title": "naver_brend_name2",
"contents": "핫플트립(자체제작 상품)",
},
{
"title": "naver_model_name",
"contents": "제주핫플버스",
},
{
"title": "naver_event",
"contents": "매일터지는 복권이벤트, 후기이벤트(특2급호텔숙박권외 1/2/3등)",
},
{
"title": "naver_gifts",
"contents": "제주오메기떡&제주삼다수 / 제주프레임 감성포토카드 증정",
},
{
"title": "naver_review_count2",
"contents": "14",
},
{
"title": "naver_qa_count",
"contents": "37",
},
{
"title": "naver_tags",
"contents": [
"#혼자놀기",
"#우정선물",
"#자유여행",
"#낭만여행",
"#효도상품",
"#추억사진",
"#맛집",
"#해변모래놀이",
"#조이풀라이프",
"#추억만들기",
],
},
{
"title": "naver_main_imag_container",
"contents": [
{
"type": "image",
"url": "https://res.klook.com/image/upload/activities/t5jgj20rdibzrjeptw5r.jpg"
},
{
"type": "image",
"url": "https://res.klook.com/image/upload/activities/lq2zjipd8dl0czvjgyt2.jpg"
},
{
"type": "image",
"url": "https://res.klook.com/image/upload/activities/k9xorryjwk1i4vcl4ubg.jpg"
},
{
"type": "image",
"url": "https://res.klook.com/image/upload/activities/sptaiy5mxyvvj2tibg49.jpg"
},
{
"type": "image",
"url": "https://res.klook.com/image/upload/activities/c28axc6ie2uotdreu9d0.jpg"
},
{
"type": "image",
"url": "https://res.klook.com/image/upload/activities/jdoyeavh0nzmkbmlsqo5.jpg"
},
{
"type": "image",
"url": "https://res.klook.com/image/upload/activities/kessckbu9izz49o5jqon.jpg"
}
],
},
]
).jsonify()
@bp.route('/clone_naver_mobile', methods=['GET'])
# @login_required
def clone_naver_mobile():
"""
Get naver_mobile
HTTP/1.1 GET
:params:
:return:
HTTP/1.1 200 JSON
"""
return SuccessAXResponse(
title="Get naver_mobile",
data=[
{
"title": "naver_logo",
"contents": "https://shop-phinf.pstatic.net/20210913_107/1631523902315pY7vA_PNG/%C7%D6%C7%C3%B9%F6%BD%BA-BI-%B1%B9%B9%AE-PC90x234.png?type=w345",
},
{
"title": "naver_representative_img",
"contents": "https://shop-phinf.pstatic.net/20211201_225/1638355877976v3cPB_PNG/39491705584668702_9653693.png?type=m510",
},
{
"title": "naver_input_first",
"contents": "투어 이용날짜 작성",
},
{
"title": "naver_input_second",
"contents": "투어 코스 선택하기",
},
{
"title": "naver_product_name",
"contents": "경주 시티투어 뚜벅이 버스투어 혼자 일일 원데이 당일 패키지 커플여행 야경투어 택시관광",
},
{
"title": "naver_price",
"contents": "28,000",
},
{
"title": "naver_price_second",
"contents": "28,000",
},
{
"title": "naver_as_info",
"contents": " 023740333 - 예약 후 출발이 확정되면 예약확정 문자를 발송해 드립니다. (최소 3일전까지 출발여부 통보)- 투어 전일 18:00 시 이후 예약건은 톡톡or카카오플러스톡(id:핫플트립)에서 확정여부 확인부탁드립니다.- 이용 당일 미팅 장소에서 구매내역 확인 후 투어 출발합니다.- 각 미팅 장소를 확인한 후 미팅 10분 전까지 꼭 도착 바랍니다.- 지정한 날짜와 코스만 이용할 수 있습니다.- 코스별 시즌 종료 후에는 대체 코스로 운영됩니다.- 이용당일 현장상황에 따라 운영시간, 코스 등이 변동될 수 있습니다.- 기상악화, 천재지변 등의 현지 사정으로 인해 투어가 취소될 수 있습니다.- 최소 출발인원 : 10인- 최소 출발인원 수의 미달로 투어가 취소될 경우, 개별적으로 연락을 드리며 전액 환불됩니다.",
},
{
"title": "naver_service_name",
"contents": "주식회사 엠티엠비코리아",
},
{
"title": "naver_service_number",
"contents": "023740333",
},
{
"title": "naver_as_number",
"contents": "023740333",
},
{
"title": "naver_brend_name",
"contents": "핫플트립",
},
{
"title": "naver_discount",
"contents": "44%",
},
{
"title": "naver_review_count",
"contents": "14",
},
{
"title": "naver_full_price",
"contents": "50,000",
},
{
"title": "naver_manufacturer",
"contents": "주식회사 엠티엠비코리아 / 자회사 (주)엔이에스티제주투어",
},
{
"title": "naver_brend_name2",
"contents": "핫플트립(자체제작 상품)",
},
{
"title": "naver_model_name",
"contents": "제주핫플버스",
},
{
"title": "naver_event",
"contents": "매일터지는 복권이벤트, 후기이벤트(특2급호텔숙박권외 1/2/3등)",
},
{
"title": "naver_gifts",
"contents": "제주오메기떡&제주삼다수 / 제주프레임 감성포토카드 증정",
},
{
"title": "naver_review_count2",
"contents": "14",
},
{
"title": "naver_qa_count",
"contents": "37",
},
{
"title": "naver_tags",
"contents": [
"#혼자놀기",
"#우정선물",
"#자유여행",
"#낭만여행",
"#효도상품",
"#추억사진",
"#맛집",
"#해변모래놀이",
"#조이풀라이프",
"#추억만들기",
],
},
{
"title": "naver_main_imag_container",
"contents": [
"https://shop-phinf.pstatic.net/20210913_203/1631524032216suPCh_JPEG/%ED%95%AB%ED%94%8C%EB%B2%84%EC%8A%A4-BI-%EC%B5%9C%EC%A2%85_%EA%B5%AD%EB%AC%B8%EB%B0%B0%EA%B2%BD.jpg",
"https://shop-phinf.pstatic.net/20211202_156/16384397946730Iiuv_PNG/%EA%B2%BD%EC%A3%BC%ED%95%AB%ED%94%8C%EB%B2%84%EC%8A%A4-%EC%8D%B8%EB%84%A4%EC%9D%BCv22.png?type=w860",
"https://shop-phinf.pstatic.net/20211202_216/1638439856832XT6nx_JPEG/%EA%B2%BD%EC%A3%BC%ED%95%AB%ED%94%8C_%EC%8B%9C%EA%B7%B8%EB%8B%88%EC%B3%90_2.jpg?type=w860",
"https://shop-phinf.pstatic.net/20211202_203/1638439922582sslTM_JPEG/%EC%98%AC%EB%8D%B0%EC%9D%B4%EC%9D%BC%EC%A0%95.jpg?type=w860",
"https://shop-phinf.pstatic.net/20211202_90/16384401295009vEFW_JPEG/%EC%A3%BC%EC%83%81%EB%82%AE%EB%B0%A4.jpg?type=w860",
],
},
]
).jsonify()
코드는 Flask, Flask-Login 등 필요한 종속성을 가져온다.
"channel"이라는 Flask 블루프린트를 "/channel" URL 접두사와 함께 정의.
@bp.errorhandler 데코레이터를 사용하여 두 가지 에러 핸들러를 정의합니다: ValidationError과
ChannelNotFound. 이러한 예외가 발생할 때 에러 응답을 JSON 형식으로 반환한다.
clone_naver 함수는 "/clone_naver" 경로의 라우트 핸들러.
"channel/clone_page/naver.jinja2"라는 HTML 템플릿을 반환.
clone_naver 함수는 GET 메서드와 함께 "/clone_naver" 경로의 라우트 핸들러로 정의.
"naver" 객체와 관련된 데이터를 포함하는 JSON 응답을 반환.
마찬가지로, clone_naver_mobile 함수는 GET 메서드와 함께 "/clone_naver_mobile" 경로의 라우트 핸들러로 정의됩니다. "naver_mobile" 객체와 관련된 데이터를 포함하는 JSON 응답을 반환합니다.
해당 코드는 Naver와 Naver Mobile 클론과 관련된 다른 경로를 처리하며, 경로와 요청 메서드에 따라 HTML 또는 JSON 응답을 반환합니다.

지금 와서 생각해보니 무척이나 재미난 경험이었다. 물론 대단한 것을 개발한 것은 아니다. 하지만, 당시에 일을 해내기 위해서 학습하고, 빠르게 결과를 만들기 위해서 동원했던 아이디어, 파이썬에 파도 몰랐던 내가 2주만에 목표한 바를 이룰수 있었던 당시에 0년차 나에게 격려를 보내주고 싶다. 할수있을까 싶은 것을 했을때 얻은 기쁨이란.. 위 경험을 기반으로 풀스택으로 한번 더 개발을 했었고 역시 두번했을때는 조금 더 난이도 있는 코드를 만들 수 있었다. 역시 노력은 배신하지 않는다 ㅎㅎㅎ
물론 지금은 프론트엔드 업무에 집중하고 있다. 하지만 저 당시에 배움으로 백엔드에 대한 이해와 DB에 대한 이해가 있었기에 지금 업무를 진행하는데 많은 이해를 바탕으로 일을 진행하고 팀원들과 소통할 수 있어서 너무 감사한 일이지 않나 싶다. 당시에는 나에게 왜 이런 시련을...주나 싶었지만 말이다.
이래서 내가 개발자가 좋다. 내가 배운 것을 활용허고 발전시킬 수 있기 때문이다. 지금도 갈길이 멀지만 0년차 시절을 생각하며 배움을 게을리 하지 말아야 겠다 다시금 다짐하게 된다.