본문 바로가기
CODE/Front-end

프로그래머스 Dev-Matching 2021 상반기 과제

by zerozero\base 2022. 3. 12.

올해 상반기 프로그래머스 Dev-Matching을 준비하면서, 지난해 상반기 과제를 풀어보았다.

 

과제 개요

https://programmers.co.kr/skill_check_assignments/100

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

고양이 사진과 파일 정보가 담긴 API로 일종의 사진 탐색기를 만드는 것이 과제이다. 다른 모듈을 사용하지 않고 바닐라 JavaScript로 만들어야 하며, 제한 시간은 3시간이었다.

 

우선 첫 화면(root)을 렌더링하는 함수를 구현했다. async/await 비동기 함수로 만들었고, 여기서 Loading은 로딩 화면을 렌더링하는 함수다.

async function Root() {
    Loading();

    const apiurl = "https://zl3m4qq0l9.execute-api.ap-northeast-2.amazonaws.com/dev";
    let rootdata = await fetch(apiurl, {
        method: 'GET',
    })
    .then(res => res.json())
    .catch(res => console.log(res.json()));
    await RootRender(rootdata);
};

 

그 다음으론 싱글 페이지로 구현(SPA)해야 해서, 폴더나 이미지를 클릭했을 때 화면을 렌더링하는 함수를 구현했다. e.target.closest과 dataset을 활용해 선택한 항목의 이름과 타입(폴더인지 파일인지), 이미지 링크를 가져오는 방식이다. 

function Click() {
    Nodes.addEventListener("click", (e) => {
        let selected = e.target.closest("div").id;
        let selectedName = e.target.closest("div").dataset.item;
        let selectedType = e.target.closest("div").dataset.type;
        let selectedImg = e.target.closest("div").dataset.file;
        if (selected && selectedType === "directory") {
            Depth.push(selected);
            DepthName.push(selectedName);
            DepthNameRender();
            NotRoot(selected, selectedName);
        } else if (selected && selectedType === "file") {
            ViewImg(selectedImg);
        } else {
            Depth.pop();
            DepthName.pop();
            DepthNameRender();
            Depth[Depth.length-1] ? NotRoot(Depth[Depth.length-1]) : Root();
        }
    });
};

 

 

 

코드 전체

const appwrap = document.querySelector(".App");
const Nodes = appwrap.querySelector(".Nodes");
const Bread = appwrap.querySelector(".Breadcrumb");
const Depth = [null];
const DepthName = ['root'];

function Loading() {
    Nodes.innerHTML = `
        <div class="Loading">
        </div>
    `;
}
function ViewImg(file) {
    appwrap.insertAdjacentHTML('beforeend', `
    <div class="Modal ImageViewer">
        <div class="content">
        <img src="https://fe-dev-matching-2021-03-serverlessdeploymentbuck-t3kpj3way537.s3.ap-northeast-2.amazonaws.com/public${file}" width="450px">
    </div>
    `);
    const ViewerModal = document.querySelector(".ImageViewer");
    ViewerModal.addEventListener("click", (e) => {
        if (e.target.classList.contains("Modal")){
            ViewerModal.remove();
        };
    })
    document.addEventListener("keydown", (e) => {
        if (e.key === "Escape") {
            ViewerModal.remove();
        }
    });
};
function DepthNameRender() {
    Bread.innerHTML = DepthName.map((value) => {
        return `<div>${value}</div>`;
    }).join("");
};

function RootRender(data) {
    Nodes.innerHTML = data.map((ele) => {
        return `<div class="Node" id=${ele.id} data-item=${ele.name} data-type=${ele.type.toLowerCase()} data-file=${ele.filePath}>
            <img src="./assets/${ele.type.toLowerCase()}.png">
            <div>${ele.name}</div>
        </div>
        `
    }).join("");
};
function NotRootRender(data) {
    console.log(data);
    const prev = `<div class="Node" data-type="prev">
    <img src="./assets/prev.png">
  </div>
    `;
    Nodes.innerHTML = prev + data.map((ele) => {
        return `<div class="Node" id=${ele.id} data-item=${ele.name} data-type=${ele.type.toLowerCase()} data-file=${ele.filePath}>
            <img src="./assets/${ele.type.toLowerCase()}.png">
            <div>${ele.name}</div>
        </div>
        `
    }).join("");
};

function Click() {
    Nodes.addEventListener("click", (e) => {
        let selected = e.target.closest("div").id;
        let selectedName = e.target.closest("div").dataset.item;
        let selectedType = e.target.closest("div").dataset.type;
        let selectedImg = e.target.closest("div").dataset.file;
        if (selected && selectedType === "directory") {
            Depth.push(selected);
            DepthName.push(selectedName);
            DepthNameRender();
            NotRoot(selected, selectedName);
        } else if (selected && selectedType === "file") {
            ViewImg(selectedImg);
        } else {
            Depth.pop();
            DepthName.pop();
            DepthNameRender();
            Depth[Depth.length-1] ? NotRoot(Depth[Depth.length-1]) : Root();
        }
    });
};

async function Root() {
    Loading();

    const apiurl = "https://zl3m4qq0l9.execute-api.ap-northeast-2.amazonaws.com/dev";
    let rootdata = await fetch(apiurl, {
        method: 'GET',
    })
    .then(res => res.json())
    .catch(res => console.log(res.json()));
    await RootRender(rootdata);
};
async function NotRoot(itemId) {
    Loading();

    const apiurl = "https://zl3m4qq0l9.execute-api.ap-northeast-2.amazonaws.com/dev/"+itemId;
    let getdata = await fetch(apiurl, {
        method: 'GET',
    })
    .then(res => res.json())
    .catch(res => console.log(res.json()));
    await NotRootRender(getdata);
};



Root();
Click();

댓글