전체 글 58

새로고침/뒤로가기 시도 시 모달 띄우기

일기 작성 페이지에서 새로고침, 뒤로가기 등을 시도할 때 이동을 막고 경고 모달을 띄우려고 한다. const router = useRouter();const pathname = usePathname(); // 현재 경로const lastPathname = useRef(pathname); // 이전 경로 저장useEffect(() => { if (pathname !== lastPathname.current) { // 페이지 이동 시도 감지 setShowSaveRestrictionModal(true); // 모달 띄우기 router.replace(lastPathname.current); // 현재 페이지로 강제 이동 → 이동 막기 }}, [pathname, router]);pathnam..

개발/프로젝트 2025.05.27

Tiptap 라이브러리로 텍스트 에디터 만들기

텍스트 에디터를 만들기 위해 Tiptap 라이브러리를 사용해 봤다. Tiptap 라이브러리ProseMirror를 기반으로 한 모던하고 확장 가능한 Rich Text Editor!Next.js, React, Vue, Svelte 등 다양한 프레임워크와 잘 통합되고 마크다운처럼 텍스트를 구조적으로 관리할 수 있는 기능을 제공한다. Tiptap 주요 특징1. ProseMirror 기반- 마크다운처럼 텍스트 구조를 명확하게 파악할 수 있는 트리 기반 편집기2. 확장성- Extension을 통해 기능을 자유롭게 추가하거나 수정 가능3. Headless 구조- 원하는 UI 직접 구성 가능!4. React/Vue 지원- @tiptap/react, @tiptap/vue-3 패키지 사용 Tiptap 구성 요소1. use..

개발/프로젝트 2025.05.27

[자료구조] Queue를 활용한 프린터 우선순위 예제

QueueFIFO (First In First Out) 구조먼저 들어간 데이터가 먼저 나오는 자료구조! Queue의 메서드 enqueue(item)큐에 데이터 추가 (뒤에서 넣음)dequeue()큐에서 데이터 제거 (앞에서 꺼냄)peek()가장 앞에 있는 값 확인 (안 꺼냄)isEmpty()큐가 비었는지 확인size()큐의 크기 확인Queue도 Stack과 마찬가지로 배열을 통해 JavaScript에서 구현할 수 있다.const queue = [];queue.push("A"); // enqueue -> 뒤에서 추가queue.push("B");console.log(queue.shift()); // dequeue → A -> 앞에서 제거console.log(queue); // ["B"]S..

개발/자료구조 2025.05.11

[자료구조] Stack을 이용한 괄호 유효성 검사 예제

스택 (Stack)LIFO (Last In First Out) 구조가장 마지막에 넣은 걸 먼저 꺼내는 자료구조 주요 메서드 push(item)스택에 데이터 추가pop()스택에서 데이터 꺼냄 (마지막 값)peek()가장 위에 있는 값만 확인 (꺼내진 않음)isEmpty()스택이 비었는지 확인length 또는 size()현재 스택의 길이 확인 JavaScript에는 Stack 자료구조가 따로 없지만, 배열을 통해 구현할 수 있다.배열에서 Stack의 메소드를 쓰면 스택처럼 동작하는 것!const stack = [];stack.push(1); // [1]stack.push(2); // [1, 2]console.log(stack.pop()); // 2 꺼냄console.log(stack); // ..

개발/자료구조 2025.05.11

스크롤 기반 싱글 페이지 라우팅 구현하기

포트폴리오 페이지를 만들려는데, 스크롤 기반으로 동작되도록 하고 싶었다.일단 필요한 기능은1. 스크롤 시 경로 변경2. 메뉴 클릭 시 해당 섹션으로 이동3. 특정 페이지(메인, 마지막)에선 메뉴 숨김const mainRef = useRef(null); // 타입 명시const aboutMeRef = useRef(null);const projectRef = useRef(null);const experienceRef = useRef(null);const contactRef = useRef(null);useRef로 각 세션의 DOM을 저장한다.이걸 이용해서 scrollntoView()로 해당 섹션으로 스크롤 하거나, IntersectionObserver로 감시할 수 있다.useRef리액트 컴포넌트에서 DOM ..

개발/프로젝트 2025.04.04

[프로그래머스] 수열과 구간 쿼리 2, 3, 4

수열과 구간 쿼리 2- 정수 배열 arr와 2차원 정수 배열 queries가 주어짐.- queries의 원소는 각각 하나의 query를 나타내며, [s, e, k] 꼴- 각 query마다 순서대로 s ≤ i ≤ e인 모든 i에 대해 k보다 크면서 가장 작은 arr[i]을 찾음- 각 쿼리의 순서에 맞게 답을 저장한 배열 반환 (단, 특정 쿼리의 답이 존재하지 않으면 -1 저장)우선 arr 배열을 s ≤ i ≤ e과 i > k로 필터링을 한다.그 후 필터링 된 배열에서 가장 작은 수를 Math.min() 메소드로 찾으면 됨. (없으면 -1)function solution(arr, queries) { const answer = []; for (const [s, e, k] of queries) { //..

개발/알고리즘 2025.04.03

멋쟁이사자처럼 13기 최종 합격 후기

1년의 휴학 후 복학과 함께 멋쟁이사자처럼 13기에 지원했다.사실 면접 일정 때 여행이 예정되어 있어서 거의 포기하고 있었는데, 면접 스케줄을 조정해주신다고 하셔서 냉큼 지원!!서류1. 다양한 IT동아리 중에서 멋쟁이사자처럼 대학 13기를 선택하고 지원하시게 된 이유를 작성해주세요. (500자 이내)저학년 때부터 이미 멋사를 알고 있었기 때문에, 비전공자를 위한 동아리라는 점과 해커톤 말고도 아이디어톤이 있어서 사용자를 위한 서비스를 직접 기획까지 할 수 있는 동아리라는 점에서 멋쟁이사자처럼에 지원하게 됐다고 썼다.2-2. 위의 파트를 선택한 이유와 관련 경험을 해본 적이 있는지, 그리고 이 파트에 지원하기 위해 과거 또는 현재에 노력하고 있는 것이 있는지 작성해주세요. (500자 이내)프론트엔드 파트로..

대외활동 2025.03.23

[리팩토링] 새로고침 해도 검색 결과가 남아있도록 하기

// 검색 버튼 클릭 시 실행const searchHandler = () => { if (!selectedProvider) globalSearch("전체", selectedTag, selectedTerm); else globalSearch(selectedProvider, selectedTag, selectedTerm); // 통합 검색의 경우 통합 검색 페이지로 이동 if (type === "header") { router.push(`/global-search`); }};기존에는 배급사와 입력한 태그, 입력한 검색어를 바탕으로 globalSearch를 호출해서 검색 API를 호출했었다.이렇게 호출해서 스토어에 검색어들도 저장해놓고, 이걸 다시 불러와서 검색창에 적용해놨..

개발/프로젝트 2025.02.28

Zustand로 API 호출 및 상태 관리하기

Zustand를 사용해서 웹툰 관련 상태와 API 호출 함수들을 관리하는 스토어인 WebtoonStore.ts를 작성해 보았다.Zustand는 React 애플리케이션에서 전역 상태 관리를 쉽게 할 수 있도록 도와주는 경량 라이브러리이다. import { create } from "zustand"; interface WebtoonState { webtoons: WebtoonData[]; // 웹툰 목록 tagList: Tag[]; // 태그 목록 selectedProvider: string; // 배급사 selectedTag: string; // 검색 태그 selectedTerm: string; // 검색어 selectedTagIds: number[]; // 선택한 태그 selectedTags..

개발/프로젝트 2025.02.28

Tailwind CSS + SCSS로 반응형 구현하기

기존 Tailwind CSS를 사용하고 있었고, 모바일뷰, 태블릿뷰, 데스크탑뷰 이렇게 3개의 반응형을 구현해야 했다.멘토님께서 BP가 많아서 복잡해질 가능성이 있다고, 아예 뷰마다 컴포넌트를 분리하라고 하셨는데제대로 된 방법을 몰라서 그런지 코드 중복이 너무 많아졌고, 유지보수에도 문제가 있을 것 같았다.그래서 또 알려주신 방법이, Tailwind CSS와 SCSS를 함께 사용하는 것!return ( {/* 인기 웹툰 */} 인기 웹툰 {breakpoint === "mobile" ? ( {popularDa..

개발/프로젝트 2025.02.25