테마 저장 구현하기
사용자가 선택한 색상을 저장하고 다시 불러올 수 있도록 해야하고
사용자는 배경색과 테두리 색상을 변경할 수 있으며,
변경된 색상은 로컬 스토리지 (localStorage) 에 저장되어야한다.
▶ html, css 파일
<!DOCTYPE html>
<html>
<head>
<title>테마 저장하기</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
</style>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h2 class="heading">테마 설정</h2>
<div class="options">
<div class="option">
<span>채우기</span>
<input type="color" id="box-color" name="box-color">
</div>
<div class="option">
<span>테두리</span>
<input type="color" id="box-border-color" name="box-border-color">
</div>
</div>
<div id="box"></div>
<script src="index.js"></script>
</body>
</html>
@font-face {
font-family: 'NanumSquareNeo-Variable';
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_11-01@1.0/NanumSquareNeo-Variable.woff2')
format('woff2');
font-weight: normal;
font-style: normal;
}
:root {
--red: #e46e80;
--orange: #f18575;
--yellow: #fbc85b;
--green: #32b9c1;
--blue: #5195ee;
--purple: #8579ef;
--n000: #f9fafc;
--n100: #f0f3f7;
--n200: #e0e4ec;
--n300: #cacfd9;
--n400: #9ba2b0;
--n500: #7f8594;
--n600: #616775;
--n700: #494d59;
--n800: #3e414d;
--n900: #343843;
--n930: #2b2f3a;
--n960: #262a34;
--light-red: #ffa8b5;
--light-orange: #ffbab0;
--light-yellow: #ffe7b2;
--light-green: #7fd9df;
--light-blue: #77b2ff;
--light-purple: #9689ff;
--dark-red: #dc596d;
--dark-orange: #e16a58;
--dark-yellow: #e4ac31;
--dark-green: #1d9da6;
--dark-blue: #3a7fd8;
--dark-purple: #695dd0;
--light-brown: #b9968e;
--brown: #a87c72;
--dark-brown: #9a695e;
}
* {
box-sizing: border-box;
}
html {
font-family: NanumSquareNeo-Variable, sans-serif;
font-size: 16px;
}
body {
margin: 0 auto;
padding: 16px;
max-width: 720px;
width: 100%;
}
a {
color: var(--purple);
}
.heading {
font-size: 32px;
margin: 32px 0;
text-align: center;
}
.options {
display: flex;
gap: 32px;
margin: 32px 0;
}
.option {
flex: 1 0;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 16px;
padding: 24px;
background-color: var(--n100);
border-radius: 8px;
}
#box {
height: 100px;
margin: 0 auto;
border-radius: 4px;
border-style: solid;
border-width: 16px;
}
우선 테마 저장 기능을 구현하기위해 무엇을 해야하는지 생각해보자.
사용자가 색상을 선택하면 박스의 색상이 바뀌고
그 값이 저장되어야 한다.
즉, 다음과 같은 기능을 구현 해야야한다.
- UI 요소 가져오기 (input type="color", div 등)
- 사용자가 색상을 선택하면 박스의 색상을 변경
- 변경된 색상을 저장 (localStorage)
- 페이지를 새로고침해도 로컬 스토리지에 저장된 색상을 유지
▶ 필요한 요소 정리 (HTML 분석)
우선 자바스크립트에서 조작해야 할 요소들을 정리해야 한다.
HTML 파일을 보면 색상을 변경할 두 개의 input 태그와 색상이 적용될 박스가 있다.
- #box-color : 박스 배경색을 선택하는 색상 입력 필드
- #box-border-color: 박스 테두리 색상을 선택하는 색상 입력 필드
- #box: 색상을 적용할 대상
이제 이 요소들을 자바스크립트에서 가져와서 조작해야한다.
▶ 필요한 기능
- Step 1. 요소를 가져오기 (document.getElementById)
- Step 2. 색상이 변경되면 change 이벤트 감지
- Step 3. 변경된 색상을 박스에 적용
- Step 4. 변경된 색상을 localStorage에 저장
- Step 5. 저장된 색상을 페이지 로드 시 다시 적용
▼ Step 1. 요소 가져오기
getElementById를 사용하여 요소를 가져온다.
// index.js
// Step 1. 요소를 가져오기 (document.getElementById)
const box = document.getElementById('box');
const boxColorInput = document.getElementById('box-color');
const boxBorderColorInput = document.getElementById('box-border-color');
▼ Step 2. 색상이 변경되면 change 이벤트 감지
// Step 2. 색상이 변경되면 이벤트 감지
boxColorInput.addEventListener('change', (event) => {
console.log('배경색이 변경됨:', event.target.value);
})
boxBorderColorInput.addEventListener('change', (event) => {
console.log('테두리색이 변경됨:', event.target.value);
})
사용자가 색상을 선택하면 콘솔에 출력 되게 한다. (디버깅)
▼ Step 3. 변경된 색상을 박스에 적용
// Step 2. 색상이 변경되면 이벤트 감지
boxColorInput.addEventListener('change', (event) => {
// console.log('배경색이 변경됨:', event.target.value);
// Step 3. 변경된 색상을 박스에 적용
box.style.backgroundColor = event.target.value;
})
boxBorderColorInput.addEventListener('change', (event) => {
// console.log('테두리색이 변경됨:', event.target.value);
// Step 3. 변경된 색상을 박스에 적용
box.style.borderColor = event.target.value;
})
▼ Step 4. 변경된 색상을 저장 (localStorage)
// Step 2. 색상이 변경되면 이벤트 감지
boxColorInput.addEventListener('change', (event) => {
const color = event.target.value;
// console.log('배경색이 변경됨:', event.target.value);
// Step 3. 변경된 색상을 박스에 적용
box.style.backgroundColor = color;
// Step 4. 변경된 색상을 저장 (localStorage)
localStorage.setItem('boxColor', color);
})
boxBorderColorInput.addEventListener('change', (event) => {
const borderColor = event.target.value;
// console.log('테두리색이 변경됨:', event.target.value);
// Step 3. 변경된 색상을 박스에 적용
box.style.borderColor = borderColor;
// Step 4. 변경된 색상을 저장 (localStorage)
localStorage.setItem('boxBorderColor', borderColor);
})
이제 변경된 색상이 localStorage 에 저장되지만
새로고침하면 다시 기본값으로 돌아오는 문제가 발생한다.
▼ Step 5. 저장된 색상을 페이지 로드 시 다시 적용
새로고침을 하면 기존의 변수 값이 사라지므로 localStorage에서 저장된 값을 다시 불러와야한다.
사용자가 설정한 색상을 유지하려면
페이지가 로드될 때 이전에 저장된 값이 있으면 불러와서 적용해야한다.
우선 localStorage에 저장된 boxColor랑 boxBorderColor 값을 가져와야 한다
const savedBoxColor = localStorage.getItem('boxColor');
const savedBoxBorderColor = localStorage.getItem('boxBorderColor');
그런 다음 if문을 열어서 null 값이아닌
saveBoxColor와 saveBOxBorderColor 값이 존재한다면
box의 배경색과 테두리색을 저장된 값으로 변경해주고
input type="color' 에도 저장된 값을 적용해줘야한다.
또한 UI와 실제 박스 색상이 일치하도록 해줘야한다.
if (saveBoxColor) {
box.style.backgroundColor = saveBoxColor;
boxColorInput.value = saveBoxColor;
}
if (saveBoxBorderColor) {
box.style.borderColor = saveBoxBorderColor;
boxBorderColorInput.value = saveBoxBorderColor;
}
}
그리고 페이지가 로드될 때 (window.onload) 실행해야 저장된 색상이 적용되므로
로컬 스토리지에서 가져온 색상을 박스와 색상 선택기에 반영해야한다.
loadSavedColors(); // 페이지 로드 시 실행
모든 단계를 합치면 다음과 같이 정상적으로 작동하는 것을 확인할 수 있다.
const box = document.getElementById('box');
const boxColorInput = document.getElementById('box-color');
const boxBorderColorInput = document.getElementById('box-border-color');
function loadSavedColors() {
const savedBoxColor = localStorage.getItem('boxColor');
const savedBoxBorderColor = localStorage.getItem('boxBorderColor');
if (savedBoxColor) {
box.style.backgroundColor = savedBoxColor;
boxColorInput.value = savedBoxColor;
}
if (savedBoxBorderColor) {
box.style.borderColor = savedBoxBorderColor;
boxBorderColorInput.value = savedBoxBorderColor;
}
}
boxColorInput.addEventListener('change', (event) => {
const color = event.target.value;
box.style.backgroundColor = color;
localStorage.setItem('boxColor', color);
});
boxBorderColorInput.addEventListener('change', (event) => {
const borderColor = event.target.value;
box.style.borderColor = borderColor;
localStorage.setItem('boxBorderColor', borderColor);
});
loadSavedColors();
+α 기본값 설정하기
기본값을 미리 지정하면 로컬 스토리지에 값이 없을 때도 색상이 적용된다
우선 기본값을 먼저 설정해준다.
// Step 5. 저장된 색상을 페이지 로드 시 다시 적용
function loadSavedColors() {
// 색상 기본값 설정
const defaultBoxColor = '#ff0000'; // 기본 배경색 (빨강)
const defaultBoxBorderColor = '#0000ff'; // 기본 테두리색 (파랑)
const savedBoxColor = localStorage.getItem('boxColor');
const savedBoxBorderColor = localStorage.getItem('boxBorderColor');
if (savedBoxColor) {
box.style.backgroundColor = savedBoxColor;
boxColorInput.value = savedBoxColor;
}
if (savedBoxBorderColor) {
box.style.borderColor = savedBoxBorderColor;
boxBorderColorInput.value = savedBoxBorderColor;
}
}
loadSavedColors(); // 페이지 로드 시 실행
그런다음 || 연산자로 boxColor가 null이면 기본값 #ff0000이 적용되고
boxBorderColor가 null이면 기본값 #0000ff이 적용되게 해준다.
// Step 5. 저장된 색상을 페이지 로드 시 다시 적용
function loadSavedColors() {
// 색상 기본값 설정
const defaultBoxColor = '#ff0000'; // 기본 배경색 (빨강)
const defaultBoxBorderColor = '#0000ff'; // 기본 테두리색 (파랑)
const savedBoxColor = localStorage.getItem('boxColor') || defaultBoxColor; // 저장된 값이 없으면 기본값 사용
const savedBoxBorderColor = localStorage.getItem('boxBorderColor') || defaultBoxBorderColor; // 저장된 값이 없으면 기본값 사용
if (savedBoxColor) {
box.style.backgroundColor = savedBoxColor;
boxColorInput.value = savedBoxColor;
}
if (savedBoxBorderColor) {
box.style.borderColor = savedBoxBorderColor;
boxBorderColorInput.value = savedBoxBorderColor;
}
}
loadSavedColors(); // 페이지 로드 시 실행
장바구니 구현하기
파일이 많은 관계로 아예 통으로 업로드함
이번 장바구니 구현은 로컬 스토로지가 아닌 세션 스토리지를 사용할 것이다.
▶ 로컬 스토리지 vs. 세션 스토리지 차이점
로컬 스토리지 (localStorage) | 세션 스토리지 (sessionStorage) | |
데이터 유지 기간 | 브라우저를 닫아도 유지됨 | 브라우저를 닫으면 삭제됨 |
용도 | 장기적으로 저장할 때 | 일시적인 데이터 저장 (예: 장바구니) |
예제 | 사용자 테마 설정, 로그인 정보 | 장바구니, 폼 입력값 유지 |
장바구니는 "세션 동안만" 유지되는 것이 일반적이므로 sessionStorage를 사용한다.
우선 시작하기 전 각 js 파일이 어떤 용도로 쓰이는지 파악해보자.
index.js (메인 페이지) | shopping-cart.js (장바구니 페이지) | |
사용 목적 | 상품을 장바구니에 추가하고 개수를 업데이트 | 장바구니에 담긴 상품을 표시 |
주요 기능 | "담기" 버튼 클릭 시 세션 스토리지에 저장 | 세션 스토리지에서 상품을 가져와 화면에 표시 |
페이지 이동 | "장바구니로 가기" 버튼 클릭 시 페이지 이동 | "주문하기" 버튼 클릭 시 장바구니 초기화 후 이동 |
그렇다면 최종적으로 세션 스토리지를 이용하여 장바구니 기능을 구현하기위해
필요한 기능들을 정리해보자
▶ index.js 에서 필요한 기능
- Step 1. 장바구니 데이터를 세션 스토리지에서 가져오기
- Step 2. 장바구니 데이터를 세션 스토리지에 저장하기
- Step 3. 장바구니 총 개수 계산하기
- Step 4. 페이지 로드 시 장바구니 개수 업데이트
- Step 5. "담기" 버튼 클릭 시 상품을 장바구니에 추가하는 함수
- Step 6. "장바구니로 가기" 버튼 클릭 시 페이지 이동
▶ shopping-cart.js 에서 필요한기능
- Step 1. 장바구니 데이터를 세션 스토리지에서 가져오기
- Step 2. HTML 리스트에 상품 추가하기
- Step 3. 장바구니 상품 목록을 화면에 표시하기
- Step 4. "주문하기" 버튼 클릭 시 실행하기
- Step 5. 페이지 로드 시 장바구니 목록 표시하기
- Step 6. 이벤트 리스너 설정
세션 스토리지는 Web Storage API를 따르기 때문에
로컬 스토리지와 동일한 방식으로 사용할 수 있다고 했으니
테마 저장에서 배운것과 동일하므로 전체 코드로 작성했다.
// index.js
// 장바구니 개수를 표시할 요소 가져오기
const totalItemCountInCartText = document.querySelector('#total-item-count-in-cart');
/**
* Step 1: 장바구니 데이터를 세션 스토리지에서 가져오기
* 세션 스토리지에서 'cartItems' 키에 저장된 데이터를 불러오고, 없으면 빈 객체 {}를 반환.
*/
function getCartItems() {
return JSON.parse(sessionStorage.getItem('cartItems')) || {};
}
/**
* Step 2: 장바구니 데이터를 세션 스토리지에 저장하기
* JavaScript 객체를 JSON 문자열로 변환하여 'cartItems' 키로 저장.
*/
function setCartItems(cartItems) {
sessionStorage.setItem('cartItems', JSON.stringify(cartItems));
}
/**
* Step 3: 장바구니 총 개수 계산하기
* 장바구니에 담긴 모든 상품의 총 개수를 계산하여 반환.
*/
function getTotalItemCount() {
const cartItems = getCartItems();
let totalItemCount = 0;
for (const itemCount of Object.values(cartItems)) {
totalItemCount += itemCount;
}
return totalItemCount;
}
/**
* Step 4: 페이지 로드 시 장바구니 개수 업데이트
* 장바구니 개수를 세션 스토리지에서 가져와 화면에 표시.
*/
function setInitialValues() {
totalItemCountInCartText.innerHTML = getTotalItemCount();
}
/**
* Step 5: "담기" 버튼 클릭 시 상품을 장바구니에 추가하는 함수
*/
function handleAddClick(button) {
const itemName = button.dataset['itemName']; // 버튼에서 상품 이름 가져오기
const cartItems = getCartItems(); // 현재 장바구니 데이터 불러오기
// 해당 상품의 개수 증가
cartItems[itemName] = (cartItems[itemName] || 0) + 1;
// 업데이트된 장바구니 데이터를 세션 스토리지에 저장
setCartItems(cartItems);
// 장바구니 개수 업데이트
totalItemCountInCartText.innerHTML = getTotalItemCount();
}
/**
* Step 6: "장바구니로 가기" 버튼 클릭 시 페이지 이동
*/
function handleCartClick(e) {
e.preventDefault();
const totalItemCount = getTotalItemCount();
// 장바구니가 비어 있으면 empty-shopping-cart.html로 이동, 아니면 shopping-cart.html로 이동
window.location.href = totalItemCount > 0 ? './shopping-cart.html' : './empty-shopping-cart.html';
}
/**
* Step 7: 이벤트 리스너 설정
*/
function setEventListeners() {
// "담기" 버튼 클릭 이벤트 등록
document.querySelectorAll('.add-to-cart-btn').forEach((button) =>
button.addEventListener('click', () => handleAddClick(button))
);
// "장바구니로 가기" 버튼 클릭 이벤트 등록
document.querySelector('#go-to-shopping-cart').addEventListener('click', handleCartClick);
}
// 페이지 로드 시 실행
setInitialValues();
setEventListeners();
//shopping-cart.js
// 상품 이름을 변환하기 위한 사전(Dictionary)
const dictionary = {
apple: '사과',
orange: '오렌지',
banana: '바나나',
};
/**
* Step 1: 장바구니 데이터를 세션 스토리지에서 가져오기
*/
function getCartItems() {
return JSON.parse(sessionStorage.getItem('cartItems')) || {};
}
/**
* Step 2: HTML 리스트에 상품 추가하는 함수
*/
function addItemToList(name, count) {
const cartItemList = document.getElementById('cart-item-list'); // 리스트 가져오기
const item = document.createElement('li'); // 새로운 리스트 아이템 생성
item.textContent = `${dictionary[name]}: ${count}개`; // 상품명 + 개수 표시
cartItemList.appendChild(item); // 리스트에 추가
}
/**
* Step 3: 장바구니 상품 목록을 화면에 표시하는 함수
*/
function createCartItemList() {
const cartItems = getCartItems();
for (const [key, value] of Object.entries(cartItems)) {
addItemToList(key, value);
}
}
/**
* Step 4: "주문하기" 버튼 클릭 시 실행되는 함수
*/
function handleOrderButtonClick() {
alert('주문이 완료되었습니다!');
sessionStorage.removeItem('cartItems'); // 장바구니 데이터 삭제
window.location.href = './index.html'; // 메인 페이지로 이동
}
/**
* Step 5: 페이지 로드 시 장바구니 목록 표시 (초기화 함수)
*/
function setInitialValues() {
createCartItemList();
}
/**
* Step 6: 이벤트 리스너 설정
*/
function setEventListeners() {
document.querySelector('#order-btn').addEventListener('click', handleOrderButtonClick);
}
// 페이지 로드 시 실행
setInitialValues();
setEventListeners();
'JS' 카테고리의 다른 글
(1)~ (6) Web data storage - 쿠키, 웹 스토리지 정리 (0) | 2025.02.11 |
---|---|
(5) Web data storage - 웹 스토리지 다루기 (0) | 2025.02.07 |
(4) Web data storage - 웹 스토리지 (0) | 2025.02.07 |
(3) Web data storage - 쿠키 (Cookie) 다루는 함수 만들기 (0) | 2025.02.06 |
(2) Web data storage - 쿠키 (Cookie) 추가/수정/삭제 (0) | 2025.02.06 |