Porfolio 제작기 - 모바일 페이지 구현, 버그와의 싸움, refactoring <끝?!>

김현재·2021년 7월 30일
2
post-thumbnail

다음주터 학원을 가게 되어서..🥲 1차 포트폴리오 작업은 여기서 끝내기로 하였다.
마무리 작업이기에 유지보수성을 신경써서 진행했다.

이번에 한 작업은 아래와 같다.

  1. 모바일 페이지 추가
  2. 페이지 로딩 속도 개선
  3. css 리팩토링
  4. Popup 개선
  5. github issue tracking을 통해 버그 잡기

하나 하나씩 풀어보자!

Github Respository : https://github.com/hjkdw95/portfolio

모바일 페이지 추가

Preview



Code

CSS - MediaQuery

@media screen and (max-width: 1024px) {
    .wrapper {
        padding: 0 10px;
    }

    .main {
        height: 57vh;
        margin-bottom: 5px;
    }

    .main-square {
        top: -30%;
        left: 53%;
        width: 50%;
        height: 120%;
        overflow: hidden;
    }

    .works .main-square {
        top: 0;
        left: -3%;
        width: 50%;
    }

    .works-contents {
        top: -550px;
        margin-left: 0;
    }
}

mediaquerymax-width는 1024px로 지정하여 태블릿에서도 모바일 화면으로 접근 가능하도록 만들었다.
모바일 화면은 iphone 5/SE를 기준으로 하여, 가장 작은 화면에서 보았을 때도 불편함이 없도록 했다.
다양한 해상도에서 접속 가능하기에 어느 화면으로 보아도 비슷한 비율을 유지했으면 해서, 최대한 화면 layout은 픽셀이 아닌 화면 대비 %로 작업을 진행했다.



Javascript

function mobileAction() {
    if(media.matches) {
        // 개행을 위해서 innerHTML으로 처리
        detailHeader.innerHTML = `혹시, 저에 대해<br/>좀 더 알고싶으신가요?😁`;
    
        // skill box fade in 기능
        window.addEventListener("scroll", fadeIn);
    
        // skills part 세로배열
        skillBox.classList.remove("main-skills");
        skillBox.classList.add("skills");
    
        // about detail 세로배열
        aboutBox.classList.remove("about-detail");
        aboutBox.classList.add("about-detail-column");
    
        // 모바일일 때 a tag link github으로 변경(우선)
        interactive.setAttribute("href", "https://github.com/hjkdw95/layer-practice");
        brunch.setAttribute("href", "https://github.com/hjkdw95/brunch-page");
        carrot.setAttribute("href", "https://github.com/hjkdw95/javascript101/tree/main/carrot");
    } else {
        detailHeader.innerHTML = `혹시, 저에 대해 좀 더 알고싶으신가요?😁`;
    
        // skills part 가로배열
        skillBox.classList.add("main-skills");
        // about detail 가로 배열
        aboutBox.classList.add("about-detail");
    };
}

모바일 화면일때 바뀌어야 할 요소들(ex. flex-direction)을 한 곳에서 관리할 수 있도록 mobileAction이라는 함수를 생성하여 모아두었다.

flex-direction같은 css 요소들은 별도 class를 만들어, 데스크톱 화면일때는 클래스가 없다가 모바일 화면으로 접속 시 class가 생성되어, 변경된 css요소에 접근 가능하도록 했다. 아무래도 이렇게 해 놓으면 함수를 보다 한 눈에 보기 좋을 것 같아서 우선 이렇게 작업했다!
(보다보니 a tag link 변경되는 부분도 link를 다 변수로 지정해서 할당해줬으면 보다 보기 좋았을 것 같다 ➡️ 개선해야겠다!)



페이지 로딩 속도 개선

Works페이지 부분이 유독 로딩이 느린 것 같아 구글의 PageSpeed Insights를 통해 페이지 속도를 늦추는 요소를 확인하였다.
이미지 파일이 PNG이다보니 용량이 커져, JPEG로 확장자를 변경하고 CDN*을 사용하여 네트워크에서 받아와야될 요소를 최대한 줄여보고자 시도했다.
Github Pages를 이용해서 배포했기에, Jsdelivr를 사용하여 간단하게 CDN을 사용했다.

💡CDN : 용량이 큰 파일을 미리 전세계에 흩어진 캐시 서버에 저장하여, 현 사용자가 위치하고 있는 곳에서 가장 가까운 캐시 서버를 통해 해당 파일을 받아오는 기술



CSS Refactoring

Before

<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">
    <link rel="stylesheet" href="styles/style.css">
    <link rel="stylesheet" href="styles/reset.css">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@400;700&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Archivo+Black&display=swap" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;700&display=swap" rel="stylesheet">
    <script src="./scripts/typewrite.js" defer></script>
    <script src="./scripts/title-up.js" defer></script>
    <script src="./scripts/mobile_change.js" defer></script>
    <title>Welcome</title>
</head>

After

<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">
    <!-- style sheets -->
    <link rel="stylesheet" href="./style.css">

    <!-- fontawesome -->
    <script src="https://kit.fontawesome.com/2ef5ec0d29.js" crossorigin="anonymous"></script>

    <!-- Javascript -->
    <script src="./scripts/typewrite.js" defer></script>
    <script src="./scripts/title-up.js" defer></script>
    <script src="./scripts/mobile_change.js" defer></script>
    <title>Welcome</title>
</head>

css 리팩토링 덕분에 header가 매우 깔끔해졌다..!

CSS 리팩토링을 통해 head에 어마무시한 양으로 쌓여있던 stylesheet를 모두 style.css에서 관리되도록 하였다.

css를 모두 기능별로 나누어, main.css에서는 body 전체에 관련된 내역을 작성하였고, font를 import해왔다.
base에는 변경되지 않을 것들 = 세계관 설정 요소들을 저장해놓았다. 여기에는 우선reset.css를 넣어놓았다. (원래 font도 여기 넣어놓았었는데..import가 잘 되지 않아서 main.css에서 관리하도록 만들었다..)
layout에는 각 페이지마다의 컴포넌트 배치 규칙들을 지정해놓았다. (아래 참고)

/* footer  layout은 footer에 관련된 배치 내용만 기재 */
footer {
    margin: 100px;
    color: #4834d4;
}

.contacts {
    display: flex;
    justify-content: space-between;
    margin-bottom: 80px;
}

.personal-information div{
    padding-bottom: 10px;
}

.copyright {
    color: grey;
    text-align: center;
}

componenets에는 skill-box, work-box등 각 덩어리마다의 서식을 지정하였다. (아래 참고)

/* about box의 서식만 지정 */
.about-detail {
    display: flex;
    justify-content: center;
    align-items: center;
}

.about-image {
    background-image: url("https://cdn.jsdelivr.net/gh/hjkdw95/portfolio@main/assets/profile.jpeg");
    width: 350px;
    height: 500px;
    background-size: cover;
    margin-right: 100px;
}

.about-contents {
    padding: 60px;
    width: 500px;
    color: grey;
}

.about-main {
    border-left: 8px solid #4834d4;
    padding-left: 30px;
}

이런 식으로, modules 에는 공통적으로 사용되는 버튼, 타이틀, form, icon등에 대한 서식을 별도로 저장해놓았다.

폴더가 많아지니까 처음에 보기에는 겁이 나지만, 수정하고픈 것이 있으면 몇백줄의 css 줄을 내리면서 해당 클래스를 찾아야되는 수고로움을 덜 수 있어서 유지에는 훨씬 편리한 것 같다.
아무래도 파일 당 코드 줄 수가 적어 보기가 편하고, 파일 경로가 기능별로 구분되어있기에 수정할 요소를 보다 직관적으로 찾을 수 있는 것 같다.



Popup 개선

Popup은 문제가 참 많았던 아픈 손가락이었다..
첫번째 문제는, 각 popup의 위치가 가운데 고정이 되지 않는다는 점
두번째 문제는, popup.js가 너무 지저분하다는 것이었다.

1. Popup 위치 가운데 고정하기

.popup {
    position: fixed;
    width: 60%;
    height: 600px;
    left: 50%;
    margin-left: -30%; /* half of width */
    top: 50%; 
    margin-top: -300px;/* half of height */
    overflow: auto;
}

정말 허무하게 해결해냈는데, 방법은 다른게 아니고 popup의 position을 fixed로 해놓으면 되는 것이었다..! position: fixed로 가운데 배치를 해놓으니 스크롤을 내려도 popup이 가운데에 이쁘게 고정이 되었다...

2. 지저분한 popup.js 개선하기

function popupID() {
    interBtn.addEventListener("click", () => {
        clickNum = interBtn.dataset.indexNumber;
        openPopup(clickNum);
    });

    brunchBtn.addEventListener("click", () => {
        clickNum =brunchBtn.dataset.indexNumber;
        openPopup(clickNum);
    });

    carrotBtn.addEventListener("click", () => {
        clickNum = carrotBtn.dataset.indexNumber;
        openPopup(clickNum);
    });

    momentumBtn.addEventListener("click", () => {
        clickNum = momentumBtn.dataset.indexNumber;
        openPopup(clickNum);
    });

    habitBtn.addEventListener("click", () => {
        clickNum = habitBtn.dataset.indexNumber;
        openPopup(clickNum);
    });
}

지난 포스트의 이 어마무시한 javascript를 드디어 손봤다.

After

function init() {
    works.addEventListener("click", popupID);
}

// id 찾아오기
function popupID(event) {
    let id = event.target.dataset.indexNumber;
    if(id) {
        openPopup(id);
    }
}

이것도 생각보다 매우 허무하게 해결해냈다.
addEventListner를 부모 요소에도 사용할 수 있다는 것을 완전 잊고 있었지 무엇인가..!

각 버튼의 "부모 요소"인 works에 클릭 이벤트를 받을 수 있도록 설정 한 다음에, 해당 이벤트가 발생한 곳의 indexNumber를 가져오도록 했다.
함수 코드 길이가 5배나 줄어들었다...
(너무 허무해서 절대 잊지 못할 것 같다)



github issue tracking을 통해 버그 잡기


어떤 요소들을 수정해야할지 정리가 안되어서 처음으로 issue를 만들어 사용해봤다.

참, 여태 이것을 왜 안썼는지 너무 유용했다!
무엇이 문제인지, 어떻게 고쳤는지 서사가 작성되어 있기에 history tracking이 가능할 것으로 기대된다! ➡️ 이후에 비슷한 문제로 막히면 이 issue자료들을 보고 보다 빠르게 해결이 가능할 것으로 기대된다.

처음 사용하는 것이다보니 hashtag를 사용하는 요령이 없어서 약간 중구난방으로 정리안된 모습이지만, 이렇게 알게 되었으니, 후에는 보다 더 효율적으로 사용하고싶어졌다!!



회고

회고 작성이 중요하다고 하는데..사람이 참 간사한게 하는 동안에는 온 신경이 프로젝트에 가있다가 프로젝트가 딱 끝나는 순간 앞에 한 고생들과 작업들이 기억이 나지 않게 된다..!(스트레스로 인한 치매인가..)
그렇기에 정말 인상적이였던 것만 기억이 나고..그것 위주로 정리해본다 (다음부턴 다이어리로 기록을 잘 해놓아야겠다고 느끼게된다..!)

파일 용량의 중요성

내가 사용자일때는 웬만한 웹 어플리케이션, 웹페이지가 너무나 빠른 속도로 돌아갔어서 '인터넷이 너무 좋아져서 이젠 그냥 화면이 빨리 로딩이 되는구나'정도로만 생각했었다.
그런데, 막상 직접 작업을 하다보니 고작 png이미지 하나 때문에 페이지 로딩이 매우 느려졌다..! 인터넷 속도가 빨라지긴 했어도, 파일 용량은 절대 간과하지 못할 요소라는것을 피부로 느끼게 되었다.
그 덕분에 왜 요즘 SPA가 강조되고, React등의 라이브러리가 왜 흥행하는지 간접적으로 느낄 수 있었다.

코드를 작성하는 것은 웹페이지 개발의 가장 마지막 단계!

마지막에 리팩토링을 하던 때, 정말 마음이 급급해서 아무렇게나 막 코딩하기 바빴던 프로젝트 첫날이 너무너무 후회스러웠다. 코딩을 하기 전에 공통된 작업요소가 있는지 골조를 짠 다음에 작업을 해야 나중에 리팩토링을 할때도 편하고, 에러 잡는 것도 보다 수월해지는데..
그런 과정이 전혀 없이 header부터 footer까지 그냥 되는대로 막 진행하다보니, 코드를 개선하는 과정에 정말 많은 시간을 투자해야 되었다.

리팩토링 과정에서 이 고생을 하면서 졸업전시회를 준비하던 과정이 참 생각이 많이 났다. 졸업전시회는 1년동안 준비를 하게 되는데, 그 중에 반년은 실제 작업물을 만드는 기간이 아닌, 주제를 정하고, 기획을 하고 세부적으로 어떤 작업을 진행할지 단계를 그려내는 과정으로, 실제 작업물 제작 기간은 마지막 1~2달 정도가 전부이다. 이렇게 실제 제작에 늦게 들어가는 이유는, 제작 전에 발생할 수 있는 모든 변수들을 없애고, 작품의 일관성, 통일감을 유지하기 위해 그렇게 하는 것인데, 이게 참 프로그래밍 작업 과정과 비슷하다는 생각이 들었다.

단순히 코딩을 하는 것은 쉽다. 그러나, 다른 사람이 직관적으로 이해할 수 있는 코드, 수정하고 싶은 부분을 간단히 수정할 수 있도록 짜여진 코드를 만드는 것은 충분한 고민을 거쳐야만 할 수 있다. 눈물을 흘리며 졸업전시회를 준비하던 그 때 처럼, 앞으로의 개발 프로젝트도 코드를 작성하기 전 여러 변수를 고려하고, 효율적인 코드를 짜기 위한 고민을 충분히 한 뒤, 작업을 들어가야겠다.

profile
쉽게만 살아가면 재미없어 빙고!

2개의 댓글

comment-user-thumbnail
2021년 7월 30일

마지막 멘트가 인상 깊네요. 저도 코드를 무작정 치기 전에 계획을 확실히 세우고 해야겠어요! 👍

1개의 답글