SPRING 공식 웹 사이트 클론 코딩 완성!
클론코딩 진행하면서 느낀점
Spring 공식 웹사이트와 비교하면 디자인적으로 많이 부족하지만,
필요한 기능들은 70~80% 구현한 것 같다!
내 인생 처음 시도한 클론 코딩이었다.
막혔을 때 볼 수 있는 Spring 클론 코딩 강의가 있었던 것도 아니고, html/css 지식이 거의 없을 때
시작했기 때문에 오로지 나 혼자 부딪히는 경험을 해볼 수 있었다.
물론 F12(개발자 도구)로 많이 따라했지만, html/css 지식이 거의 없었던 나에게는
<div>
/ <a>
이런 간단한 태그들 말고는 모든 것이 새로워서
F12(개발자 도구)가 html/css 서적이었다.
진짜 클론코딩하면서 F12(개발자 도구)와 구글링을 엄청!! 많이 한 것 같다.
크롬의 탭들이 엄청 작아질 정도로 많은 탭에 구글 검색 창이 켜져있었다.
완성해놓고 나니 정말 뿌듯했다.
그래서 이 기쁨을 블로그에 기록하려고 한다!
구현한 코드들 / 개선 사항들을 작성할 것이다.
구현한 코드
html / css는 레이아웃, 디자인이기 때문에 기능 구현은 대부분 Javascript로 한 것 같다.
구현한 Javascript 코드를 알아보자!
※ 진짜 기초만 알고 짠 코드라 엄청 더럽게 느껴지긴 하지만 그래도 했다는 것에 의의를 두겠다 ㅎㅎ..
const HIDDEN_CLASSNAME = "hidden";
const CHANGE_COLOR_CLASSNAME = "change_color";
const CHANGE_COLOR_BOLD_CLASSNAME = "change_color_bold";
// Why Spring 메뉴바
const why_Items = document.querySelector("#why-items");
const box_1 = document.querySelector(".box_1");
const why_li = document.querySelectorAll("#why-box li a");
/* toggle로 1개 함수로 처리 가능
function onShowWhy() {
box_1.classList.remove(HIDDEN_CLASSNAME);
}
function onHiddenWhy() {
box_1.classList.add(HIDDEN_CLASSNAME);
}
*/
function ShowHidden_Why() {
box_1.classList.toggle(HIDDEN_CLASSNAME);
}
why_Items.addEventListener("mouseover", ShowHidden_Why);
why_Items.addEventListener("mouseleave", ShowHidden_Why);
box_1.addEventListener("mouseover", ShowHidden_Why);
for (let i = 0; i < why_li.length; i++) {
function ChangeColor_Why() {
why_li[i].classList.toggle(CHANGE_COLOR_CLASSNAME);
}
why_li[i].addEventListener("mouseover", ChangeColor_Why);
why_li[i].addEventListener("mouseleave", ChangeColor_Why);
}
① CSS에서 display : none;
을 class hidden
으로 설정하고 mouseover / mouseleave될 때
toggle
을 통해서 hidden이면 클래스 삭제 / hidden 없으면 클래스 추가를 통해 구현했다.
② CSS에서 color : 초록;
을 class change_color
로 설정하고 ①과 마찬가지로 toggle
을 통해 구현했다.
이때, 클론 코딩 초기였는데 querySelectAll
으로 여러 요소들을 선택하고
for문을 이용하여 여러 요소를 선택하여 반복문을 돌면서
toggle
을 한다는 생각을 했다는 것이 상당히 뿌듯했다.
근데 지금 생각해보니, 단순 글자색 변경은 CSS의 State인 :hover
로 구현할 수 있을 것 같다....
하지만 이때의 나는 CSS의 State의 S도 몰랐으니 그냥 넘어가자 ㅎㅎ...
그땐 for문 돌리고 엄청 뿌듯했는데 ㅋㅋㅋㅋ핳...
// Day, Night 버튼
const Day_Night_Btn = document.querySelector("#day_night_mode");
const body = document.querySelector("body");
const bottom_arrow = document.querySelectorAll(".bottom_arrow");
const nav = document.querySelector("#nav");
const top_banner_Btn = document.querySelectorAll(".top_banner_button");
const news_box = document.querySelector(".news_box");
const top_backcolor = document.querySelectorAll(".top_backcolor");
const hr_light = document.querySelectorAll(".hr_light");
const box_select = document.querySelectorAll(".box_select");
function onClickChangeMode() {
if (body.classList.contains("day")) {
// dark모드로 변할 때 적용할 것들
// 화살표에 반복문 돌면서 mode 적용
for (let i = 0; i < bottom_arrow.length; i++) {
bottom_arrow[i].style.borderColor = "white";
}
for (let i = 0; i < top_banner_Btn.length; i++) {
top_banner_Btn[i].style.borderColor = "white";
}
for (let i = 0; i < hr_light.length; i++) {
hr_light[i].classList.replace("hr_light", "hr_dark");
}
for (let i = 0; i < box_select.length; i++) {
box_select[i].classList.toggle("background_color_black");
}
for (let i = 0; i < card.length; i++) {
card[i].style.borderColor = "#2b2f33";
}
for (let i = 0; i < top_backcolor.length; i++) {
top_backcolor[i].style.backgroundColor = "#262a2d";
}
Day_Night_Btn.classList.replace("switch_box_day", "switch_box_night");
body.classList.replace("day", "night");
nav.classList.add("night");
news_box.style.borderColor = "#1b1f23";
} else {
// day 모드로 바뀔 때 적용할 것들
Day_Night_Btn.classList.replace("switch_box_night", "switch_box_day");
body.classList.replace("night", "day");
nav.classList.remove("night");
news_box.style.borderColor = "white";
// 화살표에 반복문 돌면서 mode 적용
for (let i = 0; i < bottom_arrow.length; i++) {
bottom_arrow[i].style.borderColor = "#1b1f23";
}
for (let i = 0; i < top_banner_Btn.length; i++) {
top_banner_Btn[i].style.borderColor = "#1b1f23";
}
for (let i = 0; i < hr_light.length; i++) {
hr_light[i].classList.replace("hr_dark", "hr_light");
}
for (let i = 0; i < box_select.length; i++) {
box_select[i].classList.toggle("background_color_black");
}
for (let i = 0; i < card.length; i++) {
card[i].style.borderColor = "#f2f7f7";
}
for (let i = 0; i < top_backcolor.length; i++) {
top_backcolor[i].style.backgroundColor = "#ebf2f2";
}
}
}
Day_Night_Btn.addEventListener("click", onClickChangeMode);
③ 현재 body
의 class가 day
인지 night
인지에 따라 버튼을 눌렀을 때 다르게 동작하게 했다!
버튼을 click
하면 여러 요소들을 day모드 / night 모드에 맞게 style을 고쳤다.
이 과정에서 toggle
이나 replace
를 사용하여 CSS 클래스를 사용해서 바꾼 것도 있지만
javascript에서 직접 style을 style.borderColor
를 줘서 바꾼 것이 더 많았다.
듣기로, 이렇게 javascript에서 직접 스타일을 바꾸는 것은 안 좋다고 들어서 최대한 CSS class를
제어하는 방향으로 가려고 했는데 borderColor
나 backgroundColor
는 class로 추가, 제거를 해도
잘 제어가 안 돼서 어쩔 수 없이 Javscript로 제어했다.
이 부분이 좀 모르겠다. javascript에서 제어하지 않고 CSS에서 제어하는 방법이 없을까?
처음에 DAY_NIGHT 모드를 어떻게 구현할지 막막했는데 생각보다는 쉬웠던 것 같다.
물론 내 코드가 엄청 더럽지만 구현은 했다..
핵심은 현재 day일때 day_night 버튼을 누르면
1. body의 배경색 검은색
2. body의 글자색 흰색
이렇게만 바꿔줘도 거의 바뀐 것을 볼 수 있었다!
const news_Items = document.querySelectorAll(".news-items");
for (let i = 0; i < news_Items.length; i++) {
function ShowHidden_Underline() {
news_Items[i].classList.toggle("news_underline");
}
news_Items[i].addEventListener("mouseover", ShowHidden_Underline);
news_Items[i].addEventListener("mouseleave", ShowHidden_Underline);
}
④ 간단하게 toggle
을 사용하여 CSS에 underline을 주는 class를 만들어서 구현했다.
이것도 만들고 보니 CSS에서 :hover
를 통해서 충분히 만들 수 있을 것 같다...
ㅠㅠ 그땐 몰랐다,,
const card_h2 = document.querySelectorAll(".card h2");
const card = document.querySelectorAll(".card");
for (let i = 0; i < card.length; i++) {
function card_Mouseover() {
card[i].classList.add("card_shadow");
card_h2[i].classList.add("change_color");
}
function card_Mouseleave() {
card[i].classList.remove("card_shadow");
card_h2[i].classList.remove("change_color");
}
card[i].addEventListener("mouseover", card_Mouseover);
card[i].addEventListener("mouseleave", card_Mouseleave);
}
⑤ CSS에 카드에 그림자와 위치를 조금 위로 옮기는 card_shadow
클래스를 설정해서 add
/ remove
로 구현하였다.
이때, toggle
을 쓰면 mouseleave
를 하지 않았는데 계속 기능이 on/off됐다.
그래서 add
/ remove
로 구현을 했는데 왜 이런지 모르겠다,,
이외의 JS로 구현한 기능들은 위의 기능과 거의 유사해서 이렇게 5가지 정도로 구현한 것 같다!
for문을 이용해서 여러 요소들을 잡고 반복문을 돌면서 변경하는 것이 재밌고 뿌듯했다!
개선사항(진행 중에 업데이트한 것, 남아있는 것 포함)
① 메뉴바 box마다 box id 바꿔가면서 했는데 한 번에 처리하는 방법이 없을까?
② 1. javascript에서 classList.add / classList.remove를 2개 함수를 써서 구현했는데
강의에서 배운 classList.toggle을 사용하면 함수 1개로 구현할 수 있다!
👉 완료
③ javascript에서 문자를 적을때 문자가 반복되면 변수로 선언해서 오타를 입력했을 때
에러를 출력해주도록 하는 것이 좋다!
"hidden"
→ const HIDDEN_CLASSNAME = "hidden"
이렇게 문자를 변수로 지정할 시 변수명은 모두 대문자로 적는 것이 관습이다.
-> 부분 완료
④ classList.add / classList.remove로 mouseover했을 때 색상변화를 줬는데 이미 색상이 있는 경우 add를 해도 기본색상으로 유지가 됐다. 어떻게 바꾸지????
className으로 class를 바꿔버리면 이미 있던 class가 날라가니깐 못 할 것 같은데..
→ classList.replace으로 해결!
⑤ top_banner 부분 글자 시간 지날때마다 바뀌는 것 구현하기
-> 처음 클론코딩할 때 transition
을 몰라서 못했는데 이젠 할 수도 있을 것 같다.
⑥ Storage로 저장해서? 사용자가 다크모드로 지정하고 종료했을 때 다시 새로고침해도 다크모드로 나오게 구현
⑦ footer SUBSCRIBE 버튼 다크모드 구현
⑧ footer 그림 링크? 구현
⑨ 화면 크기 줄어들 때 메뉴바 사라지게 하기
⑩ Day/Night 버튼에 이미지 추가해서 버튼 움직이게 하기
⑪ 카드 Night 모드 시 테두리 색깔 변경하기..
-> card.style.borderColor = ~~
를 해도 바뀌지 않는다.
⑫ <code>
부분 페이지 로드 될때 코드치는 것처럼 나오게 transition
건드리기
이렇게 클론코딩을 하고 나도... 개선사항이 엄청 많다.
그만큼 못한 부분이 많다는 건데 어떻게 하는지 알 수가 없었다.
몇 달 후에는 개선해나갈 수 있을지 모르겠다!
물론 실제 서비스가 아니기 때문에 공부 목적이지만 좀 고치기가 귀찮기도하고 무섭기도 하다.
나중에 시간이 남으면 해봐야겠다.
2022.02.11 Spring 클론코딩 1차 完