From 1cdb048e36922be534d2ed28130cd7b4e4a2b8ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=ED=9D=AC=EC=9B=90?= Date: Sat, 20 Jun 2026 02:13:52 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=AC=B8=EC=84=9C=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/개발환경.md | 89 +++++++++++++++++++++- doc/코딩규칙.md | 198 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 271 insertions(+), 16 deletions(-) diff --git a/doc/개발환경.md b/doc/개발환경.md index a670ef9..3fff395 100644 --- a/doc/개발환경.md +++ b/doc/개발환경.md @@ -1,5 +1,88 @@ # 개발환경 -- Node, Vite 최신버전 -- SCSS, JS, IMAGE 압축 빌드 -- Prettier \ No newline at end of file +--- + +## 기술 스택 + +| 항목 | 버전 | +|---|---| +| Vite | ^8.0 | +| SCSS (sass) | ^1.101 | +| jQuery | ^4.0 | +| Prettier | ^3.8 | + +--- + +## 명령어 + +```bash +npm run dev # 개발 서버 실행 (localhost:3000, 자동 브라우저 오픈) +npm run build # 프로덕션 빌드 → dist/ +npm run preview # 빌드 결과물 미리보기 +npm run format # SCSS, JS Prettier 포맷 (HTML 제외) +``` + +--- + +## 디렉터리 구조 + +``` +src/ # Vite root +├── index.html +├── js/ +│ └── main.js +├── scss/ +│ ├── main.scss +│ ├── base/ # reset, variable, mixin, font +│ └── page/ # 페이지별 SCSS +├── font/ +│ ├── SUIT/ +│ │ └── SUIT-Variable.woff2 +│ └── DMSerifDisplay/ +│ ├── DMSerifDisplay-Italic-latin.woff2 +│ └── DMSerifDisplay-Italic-latin-ext.woff2 +└── assets/ # 이미지 등 정적 파일 + +dist/ # 빌드 결과물 (git 제외) +doc/ # 프로젝트 문서 +``` + +--- + +## 빌드 설정 + +- **출력 경로**: `dist/` +- **포맷**: `iife` — `file://` 로 직접 열어도 동작하도록 모듈 속성 제거 +- **이미지 압축**: `vite-plugin-imagemin` + - jpg: mozjpeg quality 80 + - png: optipng level 5 / pngquant 0.7~0.9 + - gif: gifsicle level 3 + - svg: 빈 속성 제거, viewBox 유지 +- **CSS sourcemap**: 개발 서버에서만 활성화 (`devSourcemap: true`) + +--- + +## SCSS 설정 + +- `modern-compiler` API 사용 (`@use` 기반, `@import` 미사용) +- 7-1 패턴 구조 + +--- + +## Prettier 설정 + +- 대상: `src/**/*.scss`, `src/**/*.js` (HTML 제외) +- `printWidth: 1000` — 줄바꿈 최소화 +- `tabWidth: 2`, `useTabs: false` +- `singleQuote: false` + +--- + +## 웹폰트 + +외부 CDN 없이 셀프호스팅. `src/font/` 에 woff2 파일 포함. + +| 폰트 | 용도 | +|---|---| +| SUIT Variable | 기본 본문 폰트 (weight 100~900) | +| DM Serif Display Italic | 포인트 serif 폰트 | diff --git a/doc/코딩규칙.md b/doc/코딩규칙.md index 3712f01..9c16a45 100644 --- a/doc/코딩규칙.md +++ b/doc/코딩규칙.md @@ -1,20 +1,192 @@ # 코딩규칙 -- 클래스명은 카멜케이스 키워드에 + BEM 방식 -- BEM 의 depth 는 2depth 까지만, 이후 단계에서는 BEM 생략 -- BEM 클래스만 병렬선언, 나머지는 BEM 클래스 안에 중첩 -- 태그에 스타일을 주지 않음. 클래스를 선언해서 매핑, reset 은 제외 +--- -ex) someThing, someThing__card, someThing__card__blockArea -ex) -.someThing { - img { - } +## 클래스 네이밍 + +- 클래스명은 camelCase + BEM 방식 +- block, element 키워드가 여러 단어일 경우 camelCase 로 이어 붙임 + +``` +someThing +someThing__card +someThing__card__blockArea +gnb__logoImg +gnb__navLink +``` + +- BEM 의 `__` 는 DOM 뎁스를 반영한다 (아래 철학 참고) +- BEM depth 는 2단(`block__el__el`)까지만, 이후 단계는 BEM 생략하고 클래스 중첩 + +```scss +.someThing__card__body { + .thumb { + } // 3depth 이상은 BEM 생략 +} +``` + +- (x) `section--about` — block 수준 modifier 금지 +- (x) `section-about` — 하이픈 네이밍 금지 + +--- + +## BEM depth 철학 + +BEM 원래 스펙에서 `__element` 는 DOM 뎁스가 아닌 "개념적 소속"을 의미한다. +이 프로젝트에서는 의도적으로 **DOM 뎁스를 반영**하는 방식을 채택한다. + +클래스명만 보고도 마크업 구조를 머릿속에 그릴 수 있도록 하기 위함이다. +block 이름이 바뀌면 어차피 하위 element 전체를 수정해야 하므로, +뎁스를 표현한다고 해서 추가 비용이 발생하지 않는다. + +```html +
+
+

...

+
+
+``` + +--- + +## modifier(`--`) 규칙 + +modifier 는 **element 수준에서만** 상태나 변형을 표현할 때 사용한다. + +```scss +// (o) element 에 modifier +.history__img--1 { +} +.history__img--2 { } -.someThing__card { - .thumb { } +// (x) block 에 modifier +.section--about { +} +``` + +--- + +## 상태 클래스 + +JS 로 제어하는 동적 상태도 camelCase 로 표현한다. +단독으로 스타일을 주지 않고 반드시 BEM 선택자와 조합한다. + +```scss +// (o) 상태를 가진 요소에 직접 붙임 +.gnb.isScrolled { +} +.gnb__navLink.isActive { +} +.gnb__mobileNav.isOpen { } -(x) section--about -(x) section-about +// (x) 단독 선언 +.isOpen { +} + +// (x) 케밥케이스 +.is-open { +} +.is-active { +} + +// (x) 다른 BEM 요소를 통해 후손 타겟 +.gnb__navItem.isActive .gnb__navLink { +} +``` + +--- + +## SCSS 선언 규칙 + +**병렬 선언 vs 중첩** + +- BEM 클래스(`block`, `block__el`, `block__el__el`)는 최상위에 병렬 선언 +- 그 외(pseudo, 상태 클래스, 하위 클래스 중첩)는 BEM 클래스 안에 중첩 + +```scss +// (o) +.gnb { +} + +.gnb__inner { +} + +.gnb__navLink { + &:hover { + } + &.isActive { + } +} + +// (x) BEM 클래스를 중첩 +.gnb { + .gnb__inner { + } +} + +// (x) 서로 다른 BEM 요소 간 후손 선택자 +.gnb__navItem.isActive .gnb__navLink { +} +``` + +**미디어쿼리** + +- `@include mo` 는 각 SCSS 파일 최하단에 단일 블록으로 배치 +- 여러 군데 분산 선언 금지 + +```scss +.gnb { +} +.gnb__inner { +} + +@include mo { + .gnb { + } + .gnb__inner { + } +} +``` + +**`@use` 선언** + +- 각 파일 최상단에 `variable`, `mixin` 을 `*` 로 불러옴 + +```scss +@use "../base/variable" as *; +@use "../base/mixin" as *; +``` + +--- + +## 태그 선택자 + +태그에 직접 스타일을 주지 않는다. 클래스를 선언해서 매핑한다. +reset(`_reset.scss`) 은 예외적으로 태그 선택자를 허용한다. + +```scss +// (x) +img { + width: 100%; +} + +// (o) +.card__thumb { + width: 100%; +} +``` + +--- + +## 반응형 폰트 + +고정값 대신 `clamp()` 로 뷰포트에 따라 유동적으로 변하도록 선언한다. + +```scss +font-size: clamp(최소값, 선호값, 최대값); + +// ex) +font-size: clamp(14px, 1.3vw, 18px); +```