본문 바로가기
728x90
반응형

source-code229

Feature-Sliced Design(FSD) 도입기 최근 사내 core-package의 FE 파트 폴더 아키텍처에 Feature-Sliced Design(FSD)를 도입했습니다. 해당 FE 서비스는 1) 전통적인 React 폴더 구조 → 2) 클린 아키텍처(헥사고날 아키텍처) → 3) FSD 지금까지 이렇게 총 3번의 구조 변경을 겪었으며, 각 단계에서 느꼈던 문제점과 해결 방안을 공유하고자 합니다. 1. 전통적 폴더 구조처음 프로젝트를 구성할 당시, 가장 일반적이고 전통적인 폴더 구조 형태를 따랐습니다.src/├── api/│ ├── userApi.ts│ └── productApi.ts├── components/│ ├── Header.tsx│ ├── Footer.tsx│ ├── UserProfile.tsx│ └── ProductLi.. 2024. 8. 3.
Drag&Drop 컴포넌트에서 클릭 이벤트와 드래그 이벤트 분리하기 BackgroundDrag&Drop이 가능한 div 컴포넌트를 구현해야 했습니다. Drag&Drop의 기본 로직은 단순합니다.해당 요소의 위치 상태를 관리하면서요소를 누르면 Drag가 시작되고, 마우스를 움직이면 위치 상태를 변경하고, 마우스를 떼면 Drag를 멈추면 되겠죠.import { useState, useEffect, useRef } from 'react';interface Props { initialTop: number;}const useVerticalDrag = ({ initialTop }: Props) => { const [isDragging, setIsDragging] = useState(false); const [top, setTop] = useState(initialTop); /.. 2024. 8. 1.
[chrome extension] dynamic import시 Cannot find module 에러 해결하기 Backgroundchrome extension의 content script에서, 다른 모듈을 동적으로 import하고자 했습니다.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import import() - JavaScript | MDNThe import() syntax, commonly called dynamic import, is a function-like expression that allows loading an ECMAScript module asynchronously and dynamically into a potentially non-module environment.developer.mozilla... 2024. 7. 26.
[next js] server component 페이지 route 속도 개선하기 (with streaming) Backgrounds현재 운영 중인 서비스의 관리자 페이지는 Next.js 14 버전으로 구성되어 있습니다. Next.js는 13 버전부터 큰 변화를 겪었는데, 이는 바로 app 디렉터리 내 모든 컴포넌트가 기본적으로 서버 컴포넌트로 동작한다는 것입니다. 이를 활용해, 생성된 가이드 데이터의 상세 페이지를 서버 컴포넌트로 구성했습니다. 서버 컴포넌트를 사용하면 서버에서 데이터를 가져와 HTML을 생성하고, 클라이언트에 완성된 HTML을 반환할 수 있으며 이를 통해 초기 로딩 시간을 단축하고, 사용자 경험을 향상하고자 했습니다.// app/[id]/page.tsx import fetchData from '../lib/fetchData'; export default async function Page({ p.. 2024. 7. 23.
WebComponent에서 styled-components 사용하기 Backgrounds현재 회사에서 개발 중인 제품은 고객사 웹 페이지 위에서 동작하는 다양한 모듈들을 제공하는 형태입니다.이때 고객사 페이지와 독립적인 스타일을 유지하기 위해,별도의 웹 컴포넌트를 생성한 뒤 그 안에서 자체적으로 정의한 스타일이 동작하도록 구현했습니다. https://developer.mozilla.org/en-US/docs/Web/API/Web_components Web Components - Web APIs | MDNWeb Components is a suite of different technologies allowing you to create reusable custom elements — with their functionality encapsulated away from th.. 2024. 7. 10.
[JavaScript] 트리 데이터 구조 변환 시 무한 루프 방지하기 Backgrounds현제 개발 중인 서비스에서는 하나의 가이드 속 다양한 단계(Step)를 표현하기 위해 트리 구조의 데이터를 생성하고 관리하고 있습니다.각 Step은 수행할 작업, 다음 단계(next step)를 포함하는 형태로, 이를 통해 트리 구조를 생성하고 탐색할 수 있습니다. 이때 이러한 자료 구조 형태를 FE에서 UI로 표현해야 했습니다.BackEnd에서는 Step 목록을 단순히 가이드 하위에 존재하는 Step 배열로 반환해주고 있었고 이러한 배열 형태로는 각 node들 간의 부모-자식 관계를 나타낼 수 없었습니다. (index가 순서가 아니니까요) 따라서 FE 측에서 tree형태 UI로 나타낼 수 있도록 입력받은 node 배열을 변환해줘야 했습니다.요구 사항을 좀 더 구체적으로 얘기해 보면... 2024. 7. 9.
팩토리 구현 시, 인스턴스 타입 안전성 확보하기 Backgrounds최근 프로젝트에서 다양한 메시지 핸들러 클래스를 생성하고 관리할 필요가 생겼습니다. 메시지 핸들러는 프로젝트 내 모듈들 간의 통신을 담당하며각각의 메시지 핸들러는 자신이 해야할 일(action)과 데이터(payload), 실제 송수신 방법에 대한 메서드를 구현하고 있었습니다.(ex "사이드 패널 활성화 메시지 핸들러", "팝업 활성화 메시지 핸들러", "타겟 정보 데이터 전송 메시지 핸들러") 이때 앱 내 메시지 핸들러의 종류가 점차 많아짐에 따라,각 메시지 타입(action)에 대응하는 구체적인 메시지 핸들러 클래스들을 손쉽게 생성하고 관리하기 위해 팩토리 패턴을 적용했습니다.import { MessageHandlerPort, Message,} from "@/application.. 2024. 7. 5.
[jest] waitFor을 통한 비동기 함수 테스트 Backgrounds비동기 함수에 대한 단위 테스트를 작성해야 할 때가 있습니다.function someTask(): Promise { return new Promise((resolve) => resolve(true));}it('비동기 함수 테스트', () => { const result = someTask(); expect(result).toBe(true);}); 위와 같이 테스트 코드를 작성하면... 당연히 실패합니다! someTask는 Promise를 반환하는 비동기 함수이므로expect 구문이 실행되는 시점에는, 해당 값은 Promise이기 때문이죠. function someTask(): Promise { return new Promise((resolve) => resolve(true));.. 2024. 6. 23.
[jest] test.each를 통해 여러 입력값 테스트 간결하게 구현하기 Backgrounds동일한 테스트를, 입력값만 바꾸어서 실행해야 할 때가 있습니다. 데이터를 특정 형태로 변환하는 함수들이 대표적인 경우겠죠. 예를 들어, 입력받은 ms를 시간과 분 으로 분리하는 함수가 있습니다.import { convertMsToHoursAndMinutes } from '@/utils/time'; it('ms => 시간/분 변환 함수 동작 테스트', () => { const ms = 1800000; // 30분 const { hours, minutes } = convertMsToHoursAndMinutes(ms); expect(hours).toBe(0); expect(minutes).toBe(30); }); 1800000ms(30분)을 입력받으면, 0시간 30분 을 반환하는지 테스트 .. 2024. 6. 13.
728x90
반응형