이하진HAJIN LEE

Full-Stack Developer

화면이 아니라, 매장 운영 흐름이 끝까지 이어지는지 확인하는 개발자입니다.

Full-Stack Developer · Open to opportunities

화면 구현에서 끝내지 않고,
운영 흐름과 데이터가 실제로 연결되는지 확인합니다.

요구사항을 실제 사용 흐름으로 바꾸고, 문제가 생기면 책임 계층까지 확인합니다. 검증하지 못한 기능은 완료라고 말하지 않습니다.

설계
  • Figma 디자인 시스템
  • 화면 · 상태 Variant
  • 운영 정책 · 우선순위
구현
  • React / Vite
  • Spring Boot · MyBatis
  • MySQL · SQL View
identity.ts
// ~/portfolio/identity.tsexport const me = {  name:      '이하진',  role:      'Full-Stack Developer',  domain:    '매장 운영 · 관리자 시스템',  principle: '보이는 것과 보장되는 것을 구분한다',  available: true,}
maintypescriptUTF-8Ln 8, Col 2
8.020.43s
Dashboard API
실 DB 기준
10 6
DB Queries
대시보드 1회 요청당
4
Sales APIs
조회 책임 분리
8
Verification Stages
UI → Mock → … → Device
01About

React 화면부터 Spring Boot·MySQL의 데이터 흐름까지 연결합니다. 화면이 보이는가보다 사용자가 이 데이터를 믿고 업무에 쓸 수 있는가를 기준으로 구현과 검증 범위를 정합니다.

02What Sets Me Apart
01

빌드 성공과 기능 성공을 구분합니다

빌드와 컴파일만으로 기능 완료를 판단하지 않습니다. UI부터 실 DB·브라우저·장치까지 8단계 검증 기준으로 확인합니다.

02

보장하지 못하는 것을 완료라고 적지 않습니다

버튼이 동작해도 실제 연동을 검증하지 못했다면 완료라고 기록하지 않습니다. Case Study의 미검증 항목은 현재 상태 그대로 공개합니다.

03

문제가 생기면 책임 계층까지 따라갑니다

화면의 문제를 임시값으로 덮지 않습니다. React부터 API·Service·SQL·실제 View까지 추적해 데이터 계약의 원인을 확인합니다.

03Collaborator Feedback

집사냥 프로젝트를 함께 개발한 주 개발자의 피드백

“요청받은 작업을 처리하는 데 그치지 않고 서비스 전반의 사용자 경험을 함께 고민했습니다. 데이터 표현 방식과 화면 구성의 개선안을 제안하고, 디자인 작업과 구현 수정까지 연결했습니다. 또한 사용자 시점의 검증을 통해 엣지 케이스와 문구의 어색함까지 점검하며 서비스 완성도를 높였습니다.”

04Experience
2026.07 — 08

관리자 도메인 담당 · ASAK 팀 프로젝트 (최종 2인)

주문·메뉴·품절·결제·매출·대시보드와 영수증 출력 연계를 담당했습니다. 새 화면을 늘리기보다 메뉴 → 품절 → 주문 → 결제 → 취소 → 매출 → 대시보드 흐름을 API·DB까지 검증했습니다.

ReactViteZustand Spring BootMyBatisMySQL FigmaBruno
05Projects
assets/images/asak-admin.png 관리자 대시보드 캡처
키오스크 · 매장 운영
ASAK (Kiosk + Admin)
2026.07.01 — 08.21 · 팀 프로젝트 · 관리자 도메인 담당

주문·메뉴·품절·결제·매출을 연결한 샐러드 키오스크와 관리자 시스템입니다. 매출 API를 조회 책임별로 분리하고, 대시보드 응답을 실 DB 기준 8.02초에서 0.43초로 개선했습니다.

팀 프로젝트AdminFull Stack
06Case Study — ASAK
01Overview

매장에서 계속 열어 두는 업무 도구를 만들었습니다

관리자 페이지는 감상하는 서비스가 아니라 직원이 계속 열어 두고 쓰는 도구입니다. 지금 어떤 주문을 처리해야 하는지, 어떤 메뉴를 팔 수 없는지, 오늘 매출이 어떤지를 빠르게 판단할 수 있어야 합니다. 그래서 기능을 설계할 때 항상 화면 다음의 행동을 먼저 봤습니다.

ReactViteZustandAxios Spring BootMyBatisMySQL SQL ViewFigmaBruno
02The Challenge

실제 데이터를 붙이자 설계 단계에서 안 보이던 문제가 나왔습니다

  • 요구사항은 “관리자가 품절 상태를 관리한다” 한 줄. 메뉴만인지, 재료까지인지, 옵션도 대상인지 정의되지 않았다.
  • API 문서에는 있는 컬럼이 실제 DB에 없거나, 기존 View가 최신 테이블 구조를 반영하지 않았다.
  • 주문이 없는 시간대는 DB에 행 자체가 없어, 차트에서 “매출 0원”과 “조회 누락”을 구분할 수 없었다.
  • 매출 질문(오늘/이번 달/일별/시간대/취소 영향)이 서로 달라 하나의 DTO로 답하면 응답이 계속 커졌다.
  • 실 DB를 연결하자 대시보드 조회가 약 8초 걸렸다. 로딩 스피너로 덮을 시간이 아니었다.
03Approach

화면에서 우회하지 않고 책임을 다시 나눴습니다

  • 품절은 데이터 계층과 화면 정책을 분리했다. vw_soldout_catalog View로 메뉴·재료·옵션을 같은 구조로 제공하되, 관리자 화면에는 운영자가 자주 다루는 메뉴와 재료만 노출했다. 확장 여지는 데이터에 남기고 화면은 단순하게 뒀다.
  • 매출은 화면별이 아니라 조회 책임별로 API를 나눴다. 집계의 변경 이유가 서로 다르기 때문이다.
    sales-api.http
    GET /api/admin/sales/summary?period=month
    GET /api/admin/sales/monthly?year=2026
    GET /api/admin/sales/daily?from=2026-07-01&to=2026-07-31
    GET /api/admin/sales/daily/time-slots?date=2026-07-20&intervalMinutes=30
  • 없는 데이터는 DB에 만들지 않고 Service에서 표현했다. 발생하지 않은 사실을 저장하는 대신, 영업시간 10:00~22:00 기준으로 빈 구간을 Service가 0으로 채워 연속된 시간축을 반환하게 했다.
    responsibility
    DB        실제 주문이 발생한 사실만 저장
    Service   영업시간 기준으로 빠진 시간대를 생성
    API       연속된 시간축으로 반환
    Frontend  그대로 차트 표현
  • 주문 상태는 UI 버튼이 아니라 서버 상태 전이를 기준으로 붙였다. RECEIVED → PREPARING → COMPLETED와 취소 가능 조건을 먼저 확인하고 화면을 연결해, 완료된 주문에 제조 시작을 다시 누를 수 없게 했다.
  • 대시보드는 추측 대신 측정으로 줄였다. 필요한 값을 DB 집계가 필요한 것 / 이미 가진 데이터로 계산 가능한 것 / 중복 조회 / 실제로는 불필요한 것으로 다시 나눴다.
  • 렌더링 전용 값은 응답에서 걷어냈다. fill, barHeight를 제거하고 차트 라이브러리가 업무 데이터만 받아 높이를 계산하게 했다.
04Outcome

대시보드 응답 8.02초 → 0.43초

최초 · db_calls 108.02s
조회 통합 · db_calls 63.81s
View 재작성 시도 → 실측 후 원복4.40s
최근 주문 조회를 베이스 테이블 직접 조회로0.43s

기대와 달리 느려진 View 변경은 실측을 근거로 되돌렸습니다. 무엇이 맞았는지만큼 왜 어떤 방법을 버렸는지도 남겼습니다.

완료 기준을 8단계로 나눴습니다

기능 UIMockAPI BackendDB실 DB 브라우저장치
품절 관리완료완료완료완료완료완료완료해당 없음
주문 Live · 상태 전이완료완료완료완료완료완료완료해당 없음
메뉴 CRUD · 영양/재료완료완료완료완료완료완료완료해당 없음
매출 4종 API완료완료완료완료완료완료완료해당 없음
대시보드완료완료완료완료완료완료완료해당 없음
주문 취소완료완료완료완료완료완료완료해당 없음
결제 환불 연동완료완료완료미검증미검증미검증미검증해당 없음
영수증 출력 (RTOS)완료완료완료완료완료미검증해당 없음미검증
검증 완료 미검증 / mock 해당 없음

미검증으로 남긴 것 — 환불 흐름 일부는 실제 결제 서버가 아니라 mock에 연결돼 있습니다. 영수증 출력은 device_event API까지 구현했지만 실제 프린터 장치 검증은 하지 못했습니다. 버튼이 눌린다는 이유로 완료라고 적지 않았습니다.

05Highlights
  • vw_soldout_catalog — 메뉴·재료·옵션을 같은 구조로 통합한 품절 View
  • 매출 summary / monthly / daily / time-slots 4개 책임별 API
  • intervalMinutes=30|60 으로 시간대 차트 단위 전환
  • 영업시간 기준 빈 시간대 0 보정, 미래 날짜·미래 월 범위 제외
  • 주문 상태 전이 기반 액션 노출, 취소 실패 사유 세분화
  • 운영 데이터 보호를 위한 메뉴 soft delete
  • 로컬 정적 파일 대신 Cloudinary URL 기반 이미지 흐름
  • device_event 폴링 구조로 Web과 RTOS 장치를 느슨하게 결합
  • Daily · Entry · WBS · 회의록을 연결한 작업 기록 체계
07Skills
Frontend
  • React · JavaScript
  • Vite · React Router
  • Zustand · Axios
  • PWA
Backend
  • Java · Spring Boot
  • Gradle
  • MyBatis
Data
  • MySQL · SQL View
  • CSV / Seed Data
  • Bruno
Design & Ops
  • Figma · Cloudinary
  • Git · GitHub
  • WBS · Worklog

이 사이트는 프레임워크와 빌드 도구 없이 vanilla HTML · CSS · JS로 만들었습니다. 라이트/다크 전 항목 명도 대비 WCAG AA 이상, 가로 오버플로 없음. 소스

08Contact

이하진 · Full-Stack Developer · 2026