점메추 API Ajax 호출

2025. 9. 4. 20:59·HTML&CSS/HTML&CSS 실습

📚 필수 과제

1. 점심 메뉴 등록 화면 만들기

더보기
더보기

1️⃣ 목적

  • 사용자 입력을 기반으로 데이터를 구성하는 구조를 익힌다.
  • HTML<form>, <input> 등의 활용법을 익힌다.

2️⃣ 구현 내용

  • 메뉴 등록용 HTML 페이지(register.html)를 만들고, 입력 필드를 구성해보세요.
  • 이름, 맵기, 가격, 종류, 기분을 입력받는 form을 작성해보세요.
            <button id="button-submit" type="submit">등록하기</button>
            <button id="button-list" type="button" onclick="location.href='list.html'">목록보기</button>
            <button id="button-home" type="button" onclick="location.href='index.html'">처음으로</button>

 

과제 4번을 진행하며 수행했던 등록화면을 그대로 인용하였고 일부 수정하여 기능을 추가함

기존에는 음식 이름에 대한 입력기능이 없었던 점을 고려, input type = "text" 형태의 추가 데이터 형성

 

필수기능 4번에서 요구하는 문제이나 화면 구성을 위해 등록하기 버튼 이외에 저장된 목록을 확인할 수 있는 방향, 그리고 초기 메인화면의 연결이 진행될 수 있도록 각 html 파일들을 클릭 시 작동할 수 있도록 연결하였음

 

입력받은 form 을 가상의 MockAPI 로 POST 하는 과정이 필요하므로 아래와 같이 값을 저장하고 입력되게끔 진행 하였음

 

  <script>
    /* 서버 베이스를 MockAPI URL을 사용하고자 함
    Javascript 또한 이전 사용했던 구문에서 일부 수정만 진행*/
    const API_BASE = 'https://68b7baee73b3ec66cec55e50.mockapi.io/lunch';

    const budget = document.getElementById('budget');
    const budgetOut = document.getElementById('budget-out');
    const toKRW = v => Number(v).toLocaleString('ko-KR') + ' 원';
    budget.addEventListener('input', () => budgetOut.textContent = toKRW(budget.value));



    const form = document.getElementById('lunch-form');
    form.addEventListener('submit', async (e) => {
      e.preventDefault();
    
    const formData = new FormData(form);
    const name = formData.get('name'||'').trim();        // 이름 입력
    const spicy = formData.get('spicy');                 // 문자열 (ex: "기본 매운 맛")
    const budgetNum = Number(formData.get('budget')||0); // 숫자화
    const category = formData.get('food-category');      // 문자열
    const mood = (formData.get('mood')||'').trim();

    if (!category) return alert('음식 종류를 선택하세요.');
    if (!mood) return alert('오늘의 기분을 입력하세요.');

    const autoName = `${category} - ${spicy || '맵기 미정'}`;
    const payload = {
        name,
        spicy,                // 원문 그대로 저장
        budget: budgetNum,
        category,
        mood,
        };

    try {
        await fetch(API_BASE, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload)
    });
        alert('등록 완료!');
        form.reset();
    } catch (err) {
        console.error(err);
        alert('API 호출 실패');
    }
    });

  </script>

2. 점심 메뉴 목록을 테이블로 보여주기

더보기
더보기

1️⃣ 목적

  • API로부터 받은 리스트 데이터를 반복 렌더링하는 방법을 익힌다.
  • <table> 태그를 활용하여 리스트를 예쁘게 출력해보는 경험을 한다.

2️⃣ 구현 내용

  • fetch()를 이용해 메뉴 목록 API를 호출하세요.
  • 목록에는 간단한 내용만 노출시킵니다.
  • 각 메뉴를 테이블에 <tr>로 표현하고, 이름에 링크를 걸어 점심 메뉴 상세 내용 페이지로 연결해보세요.

 

<table> 태그를 활용하여 진행하는 것이 우선적으로 중요하였고

 

<table id="id"> 선언 , <thead> 테이블 주제가 입력되게 진행하였고, 내용입력을 통해 테이블 형태의 구조를 호출할 수 있도록 하였음

 

또한 이름 셀을 클릭하게 될 경우 상세 내용 페이지로 연결되도록 하기 위해 /lunch?id=<recommend>로 이동될 수 있도록 매칭 시켰음

 

- recommend를 사용한 이유는 API 값에서 입력된 순서 (1,2,3,4,5 ... ) 를 가볍게 나타내고 있어 해당 값을 통해 주소값을 조회할 수 있도록 기능을 연결하였음

    <script>
        const API_BASE = 'https://68b7baee73b3ec66cec55e50.mockapi.io/lunch';
        

  (async () => {
    try {
      const res = await fetch(API_BASE, { headers: { Accept: 'application/json' } });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const rows = await res.json();

      const tbody = document.querySelector('#table tbody'); // ✅ ID 선택자 추가
      if (!Array.isArray(rows) || rows.length === 0) {
        tbody.innerHTML = '<tr><td colspan="5">등록된 항목이 없습니다</td></tr>';
        return;
      }

      tbody.innerHTML = rows.map(m => {
        const budget = m.budget ? Number(m.budget).toLocaleString('ko-KR') + '원' : '-';
        return `
          <tr>
            <td><a href="detail.html?id=${m.recommend}">${m.name ?? '(이름없음)'}</a></td>
            <td>${budget}</td>
            <td>${m.spicy ?? '-'}</td>
            <td>${m.category ?? '-'}</td>
            <td>${m.mood ?? '-'}</td>
          </tr>
        `;
      }).join('');
    } catch (err) {
      console.error(err);
      alert('목록 불러오기 실패: ' + (err.message || 'unknown'));
    }
  })();
    </script>

 

페이지 로드 -> 즉시 실행 async 함수 시작 fectch(API_BASE) ->rows(JSON 배열)

입력값 0인지에 대한 검증 있다면 map으로 tr 생성을 진행 

이름 칸에는 recommend 상세 이동하도록 <a href> 태그 사용

3. 점심 메뉴 상세 내용 조회 페이지 만들기

더보기
더보기

1️⃣ 목적

  • URL 파라미터를 통해 특정 데이터를 불러오는 방법을 익힌다.
  • 상세 데이터를 시각적으로 구성하는 UI 레이아웃 설계 능력을 기른다.

2️⃣ 구현 내용

  • detail.html에서 URL에 담긴 id 값을 가져오세요.
  • 해당 id에 맞는 점심 메뉴 데이터를 Mock API에서 불러와 보여주세요.

 

URL 파라미터의 id값으로 특정 항목을 GET 하였음

GET 한 내용들을 렌더링하도록 진행하였음

 

API 값을 불러오는 과정과 상태에 대해서는 status 를 통해 확인할 수 있고

불러오는 값들은 테이블 내 body 값들로 받아들이도록 설정하여 설정해놓은 항목, 내용 외의 입력이 되었던 이름부터 기분까지의 값들을 끌고 노출시킬 수 있도록 하였음

 

입력된 순서를 기반으로 recommend의 값이 증가하는 개념으로 첫번째로 입력된 음식의 정보가 1, 그 이후 입력값들은 1씩 증가하는 개념의 정보임을 알 수 있었음

 

  (async () => {
    $status.textContent = '불러오는 중…';

    // list.html에서 detail.html?id=<recommend>로 넘어온다고 가정
    const recommend = new URLSearchParams(location.search).get('id');

    // recommend로 조회 (검증/에러처리 없이 최소 흐름)
    const res = await fetch(`${API_BASE}?recommend=${encodeURIComponent(recommend)}`);
    const arr = await res.json();
    const m = arr[0] || {};

    // 배경색/이모지 적용
    document.body.style.background = spicyBg(m.spicy);
    const emoji  = moodEmoji(m.mood);
    const budget = m.budget != null ? Number(m.budget).toLocaleString('ko-KR') + '원' : '-';

    // 표 렌더, 감정에 따라 ${emoji}로 추가 출력
    $tbody.innerHTML = `
      <tr><td>메뉴 이름</td><td>${m.name ?? '(이름없음)'} </td></tr>
      <tr><td>예산</td><td>${budget}</td></tr>
      <tr><td>맵기</td><td>${m.spicy ?? '-'}</td></tr>
      <tr><td>종류</td><td>${m.category ?? '-'}</td></tr>
      <tr><td>기분</td><td>${m.mood ?? '-'} ${emoji}</td></tr>
    `;

    $status.textContent = '';
  })();

4. 공통 UI와 흐름 연결 

더보기
더보기

1️⃣ 목적

  • 여러 HTML 파일 간 흐름을 자연스럽게 연결하는 방식을 익힌다.
  • 사용자 인터랙션을 통해 페이지 이동 및 데이터 전달을 이해한다.

2️⃣ 구현 내용

  • 메인(index.html)에 버튼을 2개 만들어 각각 등록/조회 화면으로 이동하도록 하세요.
  • 페이지 간 이동 시 자연스럽게 연결되도록 location.href를 활용하세요.

 

상기 흐름 연결 필요성으로 인하여 점메추 등록화면 외에 목록 확인, 상세 정보 확인 페이지를 연결함으로서 보다 부드러운 화면 전환과 구성을 할 수 있도록 하였음

 

화면 전환 간에도 API POST와 GET을 반복해야 하는 점임을 감안하여 Javascript를 구성하고자 노력했음


❤️‍🔥 도전 과제

1. 감정에 따라 이모지 보여주기

더보기
더보기

1️⃣ 목적

  • 문자열 데이터를 이모지로 표현하며 조건문과 객체 맵핑의 개념을 익힐 수 있어요.

2️⃣ 구현 내용

  • 기분 텍스트에 따라 해당 감정을 표현하는 이모지를 함께 출력해보세요.
  • *이모지 참고 사이트 : https://snskeyboard.com/emoji/*
 // 기분에 따른 이모지
    function moodEmoji(mood) {
    const txt = (mood || '').trim();
    if (/행복|맛|좋|행복해|신남|설렘|최고|기쁨/.test(txt)) return '😋';
    if (/든든|배부|편안|여유|무난|보통|쏘쏘/.test(txt)) return '😌';
    if (/피곤|우울|스트레스|짜증|답답/.test(txt)) return '😮‍💨';
    return '🙂';
    }

 

3개의 레벨로 이모지의 변화를 주고, 조건을 만족하지 않는 일반적인 경우는 마지막 return 값을 통해 표현될 수 있도록 이모지 조건문을 설정하였음

 

입력될 수 있는 내용 자체가 문장 형태인 관계로 .test() 메서드를 사용하고 반환 값은 true 또는 false 이므로 조건에 따라 이모지 값을 받거나 받지 않는 결과값을 뽑을 수 있음.

2. 맵기 정도에 따라 배경색 바꾸기

더보기
더보기

1️⃣ 목적

  • 동적 스타일 변경을 통해 CSS와 JS의 연동을 학습할 수 있어요.

2️⃣ 구현 내용

  • 메뉴 상세 보기에서 맵기 수준에 따라 배경색이 변경되도록 구현하세요.
// 맵기에 따른 배경색 변화
    function spicyBg(spicy) {
        const s = spicy || '';
        if (/싫어|살짝/.test(s)) return 'lightblue'; 
        if (/기본|조금/.test(s)) return 'lightyellow'; 
        if (/화끈한|아주/.test(s)) return 'red';
        return 'white'; 
    }

 

기존에 구성했던 맵기 단계는 총 6가지이나 3단계의 구성으로 위의 이모지 추출 형태와 유사하게 조건을 형성하였음

맵기 정도에 따라 빨간색 배경색부터 연한 파란색까지의 참 거짓 조건 값을 받을 수 있게 하였음

3. 생성일 기준 최신순 정렬하기 (진행중)

더보기
더보기

1️⃣ 목적

  • 데이터를 시간 기준으로 정렬하는 방법을 학습하고, Date 객체와 정렬 함수 사용에 익숙해질 수 있어요.

2️⃣ 구현 내용

  • createdAt 값을 new Date()로 파싱하여 가장 최신 항목이 위로 오도록 정렬하세요.

☠️ 트러블 슈팅

  • 발생한 Issue ① 
    • 문제의 요구사항이었던 음식 이름 기입을 할 수 있는 기능을 구현하지 못해 전반적인 구조를 다시 건드려야 했고 그 과정에서 상세 내용 페이지 값을 받아오지 못하는 상황이 발생
      • ID값을 임의로 설정하지 않아서 전반적인 내용들을 끌고오는데 어려움이 있었음
  • 해결방법 / 찾아본 내용
    • MockAPI 에 받아들이고 있는 값 중 recommend 내용을 활용하여 id값을 매칭시켰고 상세 페이지 값을 받아올 수 있도록 하였음
    •  
  • 발생한 Issue ②
    • 구현하지 못한 기능에 대해 임의로 진행 값을 인용하거나 GPT 가 안내하는 진행 방향으로 코딩을 하다보니 복잡하고 일관성 없는 코드 구성이 나타났음
  • 해결방법 / 찾아본 내용
    • 필요한 기능들을 이해하고 선언한 변수명 활용한 메서드의 작동원리들을 보다 근본적으로 이해하고자 하였음 
  • 발생한 Issue ③
    • CreatedAt 개념에 대해서는 인지하였으나, 값을 받아올 때 String 형태 또는 숫자로만 값을 불러와 정렬하는 방법이나 표현 방법 수정을 어떻게 해야할지 잘 이해하지 못함
  • 해결방법 / 찾아본 내용
    • 기능 확인 및 추가 학습 예정

'HTML&CSS > HTML&CSS 실습' 카테고리의 다른 글

점심메뉴 추천기 API  (0) 2025.09.03
점심메뉴 추천기  (0) 2025.09.03
할 일 목록 만들기  (0) 2025.09.02
프로필 페이지 제작  (0) 2025.09.02
'HTML&CSS/HTML&CSS 실습' 카테고리의 다른 글
  • 점심메뉴 추천기 API
  • 점심메뉴 추천기
  • 할 일 목록 만들기
  • 프로필 페이지 제작
stark77
stark77
하마의 IT 자기개발 이모저모, 백엔드 개발자로 거듭나기
  • stark77
    하마의 개발자 성장일기
    stark77
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 컴퓨터구조와 운영체제
        • 컴퓨터구조
        • 운영체제
      • SQL 기초
      • Spring
        • 백엔드 기초
        • Spring 실습
      • JAVA
        • Java 실습
      • HTML&CSS
        • HTML&CSS 실습
      • Git&GitHub
        • Git&GitHub 실습
      • 내배캠 끄적끄적
        • Today I Learned
      • 유용한 툴 및 사이트 정리
      • 취미
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Github
    백엔드 기초
    프로세스와 쓰레드
    JPA
    java
    String.format
    git
    객체지향프로그래밍
    객체지향
    경합조건과 교착상태
    WebSocket
    jsp
    네트워크 기초
    Til
    Stomp
    Spriingboot
    for문
    MVC
    백엔드 기초다지기
    Java 문법기초
    Spring
    thymleaf
    다형성
    BEAN
    HTML&CSS
    실시간 데이터 처리
    RestTemplate
    SpringSecurity
    웹소켓
    algorithm
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
stark77
점메추 API Ajax 호출
상단으로

티스토리툴바