https://sh5080.github.io/randomImageViewer/
Random Image Viewer
sh5080.github.io
부탁을 받게 되어서 기출문제를 문제별로 랜덤하게 넘길 수 있도록 만들어보게 되었다.
기본적인 ui는 gpt에게 맡기고, 로직을 구현했다.
백엔드에 관심이 있어서 지망하고 있긴 하지만, 간단하기도 하고 당연히 할줄 알아야 할
기본적인 간단한 구현이라고 생각해서 시작했는데 시행착오가 있어서 포스팅하게 되었다.
구성
정말 간단하게 디렉토리에 이미지파일을 넣어놓고, 웹에서 버튼을 클릭하면 디렉토리 안에 있는
이미지를 랜덤으로 보여줄 수 있도록 구상을 하고, ui가 만들어진 상태에서 시작했다.
처음 로직을 구현했을 때에는 다음과 같았다.
const randomizeButton = document.getElementById("randomize-button");
const randomImage = document.getElementById("random-image");
const imageDir = "public/";
let images = []; // 이미지 파일 이름들을 저장할 배열
// 이미지를 랜덤으로 보여주는 함수
function getRandomImage() {
if (images.length > 0) {
const randomIndex = Math.floor(Math.random() * images.length);
const imageName = images[randomIndex];
randomImage.src = imageName;
}
}
// 이미지 파일들을 불러오는 함수
async function fetchImages() {
try {
const response = await fetch(imageDir);
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.text();
const fileList = new DOMParser()
.parseFromString(data, "text/html")
.getElementsByTagName("a");
for (let i = 0; i < fileList.length; i++) {
const fileName = fileList[i].getAttribute("href");
if (fileName.endsWith(".png")) {
images.push(fileName);
}
}
// 모든 이미지를 로드하고 랜덤 이미지를 보여줌
getRandomImage();
} catch (error) {
console.error("Error fetching images:", error);
}
}
randomizeButton.addEventListener("click", getRandomImage); // 랜덤 버튼 클릭시 이미지 변경
fetchImages(); // 페이지 로드시 이미지 파일들을 불러옴
설명
1. fetchimages로 imageDir 안에 있는 이미지를 fetch하고,
2. 해당하는 이미지는 images 배열에 push한다.
3. 그리고 랜덤하게 배열의 순서를 정하는 함수가 실행된다.
로컬에서 실행했을 때 public에서 이미지를 꺼내서 랜덤으로 실행되는 것을 확인했다.
구글링하니 배포에 대해서는 금방 github pages를 통해 할 수 있는 방법을 찾을 수 있었고,
실행에 옮겼다.
문제점
로컬과 같은 세팅으로 테스트했을 때 이미지를 불러오지 못했다.
네트워크에서도 404로 확인되고, 아예 public이 확인되지 않는 것을 보게 되었다.
그래서 public을 확인할 수 있도록 여러 시도를 했지만 절대경로, 상대경로를 떠나서
public을 찾을 생각이 없어보였다.
이미지 몇 개를 루트 디렉토리로 옮기고 디렉토리까지만 경로를 입력하는 것이 아니라
이미지를 직접 입력해서 불러왔을 때는 잘 되는 것을 확인했다.
그러나 문제풀이용이다보니 문제를 많이 업로드할 수 있고, 파일명 하나하나 입력을 해주면서
사후관리를 하는 것은 쉽지 않을 것 같다.
또한 이미지를 루트보다는 한 디렉토리로 넣는 것이 편할듯 하여 방법을 고민하다가
구글링하면서 내가 어림짐작하기론, github에서 제공하는 pages는 정적 웹 서비스이고,
내가 검색해본 글들은 블로그용으로 다 이미지 한두개를 직접 지정하지,
디렉토리 안에서 전부를 가져오는 케이스는 확인할 수가 없다보니
동적으로 디렉토리에서 가져오는 것은 애초에 안되는 것인가 싶었고,
GitHub Pages에서 "public" 디렉토리가 보이지 않는 것은 정상입니다.
기본적으로 GitHub Pages는 레포지토리의 루트에서 호스팅되는 정적 웹 페이지를 지원합니다.
따라서 "public" 디렉토리는 레포지토리 루트에서 직접 접근할 수 없으며,
이미지 또는 파일을 로드할 때에도 루트를 기준으로 절대 경로를 사용해야 합니다.
라는 gpt의 답변을 듣게 되었다.
맹신할 수는 없으나 다른 방법에 대해 고민하다가 결국 다른 방법에 대해 고민했다.
github에도 api를 제공한다는 것을 알게 되었고, 바로 코드를 수정했다.
해결
api 주소는 이렇게 된다.
` https://api.github.com/repos/$ {repoOwner}/${repoName}/contents/${imageDir}`
url에 먼저 어떻게 데이터가 전송되는지 입력했더니 다음과 같았다.
{
"name": "1.png",
"path": "public/1.png",
"sha": "c137df14afe330fc86929f85fba6a0e01bb15f83",
"size": 138957,
"url": "https://api.github.com/repos/sh5080/randomImageViewer/contents/public/1.png?ref=master",
"html_url": "https://github.com/sh5080/randomImageViewer/blob/master/public/1.png",
"git_url": "https://api.github.com/repos/sh5080/randomImageViewer/git/blobs/c137df14afe330fc86929f85fba6a0e01bb15f83",
"download_url": "https://raw.githubusercontent.com/sh5080/randomImageViewer/master/public/1.png",
"type": "file",
"_links": {
"self": "https://api.github.com/repos/sh5080/randomImageViewer/contents/public/1.png?ref=master",
"git": "https://api.github.com/repos/sh5080/randomImageViewer/git/blobs/c137df14afe330fc86929f85fba6a0e01bb15f83",
"html": "https://github.com/sh5080/randomImageViewer/blob/master/public/1.png"
}
이러한 값이 배열로 들어왔다.
그렇기 때문에 filter하여 처음 구현한 조건대로 png파일만 확인해서 가져오기로 하고,
위와 같이 download_url만 맵핑하여 가져왔다.
코드에 입력값을 살피면 바로 이해할듯 하여 설명은 생략하겠다.
간단하게 url에 github의 정보들을 입력하고 contents 뒤에는 가져오길 원하는 디렉토리를 넣었다.
const randomizeButton = document.getElementById("randomize-button");
const randomImage = document.getElementById("random-image");
const repoOwner = "sh5080";
const repoName = "randomImageViewer";
const imageDir = "public";
// GitHub 레포지토리에서 이미지 파일 이름 목록을 가져오는 함수
async function fetchImages() {
try {
const response = await fetch(
`https://api.github.com/repos/${repoOwner}/${repoName}/contents/${imageDir}`
);
if (!response.ok) {
throw new Error("네트워크 응답이 실패했습니다");
}
const data = await response.json();
const imageFiles = data.filter(
(file) => file.type === "file" && file.name.endsWith(".png")
);
return imageFiles.map((file) => file.download_url);
} catch (error) {
console.error("이미지 가져오기 오류:", error);
return [];
}
}
// 리스트에서 랜덤한 이미지를 화면에 표시하는 함수
async function getRandomImage() {
const images = await fetchImages();
if (images.length > 0) {
const randomIndex = Math.floor(Math.random() * images.length);
randomImage.src = images[randomIndex];
}
}
// "다음 문제" 버튼에 이벤트 리스너를 추가합니다.
randomizeButton.addEventListener("click", getRandomImage);
// 페이지 로드시 랜덤한 이미지를 보여줍니다.
getRandomImage();
코멘트
처음 내가 시도한 방법이 이론상 안되는 것은 아닌 것 같은데,
나와 같은 사례가 아예 없지도 않을 것 같은데..
계속해서 찾아봐도 비슷한 사례를 확인하지 못해서 결국 제공되는 api를 쓰게 되어 약간 아쉽긴 하다..
'개발 > 프로젝트' 카테고리의 다른 글
[세션 / 토큰 로그인 프로젝트] 진행 상황 및 토큰 로그인 구현 (0) | 2023.07.14 |
---|---|
[세션 / 토큰 로그인 프로젝트] 진행 과정(3) 중간점검(mvc 설계) (0) | 2023.07.13 |
[세션 / 토큰 로그인 프로젝트] 진행 과정(2) 구성한 방법, 쿠키에 넣은값들 (0) | 2023.07.09 |
[세션 / 토큰 로그인 프로젝트] 진행 과정(1) 쿠키 전달한 이후 어떻게 검증할 것인가? (0) | 2023.07.08 |
[세션 / 토큰 로그인 프로젝트] 진행 전 공부 과정.. express에서 지원하는 쿠키? 세션 쿠키? 쿠키와 세션 구분하기 (0) | 2023.07.07 |