분류 전체보기 369

[ 디자인 시스템 ] (3) 라이브러리 버전 관리

모노레포 버전 관리: Changeset 자동화 모노레포에서 수십 개의 패키지 버전을 수동으로 관리하는 건 불가능에 가깝습니다. 이번 글에서는 Changeset을 활용한 자동 버전 관리 시스템을 구축하는 방법을 설명합니다. Conventional Commits와 연동하여 커밋 한 번으로 버전 결정부터 배포까지 이어지는 흐름을 만들어보겠습니다. 수동 관리의 한계 우리가 겪었던 문제들 자동화 이전에는 릴리즈 담당자가 엑셀이나 메모장에 변경 사항을 적어가며 버전을 올렸습니다. 이 과정에서 휴먼 에러는 필연적이었습니다. 문제점 상세 내용 ..

je개발 회고 2026.01.12

[ 디자인 시스템 ] (2) 모노레포 의존성 관리

모노레포 의존성 관리: ESLint Boundaries 활용 이번 글에서는 ESLint Boundaries 플러그인을 활용한 모노레포 의존성 관리 전략을 다룹니다. 단순히 "조심해서 코딩하자"는 약속을 넘어, 코드 레벨에서 의존성 규칙을 강제하고 아키텍처를 사수하는 구체적인 방법을 알아보겠습니다. 왜 의존성 관리가 중요한가 모노레포가 가지는 잠재적 위험 모노레포 환경에서는 패키지 간의 소스 코드 접근이 매우 자유롭습니다. 이는 장점이지만 동시에 치명적인 단점이 될 수 있습니다. 무분별한 import는 다음과 같은 문제를 야기합니다. // utils/src/format.tsimport { Button } from '@des..

je개발 회고 2026.01.12

[ 디자인 시스템 ] (1) 모노레포 아키텍처

모노레포 아키텍처: 레이어 기반 패키지 설계지난 글에서 모노레포 도입 배경을 다뤘다면 이번에는 구체적인 아키텍처 설계를 살펴봅니다. 패키지 간 의존성을 어떻게 구조화해야 하는지, 그리고 왜 단방향 의존성 흐름이 유지보수의 핵심인지 설명합니다.레이어 아키텍처 (Layered Architecture)설계 원칙디자인 시스템 내부의 패키지들은 엄격한 단방향 의존성을 갖도록 레이어로 구분했습니다. 이 구조는 복잡도를 낮추고 예측 가능한 시스템을 만드는 데 목적이 있습니다.하위 레이어는 상위 레이어를 참조할 수 없음 - 순환 참조(Circular Dependency)를 원천 차단합니다.같은 레이어 간 참조 지양 - 각 패키지의 독립성을 최대한 보장합니다.상위 레이어만 하위 레이어를 참조 - 데이터와 로직의 흐름을 ..

je개발 회고 2026.01.12

[ 디자인 시스템 ] (0) 모노레포로 사내 라이브러리 만들기

모노레포 관리 가이드: 의존성부터 배포까지모노레포 환경에서 디자인 시스템을 구축하며 마주했던 난관과 이를 극복하기 위해 수립한 해결 전략을 공유합니다. 의존성 제어부터 버전 관리 전략, CI/CD 파이프라인 구축까지 전체 여정을 다루는 시리즈의 첫 번째 글입니다.왜 이런 구조가 필요했나모노레포 도입 시 마주한 과제들단일 저장소(Monorepo)에서 다수의 패키지로 구성된 디자인 시스템을 개발하다 보니 다음과 같은 현실적인 문제에 부딪혔습니다.의존성 순환(Circular Dependency) - 패키지 간 참조 관계가 복잡해지면 의도치 않은 순환 참조가 발생할 위험이 큽니다.버전 관리의 모호함 - 패키지 A를 수정했을 때 이를 의존하는 패키지 B와 C의 버전도 함께 올려야 하는지 판단 기준이 모호했습니다...

je개발 회고 2026.01.12

[ CI/CD ] 모노레포 Gitlab CI/CD 전략

모노레포 CI/CD 배포 전략모노레포 환경에서 release 브랜치 기반의 자동화된 배포 파이프라인을 구축한 경험을 공유합니다. 버전 검증부터 NPM 배포까지 전 과정을 CI가 자동으로 처리하도록 설계했습니다.🚀 배포 흐름 개요전체 흐름도develop에서 release 브랜치를 생성하고 QA를 거쳐 main에 병합되면 자동으로 버전 범핑과 NPM 배포가 이루어집니다.배포 파이프라인 전체 흐름개발developQArelease/v1.0.0개발 서버CI: 버전 검증ProductionmainProductionCI: auto-releaseCI: publishdevelop→ branch →release/*→ PR & Merge →main→ 버전 범핑 & 태그 → NPM 배포자동화된 릴리즈 흐름단계작업시점담당2브랜..

je개발 회고 2025.12.22

[ 번들러 ] 모노레포 번들러 비교

모노레포 라이브러리 번들러 7종 비교 React UI 컴포넌트 라이브러리를 대상으로 7가지 번들러를 비교한 결과를 공유합니다. 각 번들러의 빌드 시간과 번들 크기 그리고 설정 복잡도를 실측하여 라이브러리 번들링에 가장 적합한 도구를 찾아보았습니다. 테스트 환경 패키지 React UI 컴포넌트 라이브러리 Entry src/index.ts Output Format ..

je개발 회고 2025.12.22

[ Git ] 회사에 맞는 브랜치 전략

Git 브랜치 전략 가이드팀 프로젝트에서 Git을 효율적으로 운용하기 위한 브랜치 전략을 정리합니다. main과 develop을 중심으로 feature, release, hotfix 브랜치를 운용하는 방식입니다.💡 참고설명의 편의를 위해 도표나 설명에는 feature 키워드를 사용합니다. 실제 개발 시에는 120-feat-login, 121-refactor-auth와 같은 형태의 브랜치명을 활용합니다.브랜치 흐름도전체적인 브랜치 흐름은 다음과 같습니다. 각 브랜치가 어떻게 분기되고 병합되는지 시각적으로 확인할 수 있습니다.Git 브랜치 흐름 main v1.0.0 v1.0.1release develop feature/a feature/b hotf..

je개발 회고 2025.12.22

[ 번들러 ] Monorepo 모노레포 번들러 비교

React UI 라이브러리를 위한 번들러 7종 비교React UI 컴포넌트 라이브러리 패키지를 빌드하기 위해 7가지 번들러를 직접 테스트해 보았습니다. tsup부터 최신 Rust 기반 번들러인 rolldown까지 각각의 특성과 실제 빌드 결과를 정리했습니다.테스트 환경테스트에 사용한 패키지는 React와 MUI 기반의 UI 컴포넌트 라이브러리입니다. 모노레포 환경에서 Button이나 Card 그리고 DataTable 등 8개의 컴포넌트를 포함한 core 패키지를 대상으로 했습니다.항목내용패키지 유형React + MUI 기반 UI 컴포넌트 라이브러리Entrysrc/index.ts (단일 진입점)Output FormatESM + CJS (dual package)ExternalReact, ReactDOM, M..

je개발 회고 2025.12.16

[ html2canvas, jsPdf ] 웹 화면을 PDF 로 다운받는 작업 후기와 숙제

PDF Export 구현 여정이 글은 대시보드 형태의 웹 애플리케이션에서 PDF 내보내기 기능을 구현하면서 겪었던 다양한 문제들과 그 해결 과정을 기록한 내용입니다. 특히 다크모드 화면을 라이트모드 PDF로 변환하고 테이블 행이 페이지 경계에서 잘리지 않도록 하는 과정에서 마주한 기술적 도전과 해결책을 공유합니다.1. 요구사항핵심 요구사항PDF Export 기능을 구현하기 위해 다음과 같은 핵심 요구사항을 정의했습니다.A4 Portrait 모드로 PDF 생성컨텐츠가 가로로 잘리지 않고 A4 너비에 맞게 자동 축소Toolbar는 PDF에서 제외화면은 다크모드지만 PDF는 라이트모드로 출력Grid/Table 셀이 페이지 경계에서 잘리지 않음페이지 번호 표시대상 페이지대상 페이지는 여러 섹션으로 구성되어 있습..

je개발 복습/ETC 2025.11.25

Next.js 서버 컴포넌트 가이드

Next.js 서버 컴포넌트 가이드 Next.js에서 서버 컴포넌트는 성능 최적화와 개발 경험 개선의 핵심입니다. 이 글에서는 서버 컴포넌트의 개념부터 실전 활용법까지 상세히 다룹니다. 1. 서버 컴포넌트 개념 클라이언트 컴포넌트와의 차이점 클라이언트 컴포넌트에서는 모든 렌더링이 클라이언트에서 발생합니다. 반면 Next.js는 기본적으로 서버에서 렌더링을 수행하고 HTML 결과만 클라이언트로 전송합니다. // app/page.tsx - 기본이 서버 컴포넌트export default async function Page() { const response = await fetch('https://api.example.com/posts'); const data = await..