본문 바로가기
개발/이것저것

[JavaScript] 나만 쓰는 맛집 리스트 만들기 (카드 UI 구현) - 1. 기본 레이아웃

by 슈스 2026. 4. 15.
반응형

 

요즘 회사에서 점심시간마다 맛집 탐방하는데 푹 빠져서 
이걸 나만 (내 친구들 하고만) 볼 수 있는 리스트를 만들어보면 어떨까? 하고 만들어본 간단한 javascript 페이지!
재미로 만들어본 페이지가 점점 기능이 추가되어서
블로그 포스팅을 해보기로 함ㅋㅋㅋ
(포스팅에서 다루는 음식점 이름은 gpt가 뽑아준 가상의 식당들임)
 
우선 이번 포스팅에서는 기본 레이아웃만 다뤄본다.
 

 
메인 페이지 : 

index.html
script.js
style.css

 
 
기본 기능 : 

- 저장된 맛집 리스트 카드 형태로 구현
- 랜덤 추천 버튼

 
 
index.html

<!doctype html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>우리 동네 맛집 리스트</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <div class="container">
    <h1>🍽️ 우리 동네 맛집 리스트</h1>

    <div class="btn-area">
      <button class="random-btn" onclick="pickRandom()">🎲 랜덤 추천</button>
    </div>

    <div id="result" class="result"></div>

    <div id="cardList" class="card-list"></div>
  </div>
  <script src="script.js"></script>
</html>

 
script.js

const restaurants = [
  { name: "김밥천국", category: "bunsik", desc: "빠르게 한 끼 해결" },
  { name: "청년국밥", category: "korean", desc: "든든한 국밥 한 그릇" },
  { name: "뚝배기집", category: "korean", desc: "집밥 느낌 나는 백반집" },
  { name: "제육나라", category: "korean", desc: "제육 가성비 맛집" },
  { name: "이자카야 모모", category: "japanese", desc: "퇴근 후 가볍게 한잔" },
  { name: "파스타집 라라", category: "western", desc: "가성비 좋은 파스타" },
  { name: "즉석떡볶이 달인", category: "bunsik", desc: "볶아먹는 재미" },
  { name: "분식의정석", category: "bunsik", desc: "튀김+떡볶이 기본기" },
  { name: "스시하루", category: "japanese", desc: "가성비 초밥집" },
  { name: "라멘야 코우", category: "japanese", desc: "진한 돈코츠 라멘" },
  { name: "우동집 하루", category: "japanese", desc: "깔끔한 우동 한 그릇" },
  { name: "비스트로 37", category: "western", desc: "분위기 좋은 데이트 장소" },
  { name: "스테이크룸", category: "western", desc: "고기 땡길 때" },
  { name: "피자팩토리", category: "western", desc: "도우 쫀득한 피자" },
  { name: "카페 무드", category: "cafe", desc: "조용한 작업 카페" },
  { name: "브루잉 커피랩", category: "cafe", desc: "핸드드립 전문" },
  { name: "디저트하우스", category: "cafe", desc: "케이크 맛집" },
  { name: "옛날손칼국수", category: "korean", desc: "칼국수 + 김치 조합" },
];

const categoryLabel = {
  korean: "한식",
  bunsik: "분식",
  japanese: "일식",
  western: "양식",
  cafe: "카페",
};

function renderList() {
  const container = document.getElementById("cardList");
  const result = document.getElementById("result");

  result.innerHTML = "";

  container.innerHTML = "";

  restaurants.forEach((item) => {
    const card = document.createElement("div");
    card.className = "card";

    card.classList.add(item.category);

    card.innerHTML = `
  <div class="title">${item.name}</div>
  <div class="category">${categoryLabel[item.category]}</div>
  <div class="desc">${item.desc}</div>
`;
    container.appendChild(card);
  });
}

function pickRandom() {
  const result = document.getElementById("result");

  const randomIndex = Math.floor(Math.random() * restaurants.length);
  const pick = restaurants[randomIndex];

  result.innerHTML = "";

  // 제목 추가
  const title = document.createElement("div");
  title.className = "result-title";
  title.innerText = "✔️ 오늘의 추천!";

  // 카드 생성
  const card = document.createElement("div");
  card.className = "card";

  // 카테고리별 클래스 추가
  if (card.category === "한식") {
    card.classList.add("korean");
  } else if (card.category === "일식") {
    card.classList.add("japanese");
  } else if (card.category === "중식") {
    card.classList.add("chinese");
  } else if (card.category === "양식") {
    card.classList.add("western");
  } else if (card.category === "카페") {
    card.classList.add("cafe");
  }

  card.innerHTML = `
    <div class="title">${pick.name}</div>
    <div class="category">${categoryLabel[pick.category]}</div>
    <div class="desc">${pick.desc}</div>
  `;

  result.appendChild(title);
  result.appendChild(card);
}

renderList();

 
 
style.css

* {
  box-sizing: border-box;
}

body {
  padding: 16px;
  font-family: Arial, sans-serif;
  background: #f7f7f7;
  margin: 0;
  padding: 20px;
}

h1 {
  text-align: center;
  margin-bottom: 10px;
}

.container {
  max-width: 900px;
  margin: 0 auto;
}

.btn-area {
  text-align: center;
  margin-bottom: 20px;
}

button {
  padding: 10px 15px;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  margin: 5px;
}

.random-btn {
  background: #ff6b6b;
  color: white;
}

.reset-btn {
  background: #ddd;
}
#result {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: 25px;
}

.result-title {
  font-size: 22px;
  font-weight: bold;
  margin-bottom: 12px;
  color: #333;
}

.result .card {
  width: 100%;
  max-width: 420px;
  padding: 22px;
  border-radius: 16px;

  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
  transform: scale(1.03);

  border-left-width: 8px; /* 강조 */
  transition: 0.3s;
}

.result .card:hover {
  transform: scale(1.05);
}

@media (max-width: 600px) {
  .result .card {
    padding: 18px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
  }
}

.card-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
}

.card {
  background: #fff;
  border-radius: 12px;
  padding: 15px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
  transition: 0.2s;
  border-left: 6px solid transparent;
}

.card:hover {
  transform: translateY(-3px);
}

.title {
  font-size: 18px;
  font-weight: bold;
  margin-bottom: 5px;
}

.category {
  font-size: 13px;
  color: #888;
  margin-bottom: 10px;
}

.desc {
  font-size: 14px;
  color: #333;
}

.card.korean {
  border-left-color: #ff6b6b;
}

.card.bunsik {
  border-left-color: #ffa94d;
}

.card.japanese {
  border-left-color: #4dabf7;
}

.card.western {
  border-left-color: #51cf66;
}

.card.cafe {
  border-left-color: #845ef7;
}

@media (max-width: 600px) {
  h1 {
    font-size: 20px;
  }

  .card {
    padding: 12px;
    border-radius: 10px;
  }

  .card .title {
    font-size: 16px;
  }

  .card .desc {
    font-size: 13px;
  }

  .result .card {
    max-width: 100%;
    transform: none; /* 모바일에서는 확대 제거 */
  }

  button {
    width: 100%;
    margin-bottom: 8px;
  }
}

 
 
 


추후 포스팅할 추가사항 : 
- 구글 시트 연동 (맛집 리스트, 리뷰 등 저장할 공간)
- 리뷰 시스템 (별점, 한줄평)
- 필터링 (카테고리, 키워드 검색 등)

반응형