주소 목록을 불러와 화면에 표시하고, 메인 주소 설정 및 취소, 주소 수정 및 삭제를 관리하는 웹 페이지를 작성하였습니다. getAddress.html과 getAddress.js 파일을 사용하여 클라이언트와 서버 간 통신을 처리하고, 데이터를 동적으로 렌더링하는 방법을 학습했습니다.
주소 목록 불러오기
fetchAddresses() 함수는 서버에서 GET api/users/me/addresses 엔드포인트를 호출하여 주소 데이터를 가져옵니다.Authorization 헤더에 Bearer 토큰을 포함하여 사용자 인증을 처리합니다.주소 목록 렌더링
renderAddressList() 함수는 가져온 주소 데이터를 기반으로 <ul> 요소에 동적으로 항목을 추가합니다.메인 주소 취소
.cancelMainButton 클래스가 추가된 버튼에 이벤트 리스너를 연결합니다.PATCH api/users/me/addresses/{addressId}/main 요청을 보내 mainAddress를 false로 설정합니다.오류 처리
getAddress.js)을 defer 속성으로 로드하여 DOM 준비 후 스크립트 실행.fetchAddresses() 호출 → REST API에서 주소 데이터 가져오기.renderAddressList()에서 주소 목록을 동적으로 생성.localStorage에서 토큰을 가져와 헤더에 포함하여 인증을 구현하는 방법을 이해했습니다.localStorage에 저장된 토큰을 안전하게 관리하기 위한 대책 필요.이번 작업을 통해 REST API를 활용한 데이터 처리 및 동적 UI 생성의 중요성을 체험할 수 있었습니다. 또한, 사용자 상호작용에 따른 서버 통신과 데이터 반영 과정의 흐름을 명확히 이해하는 데 큰 도움이 되었습니다.
getAddress.html
<!doctype html>
<html lang="en" data-theme="dark">
<head>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
/>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>주소 목록</title>
</head>
<body>
<main class="container">
<header>
<h1>주소 목록</h1>
<a href="createAddress.html" role="button">주소 등록</a>
<a href="my-page.html" role="button">마이 페이지</a>
</header>
<ul id="addressList">
<p>주소를 불러오는 중...</p>
</ul>
</main>
<script src="js/getAddress.js" defer></script>
</body>
</html>
getAddress.js
const addressList = document.querySelector('#addressList');
// 주소 목록 불러오기
const fetchAddresses = async () => {
try {
const response = await fetch('api/users/me/addresses', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
},
});
if (!response.ok) {
throw new Error('주소 목록을 불러오지 못했습니다.');
}
const addresses = await response.json();
renderAddressList(addresses.data);
} catch (error) {
console.error('주소 목록 로드 오류:', error);
addressList.innerHTML =
'<p>주소 목록을 불러오는 중 오류가 발생했습니다.</p>';
}
};
// 주소 목록 렌더링
const renderAddressList = (addresses) => {
addressList.innerHTML = '';
if (addresses.length === 0) {
addressList.innerHTML = '<p>등록된 주소가 없습니다.</p>';
return;
}
addresses.forEach((address) => {
const listItem = document.createElement('li');
listItem.innerHTML = `
<strong>${address.addressName}</strong>: ${address.address}
${
address.mainAddress
? `<span style="color: green;">[메인 주소]</span>
<a href="#" class="cancelMainButton" data-id="${address.addressId}" role="button">메인 주소 취소</a>`
: `<a href="mainAddress.html?id=${address.addressId}" role="button">메인 주소로 설정</a>`
}
<a href="patchAddress.html?id=${address.addressId}" role="button">수정</a>
<a href="deleteAddress.html?id=${address.addressId}" role="button" class="deleteButton">삭제</a>
`;
addressList.appendChild(listItem);
});
// 메인 주소 취소 버튼 이벤트 추가
document.querySelectorAll('.cancelMainButton').forEach((button) => {
button.addEventListener('click', async (e) => {
const addressId = e.target.dataset.id;
try {
const response = await fetch(
`api/users/me/addresses/${addressId}/main`,
{
method: 'PATCH',
headers: {
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ mainAddress: false }), // 메인 주소 취소 요청
},
);
if (!response.ok) throw new Error('메인 주소 취소에 실패했습니다.');
alert('메인 주소가 취소되었습니다.');
window.location.reload();
} catch (error) {
console.error('메인 주소 취소 오류:', error);
}
});
});
};
// 페이지 로드 시 주소 목록 불러오기
fetchAddresses();