HTML
태그를 적절하게 사용하여 페이지 레이아웃을 스스로 구현할 수 있다.CSS
기초 개념을 활용하여 원하는 디자인을 요소에 적용할 수 있다. input
태그 활용법에 대해 익힌다.JavaScript
로 여러 기능을 구현하여 DOM
의 요소를 조작할 수 있다.git flow
를 이해하고 PR을 작성하여 github
을 통한 코드 리뷰 방식을 이해한다.그 동안 배운 HTML
, CSS
의 학습내용을 모두 이용해서 Starbucks 홈페이지와 유사한 웹페이지를 만들고, JavaScript
을 구현하여 기능들을 구현하는 프로젝트였으며, 드디어 공부한 내용을 활용하여 프로젝트를 할 수 있다는 생각에 신나기까지 했다. 프론트엔드에서 HTML
,CSS
,JavaScript
는 초반부이며 전반적인 내용이지만, 프로젝트를 진행하면서 내가 부족한 부분이나 미숙한 부분을 점검하면서 더 성장할 기회를 준 시간이었던 것 같다. 이 글을 작성하는 시점은 모든 프로젝트의 내용 구현을 마친 후에 내 자신을 돌아보기 위한 회고록이자 프로젝트에 모든 내용과 나 자신을 되돌아 보기 위한 피드백이기도 하다.
JavaScript
를 통해 좋아요(하트) 버튼과 '엔터를 통한 댓글 입력' 기능을 구현하는 단계이다. 그 동안 배운 JavaScript 학습 내용을 점검하면서 활용할 수 있는 본격적인 단계이며, JavaScript의 부족한 점을 돌아볼 수 있는 단계였다. 리뷰 댓글 삭제와 리뷰별 좋아요 버튼 기능은 다음 단계의 내용이지만, 모두 구현한 상태기도 하며 나 역시 구현할 때 포괄적으로 구현하였기 때문에 함께 수행하였으며 코드에도 적용이 되있다.<HTML>
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>list</title>
<link href="styles/detail.css" rel="stylesheet" type="text/css" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css"
integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css2?family=Dancing+Script&display=swap" rel="stylesheet">
</head>
<body>
<nav> <!--최상단의 배너-->
<div class="menu">
<a href="" class="logo">Webucks</a>
<ul>
<li><a href="" class="menu-list">COFFEE</a></li>
<li><a href="" class="menu-list">MENU</a></li>
<li><a href="" class="menu-list">STORE</a></li>
<li><a href="" class="menu-list">WHAT'S NEW</a></li>
</ul>
</div>
</nav>
<section> <!--중반부의 레이아웃-->
<div class="container" id="one"> <!-- 중반부 전체를 감싸는 div 태그-->
<div class="first"> <!--중반부 를 두개의 div태그로 나누어 왼쪽 절반의 구역으로 나눠줌-->
<p class="coldbrew">콜드 브루</p>
<img src="coffeedetailpage.PNG" alt="콜드브루">
</div>
<div class="second"> <!--중반부 를 두개의 div태그로 나누어 오른쪾 절반의 구역으로 나눠줌-->
<br>
<p class="gray">홈 > MENU > 음료 > 에스프레소 > 화이트 초콜릿 모카</p>
<div id="fifth">
<div class="emojiright">
<p class="coffeename">화이트 초콜릿 모카</p>
<p class="coffeename2">White Chocolate Mocha</p>
</div>
<div id="heart2">
<a href="#"><i class="far fa-heart" id="heart3"></i></a>
</div>
</div>
<p class="seconddetail">달콤하고 부드러운 화이트 초콜릿 시럽과 에스프레소를 스팀 밀크와 섞어
휘핑크림으로 마무리한 음료로 달콤함과 강렬한 에스프레소가 부드럽게 어우러진 커피</p>
<div class="productdetail">
<span>제품 영양 정보</span>
<span>Tall(톨) / 355ml (12 fl oz)</span>
</div>
<div class="productdetail2"> <!--영양정보를 담아주는 div 태그-->
<div class="boxone"> <!--영양 정보를 좌우로 반반 나눠주었으며, 왼쪽에 해당하는 div 태그-->
<ul>
<li>
<span class="l">1회 지공량(kcal)</span>
<span>345</span class="r">
</li>
<li>
<span class="l">포화지방 (g)</span>
<span>11</span class="r">
</li>
<li>
<span class="l">단백질 (g)</span>
<span>11</span class="r">
</li>
</ul>
</div>
<div class="boxtwo"> <!--영양 정보를 좌우로 반반 나눠주었으며, 오른쪽에 해당하는 div 태그-->
<ul>
<ul>
<li>
<span class="l">나트륨(mg))</span>
<span>150</span class="r">
</li>
<li>
<span class="l">당류 (g)</span>
<span>35</span class="r">
</li>
<li>
<span class="l">카페인 (mg)</span>
<span>75</span class="r">
</li>
</ul>
</div>
</div>
<div class="allegy">알레르기 유발 요인 : 우유</div>
<p class="reviewnav">리뷰</p>
<div class="Allcomment"> <!--모든 댓글 내용을 담아내는 div 태그-->
<div class="comment"> <!-- comment class는 각각 하나의 댓글을 담아냄 -->
<span class="id">coffee_lover</span>
<span class="ment">너무 맛있어요!</span>
<button class="deletebutton">삭제</button>
<a href="#" class="commentheart"><i class="far fa-heart"></i></a>
</div>
<div class="comment">
<span class="id">CHOCO7</span>
<span class="ment">오늘도 화이트 초콜릿 모카를 마시러 갑니다</span>
<button class="deletebutton">삭제</button>
<a href="#" class="commentheart"><i class="far fa-heart hearts"></i></a>
</div>
<div class="comment">
<span class="id">legend_dev</span>
<span class="ment">진짜 화이트 초콜릿 모카는 전설이다.
진짜 화이트 초콜릿 모카는 전설이다.
진짜 화이트 초콜릿 모카는 전설이다.
</span>
<button class="deletebutton">삭제</button>
<a href="#" class="commentheart"><i class="far fa-heart"></i></a>
</div>
</div>
<input text="" placeholder="리뷰를 입력해주세요" class="reviewcomment"
onkeyup="if(window.event.keyCode==13){test()}"> <!--후반부에 구현할 댓글 입력을 위한 input 태그-->
</section>
<footer> <!-- 최하단부의 배너를 담는 fotter 태그 -->
<div class="bottomzone">
<div>
<p>COMPANY</p>
<ul>
<li>한눈에 보기</li>
<li>스타벅스 사명</li>
<li>스타벅스 소개</li>
<li>국내 뉴스룸</li>
<li>세계의 스타벅스</li>
<li>글로벌 뉴스룸</li>
</ul>
</div>
<div>
<p>CORPORATE SALES</p>
<ul>
<li>단체 및 기업 구매 안내</li>
</ul>
</div>
<div>
<p>PARTNERSHIP</p>
<ul>
<li>신규 입점 제의</li>
<li>협력 고객사 등록 신청</li>
</ul>
</div>
<div>
<p>ONLINE COMMUNITY</p>
<ul>
<li>페이스북</li>
<li>트위터</li>
<li>유튜브</li>
<li>블로그</li>
<li>인스타그램</li>
</ul>
</div>
<div>
<p>RECRUIT</p>
<ul>
<li>채용 소개</li>
<li>채용 지원하기</li>
</ul>
</div>
<div>
<p>WEBUCKS</p>
</div>
</div>
</footer>
</body>
<script src="js/detail.js">
</script> <!--후반부의 기능들을 구현하기 위한 js 코드-->
</html>
<JavaScript>
const heart = document.getElementById("heart3"); //오른쪽 상단의 하트 버튼 기능 구현
function hearts() {
if (heart.style.fontWeight != "bold") {
heart.style.fontWeight = "bold";
}
else {
heart.style.fontWeight = "normal";
}
}
heart.addEventListener("click", hearts);
//원래 있던 세개의 댓글 내에 하트 기능 추가.
let commentHeart = document.getElementsByClassName("commentheart");
for (let i = 0; i < commentHeart.length; i++) {
commentHeart[i].addEventListener("click", () => {
if (commentHeart[i].innerHTML === '<i class="far fa-heart"></i>') {
commentHeart[i].innerHTML = '<i class="fas fa-heart"></i>';
} // 조건에 따라 하트 아이콘(각각 내부가 채워진 아이콘과 내부가 비워진 하트 아이콘) innerHTML로 지정
else {
commentHeart[i].innerHTML = '<i class="far fa-heart"></i>';
}
});
}
let deleteButton = document.getElementsByClassName("deletebutton");
let deleteComment = document.getElementsByClassName("comment");
for (let i=0; i<deleteButton.length; i++)
{
deleteButton[i].addEventListener("click",()=>{
items.removeChild(deleteComment[i]);
});
} // 원래 존재하던 3개의 댓글 삭제창 구현
let input = document.getElementsByClassName("reviewcomment")[0]; //인풋 창을 칭하는 div 태그
let items = document.getElementsByClassName("Allcomment")[0]; //전체 댓글을 포괄하는 div tag
const onAdd = () => { //엔터시에 추가되는 댓글 기능 구현
const text = input.value;
if (input.value === '') {
input.focus();
return;
}
const comment = document.createElement("div"); //한 개의 댓글 (아이디와 멘트 포함)
comment.setAttribute('class', 'comment');
const spanMent = document.createElement('span'); // 댓글의 멘트
spanMent.setAttribute("class", 'ment');
spanMent.innerHTML = text;
const spanID = document.createElement('span'); //댓글 작성자의 아이디
spanID.setAttribute('class', 'id');
spanID.innerHTML = "G-DRAGON";
const itemDel = document.createElement('button'); // 삭제 버튼과 그 기능
itemDel.setAttribute("class", "deletebutton");
itemDel.innerHTML = "삭제";
itemDel.addEventListener('click', () => {
items.removeChild(comment);
});
const itemHeart = document.createElement("a"); //만들어지는 댓글의 하트 버튼과 그 기능
itemHeart.setAttribute("href","#");
itemHeart.setAttribute("class","commentheart");
itemHeart.innerHTML='<i class="far fa-heart"></i>';
itemHeart.addEventListener("click",()=> {
if (itemHeart.innerHTML === '<i class="far fa-heart"></i>') {
itemHeart.innerHTML = '<i class="fas fa-heart"></i>';
}
else {
itemHeart.innerHTML = '<i class="far fa-heart"></i>';
}
});
comment.appendChild(spanID);
comment.appendChild(spanMent);
comment.appendChild(itemDel);
comment.appendChild(itemHeart); //아이디와 멘트, 삭제 버튼, 하트 버튼을 comment div 태그 내에 추가해준 후
items.appendChild(comment); // 그 comment를 items(전체 댓글을 감싸는 div태그 내에 추가해주어 맨 아래에 댓글이 추가되도록 해줌)
input.value = ''; // 댓글 입력창을 비워줌
input.focus(); // 댓글 입력창에 포커스를 넣어줌
};
input.addEventListener('keypress', (event) => { // 댓글 input 창에 enter 키가 눌러졌을 때, onAdd()기능 실현해줌
if (event.key === 'Enter') {
onAdd();
}
return;
});
JavaScript
를 본격적으로 처음 활용한 프로젝트였다. 분명 머릿속에는 "이렇게 구현해서 이렇게 적용하면 되겠군!" 이라는 생각을 가지고, 코딩을 시작해보았지만, "근데 그 구현을 어떤 함수를 사용하는 거지..?" 하며 발 동동 구르고 있는 나 자신을 확인하고 있었다. 내가 모르는 함수와 메소드들도 분명 있었겠지만, 내 학습량과 공부 방법이 어느 정도는 문제가 있었다고 생각한다. 곧바로 JavaScript
레플릿 문제들을 하나하나 다시 복습하고 또 복습하였다.
이 단계에서 주된 피드백은 .getElementById
, getElementsByClassName
등의 개념이었다. 전자는 단일적인 id
를 불러오기 때문에 하나의 객체를 가지며, 후자는 class
네임을 가지는 다수의 배열을 담는 객체를 가지기 때문에 []를 통해 index를 부여해주어야 하며, 이를 템플릿으로 찍어주는 과정을 for문을 통해 간결하게 수행하여 적용할수 있다는 게 매우 큰 장점이며 나에게 큰 배움을 주었다.
또한 .innerHTML
을 통해 태그 내 내용을 모두 바꿔줌을 통해 하트 아이콘을 상황에 따라 변경해줄 수 있다는 것 역시 매우 큰 고찰을 주었다.. 별 거 아닐 수도 있지만 이러한 기능을 무수히 많은 요구에서 이뤄낼 수 있다고 생각 들었고, 나에게 큰 피드백을 주었다.
최종적으로 이 프로젝트에서 내게 가장 큰 배움은 .removeChild()
, createElement()
, setAttribute()
, appendChild()
이 네개의 method
를 배우고 활용하는 법을 알았다는 것이라고 해도 과언이 아닐 것이다.. 그 외에도 중요한 method
들이 많다지만 이번 프로젝트의 가장 큰 공신이었으며, 가장 큰 배움을 준 method들이었고 나를 더 앞으로 나아갈 수 있게 해준 method
들이었다.
특히 .setAttribute()
는 내 막혔던 프로젝트를 매우 시원하게 뚫어주었고, 프로젝트의 진행 속도를 한결 빠르게 해주었다. 기능은 attribute와 그의 value를 두개의 인자로 받아 지정해줄 수 있다는 간단한 기능이지만, 정말 큰 도움을 주었다.
부족한 JavaScript
를 점검하고 또 점검할 수 있었으며, 나를 역시 더 앞으로 나아가게 해주는 프로젝트였으며, 부족한 단점들을 보완해주는 소중한 과정이었다. 정말 부족한 나 자신이지만, 부족한 점을 보완하고 또 보완하며 더 열심히 공부하며 앞으로 나아갈 것이다.
(긴 글 읽어주셔서 감사합니다!)