[#62] 용돈 기입장 프로젝트 (feat. React)

2025. 4. 28. 13:32·LG 유플러스 유레카 SW/React

✨ 프로젝트: 용돈 기입장

"용돈 기입장"은 간단히 수입과 지출을 관리할 수 있는 React 기반 웹 어플리케이션입니다.

거래 내역 추가, 삭제 기능과 함께 잔액, 총 수입, 총 지출을 한눈에 확인할 수 있습니다.

https://nue-os.github.io/allowance-book/

 

용돈 기입장

 

nue-os.github.io

 

🛠️ 사용 기술

  • React v19 (Vite)
  • Redux Toolkit (상태 관리)
  • CSS Module (스타일 관리)
  • localStorage (데이터 저장)
  • gp-pages (배포)

 

👩🏻‍💻 개발 사항

1️⃣ 거래 내역 입력 폼 구현

텍스트, 금액, 거래 유형(수입/지출) 입력

<div className={css.inputForm}>
    <div className={css.textWrap}>
      <InputField
        label="텍스트"
        id="contents"
        value={trasactionText}
        placeholder="내용을 입력해 주세요."
        onChange={handleContentsChange}
      />
      {errorText && <p className={css.error}>{errorText}</p>}
    </div>

    <div className={css.radioGroup}>
      <RadioButton
        id="income"
        name="type"
        value="income"
        label="수입"
        checked={transactionType === 'income'}
        onChange={handleRadioChange}
      />
      <RadioButton
        id="expense"
        name="type"
        value="expense"
        label="지출"
        checked={transactionType === 'expense'}
        onChange={handleRadioChange}
      />
    </div>
    <div className={css.amountWrap}>
      <InputField
        label="금액"
        id="amount"
        value={transactionAmount}
        placeholder="금액을 입력해 주세요."
        onChange={handleAmountChange}
      />
      {errorAmount && <p className={css.error}>{errorAmount}</p>}
    </div>

    <button className={css.button} onClick={handleSubmit}>
      거래 추가
    </button>
</div>

 

2️⃣ 금액 입력 포맷팅

금액을 입력할 때 ₩ 기호와 천 단위(,) 표시를 자동으로 표시

const rawValue = e.target.value.replace(/[^0-9]/g, '') // 숫자인지 검증

if (rawValue === '') {
  setTransactionAmount('')
  return
}
const formattedAmount = '₩ ' + Number(rawValue).toLocaleString()

 

3️⃣ 입력값 검증

내용이나 금액이 비어있을 때 등록이 안 되도록 입력 검증 로직을 추가

let hasError = false;

if (trasactionText === '') {
  setErrorText('내용을 입력해주세요!');
  hasError = true;
} else {
  setErrorText('');
}

if (transactionAmount === '') {
  setErrorAmount('금액을 입력해주세요!');
  hasError = true;
} else {
  setErrorAmount('');
}

if (hasError) return;

 

4️⃣ 모달 구현

거래를 삭제할 때 실수로 지우는 것을 방지하기 위해 삭제 전 모달 확인 추가

  • Modal 컴포넌트를 재사용 가능하도록 구현
// Modal.jsx
const Modal = ({ onClose, children }) => {
  return (
    <div className={css.modal}>
      <div className={css.modalCon}>
        <button className={css.closeBtn} onClick={onClose}>
          X
        </button>
        {children}
      </div>
    </div>
  )
}
  • 모달 오픈 상태 관리
// TransactionItem.jsx
const [isModalOpen, setIsModalOpen] = useState(false)

const handleModalOpen = () => setIsModalOpen(true)
const handleModalClose = () => setIsModalOpen(false)


// ... 중략
{isModalOpen && (
    <Modal onClose={handleModalClose}>
      <p>삭제하시겠습니까?</p>
      <div className={css.btnWrap}>
        <Button color="white" text="취소" onClick={handleModalClose} />
        <Button color="red" text="확인" onClick={() => handleRemove(id)} />
      </div>
    </Modal>
)}

 

5️⃣ 데이터 관리

  • Redux Toolkit을 사용해서 거래 내역을 전역 상태로 관리
export const transactionsSlice = createSlice({
  name: 'transactions',
  initialState: {
    transactions: JSON.parse(localStorage.getItem('myData')) || [],
  },
  reducers: {
    addTransaction: (state, action) => {
      state.transactions.push(action.payload)
    },
    removeTransaction: (state, action) => {
      state.transactions = state.transactions.filter(
        transaction => transaction.id !== action.payload
      )
    },
  },
})
  • LocalStorage에 저장해서 새로고침해도 데이터가 유지되도록 관리

  • 거래 추가 시: localStorage와 Redux 둘 다 업데이트
const addItem = useCallback(
    item => {
      try {
        const list = getList()
        const id = list.length > 0 ? list[list.length - 1].id + 1 : 1
        const newItem = { ...item, id }
        const newList = [...list, newItem]
        localStorage.setItem(key, JSON.stringify(newList))
        dispatch(addTransaction(newItem))
      } catch (err) {
        console.log('[error] ', err)
      }
    },
    [key, getList]
)
  • 거래 삭제 시: localStorage와 Redux 둘 다 삭제
const removeItem = useCallback(
    id => {
      try {
        const list = getList()

        const filterdList = list.filter(item => item.id !== id)
        localStorage.setItem(key, JSON.stringify(filterdList))
        dispatch(removeTransaction(id))
      } catch (err) {
        console.log('[error] ', err)
      }
    },
    [key, getList]
)

 

6️⃣ 금액 합계 계산 기능

총 잔액, 수입, 지출 계산

// 총 수입
export const calIncome = transactions =>
  transactions.filter(t => t.type === 'income').reduce((acc, t) => acc + t.amount, 0)

// 총 지출
export const calExpense = transactions =>
  transactions.filter(t => t.type === 'expense').reduce((acc, t) => acc + t.amount, 0)

// 총 잔액
export const calBalance = transactions => calIncome(transactions) - calExpense(transactions)

 

7️⃣ 공통 Button 컴포넌트

모달이나 폼 제출 버튼처럼 여러 곳에서 버튼을 사용해야 하기에 버튼 컴포넌트 분리

  • color prop을 받아서 버튼 색상 스타일을 다르게 적용
const Button = ({ color = 'primary', text, onClick }) => {
  const buttonClass = `${css.button} ${css[color]}`;
  return (
    <button className={buttonClass} onClick={onClick}>
      {text}
    </button>
  );
};

 

🪄 완성 코드

https://github.com/nue-os/allowance-book

 

GitHub - nue-os/allowance-book: 용돈 기입장

용돈 기입장. Contribute to nue-os/allowance-book development by creating an account on GitHub.

github.com

 

728x90
반응형

'LG 유플러스 유레카 SW > React' 카테고리의 다른 글

[#64] TanStack Query(React Query) 사용해보기  (0) 2025.04.29
[#63] 날씨 오픈 API 연동  (1) 2025.04.28
[#61] Redux란  (1) 2025.04.24
[#60] React - Hook + 성능 최적화 정리  (0) 2025.04.23
[#59] React 쇼핑몰 - Shop 페이지 상품 필터링/정렬 + 페이지네이션  (0) 2025.04.22
'LG 유플러스 유레카 SW/React' 카테고리의 다른 글
  • [#64] TanStack Query(React Query) 사용해보기
  • [#63] 날씨 오픈 API 연동
  • [#61] Redux란
  • [#60] React - Hook + 성능 최적화 정리
nueos
nueos
  • nueos
    nueos 공부 기록
    nueos
  • 전체
    오늘
    어제
    • 분류 전체보기 (193)
      • 해커톤 (1)
      • 네이버 BoostCamp (6)
      • LG 유플러스 유레카 SW (5)
        • React (21)
        • TypeScript (2)
        • JavaScript (2)
        • HTML+CSS (5)
        • Spring (7)
        • Java (6)
        • SQL (2)
        • Algorithm (8)
        • CX (6)
        • Git (2)
        • 프로젝트 (2)
        • 스터디 (9)
        • 과제 (8)
        • 특강 (1)
      • React (3)
      • Next (0)
      • Javascript (2)
      • HTML (2)
      • CSS (9)
      • Algorithm (6)
      • Database (0)
      • OS (13)
      • C++ (24)
      • Python (1)
      • jQuery (1)
      • Django (1)
      • Git (1)
      • 개발 지식 (3)
      • 정보 보안 (22)
      • 포렌식 (1)
      • 암호 (2)
      • 기타 (4)
      • 패스트캠퍼스 FE 프로젝트십 (5)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

    스택
    Stack
    완전 탐색
    힙
    제주해커톤
    큐
    기술로바꾸는세상
    디지랩챌린지
    디지털혁신
    exhaustive search
    Queue
    heap
    제주지역혁신플랫폼지능형서비스사업단
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
nueos
[#62] 용돈 기입장 프로젝트 (feat. React)
상단으로

티스토리툴바