FrontEnd Develop 77

MJS 식단 페이지 리팩토링 기획안

1. 기획 배경 — “하나의 페이지에 모든 걸 넣은 게 문제였다” 처음 식단 페이지를 만들 때는 MVP 수준으로 단일 컴포넌트에모든 로직(데이터 fetch, 상태, 날짜 이동, UI)을 넣어 빠르게 완성했어요. 하지만 그 구조는 다음과 같은 문제를 드러냈습니다. 모바일에서도 데스크톱용 주간 테이블이 그대로 표시되어 가독성이 나쁨브라우저 크기에 따라 한 컴포넌트 안에서 조건문이 난무함React Query / 상태 / 날짜 계산 로직이 뒤섞여 유지보수가 어려움간단한 변경도 “하루 걸리는 구조”가 됨 이 시점에서 UI 관심사와 데이터 로직을 분리하고, 기기별 UX를 맞추자는 기획이 시작됐습니다. 2. 리팩터링 방향성 — “역할 단위로 쪼갠다”우리는 React의 단일 책임 원칙(Single Responsib..

MJS : 학사일정 컴포넌트 및 자유게시판 HOT 게시물 컴포넌트 연동 문서

대상: 신입/합류 개발자목표: 두 위젯을 빠르게 이해하고, 팀의 코드/디자인 규칙에 맞춰 안정적으로 개발·확장할 수 있도록 한다.위젯학사일정 텍스트 전용 패널(달력 그리드 없음)자유게시판 HOT 게시물 리스트(로그인 게이팅)0. 스택 & 전제Next.js/React 18, TypeScript (strict), Tailwind CSS, Zustand(전역 인증), react-icons(아이콘)디자인 토큰: mju-primary, grey-40 등 (Tailwind theme.extend.colors에 등록되어 있어야 함)API 모듈: getAcademicEvents, getBoards (서버 응답이 케이스별로 달라질 수 있음 → 안전 파서 필요)// tailwind.config.{js,ts} 예시expor..

MJS 광고 캐러셀 & 실시간 검색 순위 집계 Component 설계 가이드

1. 광고 캐러셀 (AdCarousel)설계 의도학교/동아리/행사 홍보용 이미지를 자동 순환으로 보여주는 컴포넌트.hover 시 자동 재생을 멈추어 UX를 개선.접근성(aria-label, 버튼 제어) 고려.기술적 포인트상태 관리index: 현재 활성화된 슬라이드 인덱스를 관리.timerRef: setTimeout 관리용 ref, 언마운트 시 clearTimeout 보장.hoverRef: 마우스 오버 여부를 추적하여 autoplay 제어.useMemoslides = images가 주어지면 외부 이미지, 없으면 DEFAULT_IMAGES 사용.useMemo를 사용해 불필요한 재계산 방지. (단, 단순 배열이라 성능상 큰 차이는 없으므로 가독성/안정성을 위해 선택적으로 사용.)타입 지정images 배열은 옵..

MJS 명대뉴스 반응형 구현

대상 코드: NewsCard 컴포넌트 (article, aria-labelledby, aspect-ratio, onError 캐스팅, React.memo)GPT의 흐름을 파악하기 위한 “왜 이렇게 썼는지”를 끝까지 파고드는 설명형 레퍼런스입니다. 시맨틱 태그부터 접근성, 이미지 비율, 이벤트 타입 캐스팅, 메모이제이션까지 한 번에 훑습니다.1) 는 무엇이고, 언제 쓰나?시맨틱 태그(의미 있는 HTML 태그) 중 하나로, 블로그 글/뉴스 카드/피드 아이템처럼 독립적으로 의미가 성립하는 콘텐츠 묶음을 감싸는 데 씁니다.특징문서 내에서 단독 재사용 가능한 콘텐츠 블록.RSS, 북마크, 공유 등 콘텐츠 단위로 식별되길 원하는 영역.내부에 제목()이 있는 것이 일반적.언제 대신 ?이 카드 하나가 하나의 글/뉴스..

MJS 반응형 리빌드 & 방송국 페이지 성능 튜닝

목표 요약모바일: 캐러셀(드래그) 탭 + 상단 여백 축소 + Compact 프로필 + 날씨 비표시데스크탑: 탭 중앙정렬 유지 + Full 프로필 + 날씨 표시 + 방송국 3×3 그리드 고정성능: iframe 즉시로딩 제거(썸네일 → 클릭 시 임베드), 불필요 렌더/네트워크 최소화, LCP/TTI 개선0. 변경 전 주요 Pain Points탭이 모바일에서 줄바꿈/과밀 → 터치 정확도·가독성 저하.Navbar–Header–SearchBar 간격이 모바일에서 과도.Profile/Weather가 모바일에서도 동일 무게로 렌더 → 초기 비용↑.방송국 페이지에서 iframe 다건 즉시 로딩 → 초기 렌더/네트워크 폭증, TTI 지연.데스크탑 초대형 해상도에서 4열까지 늘어나 일관된 3×3 레이아웃 유지 실패.1. ..

React Router Link 클릭 시 기본 이동 동작 제어하기

상황비로그인 사용자가 클릭하면 로그인 페이지로 보내는 기능을 구현하려고 했습니다.그래서 이렇게 코드를 작성했습니다.const handleBoardClick = () => { if (!isLoggedIn) navigate('/login');};그리고 에 붙였죠.검색게시판그런데… 결과는?비로그인 상태에서도 /board 페이지로 가버리는 현상이 발생했습니다.내 함수가 실행되긴 했지만, 결국 Link의 기본 이동이 이겨버린 거죠.이유는 Link tag의 기본적인 anchor 작동이 사설함수를 이긴다는 것을 간과한 것입니다. 와 태그의 동작과 똑같게 작동하며 취급되기에 기본 anchor Active를 합니다.그렇기에 사설함수의 작동이 무시되는 것입니다.자세한 원인 분석여기서 중요한 사실은 가 단순한 React..

Zustand 함부로 가져오지 않는 것에 대하여

프론트엔드에서 전역 상태 관리 라이브러리를 사용할 때, 흔히 하는 실수 중 하나가 그냥 전부 가져오기입니다.Zustand 역시 간단하고 직관적이지만, 성능과 보안 측면에서 "필요한 값만" 가져오는 습관이 매우 중요합니다.이번 글에서는 제가 겪은 상황을 중심으로, 왜 selector 패턴(useAuthStore((s) => s.isLoggedIn))을 썼는지, 그리고 검색게시판처럼 민감한 정보 접근에서 프론트에서 1차적으로 예방하는 방법까지 정리합니다.1. 상황프로젝트에서 검색게시판(Board) 페이지는 로그인한 사용자만 접근 가능백엔드에서 인증 검사를 하지만, 프론트에서도 1차적으로 접근을 차단하여 UX와 보안을 강화하고 싶음전역 상태 관리(Zustand)를 이용해 isLoggedIn 값을 글로벌로 관리..

MJS _ 명대방송국 연계

1. 페이지네이션 설계안 요구사항 한 페이지에 9개의 데이터를 보여준다.페이지 하단에 점(dot) 형태의 페이지네이션 UI를 표시한다.한 번에 최대 5개의 점만 표시한다.다음/이전 버튼으로 페이지를 이동하면 점이 슬라이드처럼 움직인다.점을 클릭하면 해당 페이지로 이동한다. 2. 기본 프로토타입 구현 초기 구현은 단순하게 현재 페이지 기준으로 start/end 계산 후 점 배열을 만들고,이전/다음 버튼, 점 클릭 시 onChange()로 페이지 변경 요청을 하는 구조였습니다. type Props = { currentPage: number; totalPages: number; onChange: (page: number) => void; window?: number; // 보이는 점 개수};export..

Set 자료구조로 사이드바 UX 개선하기

예전 프로젝트에서 사용자 친화적인 사이드바(Sidebar)를 만들기 위해 다양한 UI/UX 개선을 적용했다. 진행하고 있는 AI TUTOR 프로젝트의 SIDEBAR의 UI/UX에도 개선이 필요했다. 1. Hovering을 하고 있지도 않은데, Hovering 시 바뀌는 스타일이 불필요하게 적용됨 2. toggling 반응속도가 느림 이때 쓸 수 있는 방법은 JavaScript의 Set 자료구조를 활용한 열림/접힘 상태 관리 최적화가 있었다. 이 문서는 해당 리팩토링 과정과 그 이유, 그리고 부수적인 UI 버그 해결 방법까지 총망라한 정리이다.1. 기존 사이드바 상태 관리 방식초기에는 각 폴더의 노트 리스트 열림 여부를 다음과 같이 관리했다:const [isNoteOpen, setIsNoteOpen] =..

백엔드에서 요구한 데이터 구조에 맞춘 API 타입 설계

"기존 백엔드에서 요구한 데이터 구조를 기반으로, 프론트엔드 협업을 위한 API 데이터 타입을 어떻게 정의하고 왜 그렇게 구성하는가?"스스로에게 정말 많이 던졌던 질문이다.한번 파헤쳐보자!1. 실제 백엔드에서 주는 /notices API 응답 구조HTTP Method: GETBody 없음 (GET 요청이기 때문에 일반적으로 body에 데이터를 담지 않음)모든 데이터는 query parameter로 전달됨{ "content": [ { "title": "[공지] ...", "date": "2025.04.08", "category": "career", "link": "https://..." } ], "pageable": { "pageNumber": 0,..