요구사항
- 고양이 사진 API를 통해 사진과 폴더를 렌더링합니다.
- 폴더를 클릭하면 내부 폴더의 사진과 폴더를 보여줍니다.
- 현재 경로가 어딘지도 렌더링 합니다(브레드 크럼).
- 루트 경로가 아닌 경우, 파일 목록 맨 앞에 뒤로가기를 넣습니다.
- 사진을 클릭하면 고양이 사진을 모달창으로 보여줍니다.
- esc를 누르거나 사진 밖을 클릭하면 모달을 닫습니다.
- API를 불러오는 중인 경우 로딩 중임을 알리는 처리를 합니다.
요점 정리

- App.js : 모든 컴포넌트를 관리함.
- Breadcrumb.js : 목록의 자취를 보여줌.
- Nodes.js : 노트 타입에 따라 폴더, 파일을 보여줌.
- ImageView.js : 클릭한 이미지를 관리함.
- Loading.js : API가 호출될 동안 로딩 중임을 알려줌.
API 호출
- App.js에서
fetchNodes
라는 함수를 만들어 파라미터로 id를 전달받으면 id에 맞는 노드를 반환함.
- 현재 상태에서 반환받은 값을 포함하여
setState
함.
- 이때
isRoot
를 확인하여 id가 있다면 false를, 없다면 true를 반환하게 만들어 root의 값을 알아낼 수 있음.
파일 이동 구현
- Node 컴포넌트 생성자에
onClick
함수를 만들어 node의 type(directory/file)에 따라 노드의 id에 맞는 폴더를 보여줄지, 파일을 보여줄지를 결정함.
const nodes = new Nodes({ $target, initialState: { isRoot: true, //뒤로가기 넣을지말지 결정 nodes: [], }, onClick: async (node) => { if (node.type === "DIRECTORY") { await fetchNodes(node.id); } if (node.type === "FILE") { this.setState({ ...this.state, selectedImageUrl: `https://cat-api.roto.codes/static${node.filePath}`, }); } }, });
- Nodes.js에서는 root인지를 판별해 뒤로가기 버튼을 만들어주고, nodes를
map
으로 순회하며 파일, 폴더에 맞는 이미지를innerHTML
해줌.
addEventListner
로 클릭했을 때 node의 id를 알아내어onClick
의 파라미터로 전달함.
Modal 구현
onClose
를 클릭 시 콜백함수로 전달함.
onClose
는 선택된 이미지 url을 null로setState
함.
window.addEventListener("keyup", (e) => { if (e.key === "Escape") { onClose(); } }); $imageViewer.addEventListener("click", (e) => { if (Array.from(e.target.classList).includes("Modal")) { onClose(); } });
뒤로 가기
- 뒤로가기는 폴더 경로를 기억하고 있어야 함.
- App.js this.state로
paths
라는 항목을 만들어 뒤로갈 경로를 쌓음 → onClick할 때마다paths.push(node)
- node가 없을 때
onPrevClick
함수가 호출될 수 있게 만듦.
onPrevClick
은paths.pop
을 하여 경로를 뺀 후, paths의 길이에 따라 root를 fectch할지, 마지막 paths의 id를 fetch할지 결정함.
로딩 처리
- Loading.js에서
isLoading
상태에 따라 display값을 block 또는 none으로 지정함.
- App.js에서 컴포넌트 생성자를 만듦.
- fetchNodes 함수가 호출될 때 setState로 isLoading을 true로 변환 후, 함수 마지막 부분(fetch가 완료되었을 때) false로 상태를 변경.
- App.js의 setState에
loading.setState(this.state.isLoading);
값을 추가함으로써 Loading 컴포넌트가 해당 값에 따라 로딩중임을 표시할 수 있게 만듦.
Breadcrumb 만들기
- Breadcrumb.js에서 root와 함께
map
으로 이름을 innerHTML로 그림.
this.render = () => { $breadcrumb.innerHTML = ` <div>Root</div> ${this.state.map(({ name }) => `<div>${name}</div>`).join("")} `; };
- App.js에서 breadcrumb 컴포넌트를 만들고 setState에
breadcrumb.setState(this.state.paths);
를 함(로딩바와 같은 원리).
- 클릭했을 때 바로가기 만들기 : breadcrumb 컴포넌트에
onClick: (id) => {fetchNodes(id);}
- 이때 root 등 이전 경로를 클릭했을 땐 path를 다시 렌더링하여 이전에 표시된 경로를 지워주어야 함.
//onClick 내부 if (id) { const nextPaths = id ? [...this.state.paths] : []; const pathIndex = nextPaths.findIndex((path) => path.id === id); this.setState({ ...this.state, paths: nextPaths.slice(0, pathIndex + 1), }); } else { this.setState({ ...this.state, paths: [], }); }
컴포넌트끼리 유기적으로 움직이게 만들면, 매번 같은 코드를 만들필요 없이 컴포넌트의 큰 흐름에 합류시키기만 하면 됨.