Skip to content

4.2장: GET 요청 전송

학습 시간: 45분


1. GET: 우주 함대 원격 측정 요청

GET 요청은 데이터를 가져오기 위한 기본 명령어입니다. 우리 통제 센터에서는 이는 "함대 통제 센터, 상황을 보고하라!"라는 요청과 같습니다.

FastAPI 서버에 두 가지 유형의 GET 요청을 보내기 위해 fetch를 사용할 것입니다:

  1. 전체 컬렉션 가져오기: "내 모든 함대를 보여줘".
  2. 단일 리소스 가져오기: "ID 2번 함선에 대한 자세한 정보를 줘".

💡 우주 비유:

GET /spaceships는 모든 함대에 호출 부호를 보고하도록 요청하는 광역 요청입니다.

GET /spaceships/3은 특정 함선(ISS)에 시스템에 대한 전체 데이터를 전송하도록 요청하는 주소 지정 요청입니다.


2. CORS 문제: "행성 간 간섭"

요청을 보내기 전에 한 가지 중요한 문제를 해결해야 합니다. 기본적으로 브라우저는 보안상의 이유로 한 "도메인"(file:///... 또는 http://localhost:5500)에서 로드된 웹 페이지(우리의 통제 센터)가 다른 "도메인"(http://127.0.0.1:8000)의 API로 요청을 보내는 것을 금지합니다.

이 정책을 CORS(교차 출처 리소스 공유)라고 합니다.

프론트엔드가 백엔드와 통신할 수 있도록 하려면 FastAPI 서버가 브라우저에게 "괜찮아, 이 주소에서의 요청을 신뢰해"라고 말하도록 구성해야 합니다.

1단계: python-multipart 설치 미들웨어의 올바른 작동을 위해 필요합니다.

pip install python-multipart

2단계: main.py에서 CORS 설정 FastAPI 프로젝트의 main.py 파일을 열고 다음 코드를 추가하세요:

# main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware  # <-- 미들웨어 임포트

# ... 나머지 코드 (모델, db_spaceships) ...

app = FastAPI(
    title="Fleet Management API",
    # ...
)

# --- CORS 설정 ---
# 어떤 "도메인"(origins)이 요청을 보낼 수 있는지 지정합니다.
origins = [
    "http://localhost",
    "http://localhost:8080",
    "http://127.0.0.1:5500",  # VS Code의 Live Server용 주소
    "null"  # 로컬 파일 file:/// 에서의 요청용
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,  # 지정된 origins 허용
    allow_credentials=True,
    allow_methods=["*"],  # 모든 메서드 (GET, POST 등) 허용
    allow_headers=["*"],  # 모든 헤더 허용
)

# --- 아래에 엔드포인트 ---
@app.get("/")
# ...
이제 API 서버는 프론트엔드로부터 요청을 받을 준비가 되었습니다. 변경 사항을 적용하려면 uvicorn을 다시 시작하세요!


3. 모든 함선 목록 가져오기

우리 함대를 표시할 인터페이스를 만들어봅시다.

1단계: index.html 업데이트

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>통제 센터 - 함대 관리</title>
    <style>
        body { font-family: sans-serif; }
        .ship-list { list-style: none; padding: 0; }
        .ship-list li { border: 1px solid #ccc; margin-bottom: 10px; padding: 15px; border-radius: 5px; }
    </style>
</head>
<body>
    <h1>우주 함대 제어판</h1>

    <button id="load-fleet-btn">함대 데이터 요청</button>

    <h2>기기 목록:</h2>
    <ul id="fleet-list" class="ship-list">
        <li>명령 대기 중...</li>
    </ul>

    <script src="app.js"></script> <!-- 외부 스크립트 연결 -->
</body>
</html>

2단계: app.js 생성 index.html 옆에 app.js 파일을 만드세요. 여기에 모든 로직을 배치할 것입니다.

// app.js

const API_BASE_URL = 'http://127.0.0.1:8000'; // 우리 FastAPI 서버의 URL

const loadFleetBtn = document.getElementById('load-fleet-btn');
const fleetList = document.getElementById('fleet-list');

// 함대 로드 및 표시 함수
async function fetchAndDisplayFleet() {
    try {
        fleetList.innerHTML = '<li>원격 측정 로드 중...</li>';

        // /spaceships로 GET 요청 전송
        const response = await fetch(`${API_BASE_URL}/spaceships`);

        if (!response.ok) {
            throw new Error(`네트워크 오류: ${response.status}`);
        }

        const ships = await response.json(); // 함선 배열 가져오기

        // 목록을 지우고 데이터 표시
        fleetList.innerHTML = '';
        if (ships.length === 0) {
            fleetList.innerHTML = '<li>등록된 기기가 없습니다.</li>';
            return;
        }

        ships.forEach(ship => {
            const listItem = document.createElement('li');
            listItem.innerHTML = `
                <strong>${ship.name} (ID: ${ship.id})</strong><br>
                유형: ${ship.type}<br>
                발사 연도: ${ship.launch_year}<br>
                상태: ${ship.status}
            `;
            fleetList.appendChild(listItem);
        });

    } catch (error) {
        console.error('함대 데이터를 로드하지 못했습니다:', error);
        fleetList.innerHTML = `<li>오류: ${error.message}</li>`;
    }
}

// 버튼에 이벤트 핸들러 추가
loadFleetBtn.addEventListener('click', fetchAndDisplayFleet);

  • async/await: 우리는 프라미스 작업을 위한 새롭고 더 편리한 구문을 사용했습니다. 4.5장에서 자세히 살펴보겠습니다. 지금은 await가 페이지를 차단하지 않고 프라미스 실행을 "기다린다"는 것만 알아두세요.
  • try...catch: 비동기 함수에서 오류를 처리하는 좋은 방법입니다.

3단계: 테스트 브라우저에서 index.html을 엽니다 (VS Code의 Live Server 확장 기능을 통해 http://127.0.0.1:5500에서 실행하는 것이 가장 좋습니다). "함대 데이터 요청" 버튼을 클릭합니다. FastAPI에서 가져온 함선 목록이 페이지에 표시되어야 합니다!


4. 단일 함선 데이터 가져오기

이제 특정 ID로 정보를 요청하는 양식을 추가해봅시다.

1단계: index.html에 양식 추가

<!-- index.html, 목록 뒤 -->
<hr>
<h2>ID로 요청</h2>
<form id="ship-form">
    <input type="number" id="ship-id-input" placeholder="기기 ID 입력" required>
    <button type="submit">기기 찾기</button>
</form>
<div id="ship-details" class="ship-list"></div>

2단계: app.js에 로직 추가

// app.js, 파일 끝에

const shipForm = document.getElementById('ship-form');
const shipIdInput = document.getElementById('ship-id-input');
const shipDetails = document.getElementById('ship-details');

async function fetchShipById(event) {
    event.preventDefault(); // 페이지 새로고침 방지
    const shipId = shipIdInput.value;

    if (!shipId) {
        alert('ID를 입력해주세요.');
        return;
    }

    try {
        shipDetails.innerHTML = '<li>기기 검색 중...</li>';

        // /spaceships/{id}로 GET 요청 전송
        const response = await fetch(`${API_BASE_URL}/spaceships/${shipId}`);

        if (response.status === 404) {
             throw new Error('해당 ID의 기기가 등록되지 않았습니다.');
        }
        if (!response.ok) {
            throw new Error(`네트워크 오류: ${response.status}`);
        }

        const ship = await response.json();

        shipDetails.innerHTML = `
            <li>
                <strong>${ship.name} (ID: ${ship.id})</strong><br>
                유형: ${ship.type}<br>
                발사 연도: ${ship.launch_year}<br>
                상태: ${ship.status}
            </li>
        `;
    } catch (error) {
        console.error(`기기 ${shipId} 검색 오류:`, error);
        shipDetails.innerHTML = `<li>오류: ${error.message}</li>`;
    }
}

shipForm.addEventListener('submit', fetchShipById);

  • 사용자에게 더 명확한 오류 메시지를 제공하기 위해 404 상태를 별도로 처리했습니다.

3단계: 테스트 페이지를 새로고침하고, 기존 함선의 ID(예: 1)를 입력한 다음 "기기 찾기"를 클릭합니다. 해당 데이터를 볼 수 있습니다. 존재하지 않는 ID(예: 99)를 입력해보세요. 오류 메시지가 표시될 것입니다.


복습 퀴즈

1. 브라우저의 CORS 정책이 필요한 이유는...

2. `localhost:5500`의 프런트엔드가 FastAPI에 접근하도록 허용하려면...

3. ID=5인 특정 리소스에 대한 데이터를 얻으려면 요청 URL은 다음과 같아야 합니다:

4. JavaScript에서 `await` 키워드는 다음으로 선언된 함수 내에서만 사용할 수 있습니다:

5. 폼 제출 핸들러에서 `event.preventDefault()`는 다음을 위해 필요합니다:


🚀 장 요약:

"지구"와 "우주" 간의 통신 채널을 성공적으로 설정하고 원격 측정을 요청하는 방법을 배웠습니다!

  • 🛡️ FastAPI 서버에 CORS를 설정하여 "행성 간 간섭" 문제를 해결했습니다.
  • 🛰️ 모든 우주선 목록을 가져와 표시하는 기능을 구현했습니다.
  • 🔭 ID로 특정 우주선에 대한 데이터를 요청하는 인터페이스를 생성했습니다.

관제 센터가 데이터를 수신하고 있습니다! 다음 장에서는 우주선을 생성, 업데이트 및 삭제하는 명령을 전송하는 등 적극적인 조치로 넘어갈 것입니다.

📌 확인:

  • CORSMiddleware가 설정된 상태로 FastAPI 서버가 실행 중인지 확인하세요.
  • "데이터 요청" 버튼을 클릭할 때 페이지에 우주선 목록이 나타나는지 확인하세요.
  • ID로 검색하는 폼이 기존 우주선을 올바르게 찾고 존재하지 않는 우주선에 대해 오류를 보고하는지 확인하세요.

⚠️ 오류 발생 시:

  • 브라우저 콘솔의 CORS 오류: CORSMiddleware를 추가한 후 uvicorn을 다시 시작하지 않았거나, 프런트엔드 주소(예: http://127.0.0.1:5500)가 origins 목록에 추가되지 않았을 수 있습니다.
  • Failed to fetch: FastAPI 서버가 실행 중이고 API_BASE_URL에 지정된 주소로 액세스할 수 있는지 확인하세요.