Community이미지github.com

Farhad1618/grainy-gradients

CSS 그라데이션과 배경에 필름 그레인(노이즈)을 추가하여 인쇄된 듯한 질감을 주고 색상 밴딩을 제거합니다. 단일 배경 또는 전체 사이트/앱에서 작동하며, 코드베이스를 스캔하여 모든 배경을 나열하고 선택할 수 있도록 합니다. 각 배경을 측정하고 블렌드와 양을 직접 선택하며, 실제 페이지에서 전후 비교를 보여주고 방문자 화면(HDR/OLED, 고대비, 인쇄)에 적응하는 CSS를 작성합니다. 누군가 배경이나 그라데이션이 싸보이거나, 평평하거나, 플라스틱 같거나, 너무 매끄럽거나, 디지털 같거나, 프리미엄이 아니라고 말하거나, 줄무늬나 밴딩이 보인다고 말하거나, 그레인, 노이즈, 질감 또는 필름/포스터 느낌을 요구하거나, 사이트의 그라데이션을 확인해 달라고 하거나, feTurbulence 노이즈 트릭을 언급할 때 사용하세요.

grainy-gradients란 무엇인가요?

Grainy gradients는 CSS 배경에 필름 그레인(노이즈)을 추가하여 디지털 그라데이션을 인쇄된 듯한 질감으로 바꾸고 색상 밴딩을 숨기는 AI 에이전트 스킬입니다. Claude Code, Cursor, Codex 등 모든 터미널 및 파일 접근이 가능한 AI 코딩 에이전트와 함께 사용할 수 있습니다. 이 스킬은 단일 배경(요소 지정) 또는 전체 코드베이스 스캔을 지원하며, 스타일시트, 마크업, Tailwind 클래스 등을 분석하여 후보 배경을 분류합니다. 그레인은 미드그레이를 기준으로 한 지각적 밝기(L*)를 측정하여 0.5/0.8/1.4(미세/중간/강함) 수준을 목표로 하며, CIELAB 색 공간의 특성을 활용하여 어떤 색상에서도 동일한 시각적 효과를 제공합니다. 주요 기능으로는 실제 페이지 전후 비교(브라우저 기반 headless 렌더링과 드래그 슬라이더), CSS 미디어 쿼리(dynamic-range, prefers-contrast, print)를 통한 HDR/OLED, 고대비 모드 및 인쇄 시 자동 적응, 정확한 그레인 구현 여부를 확인하는 자동 체크 등이 있습니다. 에이전트는 배경 선택, 전후 비교 확인, 최적 옵션 선택 세 가지 결정만 사용자에게 맡기고 나머지 모든 과정을 자동으로 수행합니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Farhad1618/grainy-gradients/tree/HEAD/skills/grainy-gradients

Installed? Explore more 이미지 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

그레인 그라데이션(Grainy gradients)

매끄러운 디지털 그라데이션은 "컴퓨터"처럼 읽힙니다. 미세한 노이즈 레이어를 추가하면 인쇄물이나 필름처럼 보이게 하고, 밴딩(8비트 색상 레벨이 전환될 때 나타나는 눈에 띄는 줄무늬)을 숨깁니다.

사용자는 보고 선택만 합니다. 나머지는 모두 당신이 처리합니다. 블렌드 모드, 불투명도 또는 숫자에 대해 절대 묻지 마세요. 사용자는 다음 세 가지 결정만 내리면 됩니다:

  1. 어떤 배경에 적용할지 (전체 사이트를 스캔한 경우에만).
  2. 먼저 전후 비교를 볼지, 아니면 바로 적용할지.
  3. 미리보기에서 어떤 옵션이 가장 좋아 보이는지.

어떻게 생각해야 할까

  • 그레인은 질감이지 색상이 아닙니다. 밝게 하거나, 어둡게 하거나, 색조를 입혀서는 안 됩니다. 노이즈는 미드그레이를 기준으로 하므로 밝기 변화가 0에 가까워야 합니다. 순수한 검정이나 흰색에는 적용할 수 없으며, 보고서에 그렇게 명시됩니다.

  • 보이는 것을 측정하세요, 불투명도가 아닙니다. 눈에 보이는 그레인은 L*(CIELAB 밝기, 0-100)의 분포로 측정되며, L*은 지각적이므로 동일한 숫자는 모든 색상에서 거의 동일하게 보입니다. 약 0.45 미만에서는 아무도 볼 수 없습니다. 목표값은 미세/중간/강함에 대해 각각 0.5 / 0.8 / 1.4입니다.

  • 밝은 부분에서 어두운 부분으로 가는 그라데이션에서 Even이 중요합니다. Overlay는 그레인의 대부분을 밝은 부분에 집중시킵니다. Even은 블렌드(보통 soft-light)를 선택하여 그레인을 더 고르게 분포시킵니다. 사람들은 보통 Even을 선호합니다.

  • 그레인은 배경에 속합니다. 배경 바로 위에 위치하며, 다른 모든 요소 아래에 있고, 배경이 가는 곳이면 어디든 함께 갑니다. 배경이 페이드 인되면 그레인도 함께 페이드 인됩니다.

  • 각 방문자의 화면에 적응합니다. 웹사이트는 OLED와 LCD를 구분할 수 없지만, CSS는 HDR 화면(대부분의 OLED 폰, XDR 노트북)과 고대비 설정을 감지할 수 있습니다. CSS에는 다음 미디어 쿼리가 포함됩니다:

    • 어두운 배경은 HDR 화면에서 그레인이 약간 줄어듭니다.
    • 고대비 설정에서는 그레인이 줄어듭니다.
    • 인쇄 시에는 꺼집니다.

    모두 CSS로 처리되며, 라이브 사이트에는 스크립트가 필요 없습니다.

  • 그레인이 도움이 되지 않는 경우는 건너뛰세요:

    • 작은 요소(버튼, 배지, 아이콘)
    • 그라데이션 텍스트
    • 사진 위의 반투명 스크림 및 페이드
    • 줄무늬 및 해치 패턴

1. 어떤 방식으로 요청했나요?

  • 한 곳("히어로가 평범해 보여요", "푸터에 그레인을 추가해 주세요"): 배경 한 곳 찾기로 이동하세요.
  • 전체 사이트 또는 앱("내 코드베이스를 살펴봐 주세요", "모든 그라데이션을 확인해 주세요", "전체 사이트에 적용해 주세요"): 전체 사이트 스캔으로 이동하세요.

2a. 배경 한 곳 찾기

실제로 배경을 칠하는 요소를 찾으세요. 확인할 사항:

  • 요소 자체와 그 ::before 및 ::after
  • 요소 내부 또는 뒤에 있는 전체 크기의 레이어 (섹션은 종종 별도의 절대 위치 div에서 색상을 가져옵니다)

브라우저 도구를 사용하여 후보를 나열하세요:

[...document.querySelectorAll('#section, #section *')].flatMap(e => [null, '::before', '::after'].map(p => [e, p, getComputedStyle(e, p)]))
  .filter(([, p, c]) => (!p || c.content !== 'none') && (c.backgroundImage !== 'none' || c.backgroundColor !== 'rgba(0, 0, 0, 0)'))
  .map(([e, p, c]) => `${e.tagName.toLowerCase()}${e.id ? '#' + e.id : ''}.${[...e.classList].join('.')}${p || ''} | ${c.position} | opacity ${c.opacity} | ${(c.backgroundImage !== 'none' ? c.backgroundImage : c.backgroundColor).slice(0, 80)}`)

브라우저가 없다면 CSS를 읽으세요. 어느 쪽이든, 해당 배경의 다른 버전(미디어 쿼리, 다크 모드 규칙)을 CSS에서 검색하세요. 5단계를 위해 기록해 두세요.

그런 다음 3단계로 이동하세요.

2b. 전체 사이트 스캔

node <이 스킬의 폴더>/scripts/scan.mjs <프로젝트 폴더>

약 1초 안에 스타일시트(규칙, 미디어 쿼리, 사용자 정의 속성), 마크업 및 컴포넌트(Tailwind 그라데이션 클래스, 인라인 스타일, CSS-in-JS)를 읽습니다. 찾은 항목을 네 그룹으로 분류합니다:

  • 좋은 후보: 큰 배경.
  • 확인 필요: 코드에서 크기를 알 수 없음.
  • 이미 그레인이 있음.
  • 건너뛰기, 이유 포함.

또한 각 스타일시트를 로드하는 페이지를 나열합니다. 전체 데이터를 보려면 --json을 추가하세요.

"확인 필요" 항목은 직접 정렬하세요. 목록을 보여주기 전에, 볼 수 있는 내용을 기준으로 정렬하세요. 브라우저 도구를 사용하여 페이지에서의 크기를 측정하세요. 그렇지 않으면 마크업을 읽으세요. 각 항목을 좋은 후보 또는 건너뛰기로 이동하세요. 확인할 수 있었던 항목의 목록을 사용자에게 보내지 마세요.

그런 다음 목록을 보여주세요. 짧게, 각 항목 한 줄씩, 평이한 말로, 페이지별로 그룹화하여 보여주세요. 예시:

그레인을 적용할 수 있는 배경 6개를 찾았습니다:

  1. 홈, 투어 섹션: 어두운 그라데이션, 페이드 인됨
  2. 홈, 히어로: 어두운 방사형 글로우
  3. 지속가능성, 헤더: 녹색-검정 그라데이션
  4. 채용, "made here" 밴드: 주황색-검정 그라데이션

12개는 건너뜁니다: 버튼, 그라데이션 텍스트, 사진 스크림 및 줄무늬 패턴. 견적 페이지에는 이미 그레인이 있지만, 아무도 볼 수 없는 양이므로 다시 작업하겠습니다.

그런 다음 선택하게 하세요. 다중 선택 질문 도구(Claude Code의 AskUserQuestion)가 있다면 사용하세요:

  • "어떤 배경에 그레인을 적용할까요?"라고 묻고 **모두 (권장)**을 첫 번째 옵션으로 놓으세요.
  • 최대 3개의 추가 항목에 대해 각각을 옵션으로 나열하고 다중 선택을 켜세요.
  • 항목이 4개를 초과하면 먼저 "모두 적용할까요, 아니면 고를까요?"라고 묻고, "고를게요"라고 답하면 최대 4개 항목씩 다중 선택 질문을 하세요.

도구가 없으면 "all" 또는 번호로 답변해 달라고 요청하세요.

3. 전후 비교 또는 바로 적용 질문

선택된 모든 항목에 대해 한 번만 질문하세요: "먼저 전후 비교를 보고 싶으신가요, 아니면 각 항목에 가장 좋은 옵션을 바로 적용할까요?" 가능하면 다중 선택 도구를 사용하여 **먼저 보여주기 (권장)**와 바로 적용하기 옵션을 제공하세요.

아래 도구는 **Node 22+**와 컴퓨터에 설치된 Chrome, Chromium, Edge 또는 Brave가 필요합니다(자동으로 찾습니다. CHROME_PATH로 재정의 가능). 이 도구들은 headless 모드로 페이지를 열기 때문에 사이트에 접근 가능해야 합니다: 실행 중인 개발 서버, 스테이징 URL, 또는 일반 HTML의 경우 file://. 사이트에는 아무것도 추가되지 않습니다.

4. 전후 비교 보여주기

먼저 보여주기: 리뷰 페이지

백그라운드에서 실행하세요(사용자를 기다립니다). 페이지당 하나의 --url과 그 페이지의 선택자를 함께 입력하세요:

node <스킬>/scripts/review.mjs --url http://localhost:3000/ --selector ".hero" --selector ".footer-band" \
                                --url http://localhost:3000/about --selector ".about-header"
  • 자체적으로 사진을 찍습니다. 각 배경에 대해 페이지의 현재 모습과 모든 옵션, 그리고 HDR 화면과 고대비 설정에서 보이는 모습을 촬영합니다. 페이지당 약 10-30초가 소요됩니다.
  • 그런 다음 로컬 리뷰 페이지를 브라우저에서 열고 주소를 출력합니다. 사용자에게도 링크를 알려주세요.
  • 각 배경에는 카드가 표시됩니다:
    • 전후 비교 슬라이더
    • 밴딩 확대 보기: 가장 밴딩이 심한 영역을 확대합니다(축소된 사진에서는 미세한 그레인이 보이지 않습니다).
    • 옵션 탭 (권장 옵션에는 별표 표시)
    • 화면 전환 버튼
    • 측정된 숫자 및 보고서가 포함된 "이유"
  • "완료, 선택 전송" 버튼을 누르면 선택 사항이 바로 전송됩니다. 복사-붙여넣기가 필요 없습니다.

사용자에게 한 줄로 설명하세요: "각 사진을 드래그하고, 확대 보기를 시도하고, 배경당 하나를 고른 다음 Done을 누르세요." 명령이 종료되면 출력에 선택 사항, 각 배경에 대한 CSS, 그리고 7단계 확인을 위한 배경별 기준 폴더가 포함됩니다.

채팅에도 사진을 보여주세요. 각 기준 폴더에는 compare-<옵션>.png가 있습니다:

  • 전체 전후 비교
  • 확대된 세부 사항
  • 대비를 늘린 동일한 세부 사항(밴딩은 줄무늬로, 그레인은 노이즈로 표시됨)
  • 측정된 숫자

권장 옵션을 사용자에게 보내세요(파일 전송 도구가 있으면 사용하고, 없으면 경로를 알려주세요). 이것이 변경이 실제로 이루어졌다는 증거입니다.

바로 적용하기

결과를 확인하고 보여줄 수 있도록 먼저 기준 사진과 사진을 찍으세요:

node <스킬>/scripts/shoot.mjs --url http://localhost:3000/ --selector ".hero" --option recommended --out ./grain-shots

사진 한 장당 한 줄씩(그레인, 밝기, 줄무늬 너비)을 출력하고 <out>/<selector>/에 report.json(보고서, 모든 옵션에 대한 CSS, 권장 옵션)과 compare-<옵션>.png를 씁니다. report.json에서 권장 CSS를 사용하세요.

Chrome이 없거나 사이트를 headless로 접근할 수 없는 경우

페이지 내 미리보기로 대체하세요: dist/grain-page.js을 사이트의 스크립트 옆에 복사하고(로드되는지 확인, 200 반환), <script src="/js/grain-page.js" data-grain=".hero | .footer" defer></script>를 추가하고, 사용자가 ?grain을 붙여 페이지를 열도록 하세요. 실제 페이지에 드래그 가능한 핸들과 함께 동일한 옵션이 표시됩니다. Copy picks는 각 배경에 대해 grain: <옵션> + 모양을 복사하며, 이를 node <스킬>/scripts/grain.js --look -에 파이프하여 CSS를 얻습니다. 나중에 태그와 파일을 제거하세요.

브라우저가 전혀 없으면 직접 모양(look)을 작성하고 grain.js를 실행하세요:

{ "selector": ".hero", "kind": "gradient", "shape": "linear",
  "colours": [{ "colour": "#323435", "pos": 0 }, { "colour": "#141617", "pos": 1 }],
  "lengthPx": 900, "background": "linear-gradient(...)", "behind": "#ffffff",
  "solidBase": true, "position": "relative", "freePseudo": "::after", "moves": null }

또는 node grain.js --colours "#323435,#2a2c2d@24%,#141617" --length 900 --selector ".hero" [--shape radial] [--fade-over "#fff"] [--option even].

엔진이 결정하는 사항 (당신이 할 필요 없음)

상황처리 방법
요소의 그라데이션 또는 단색한 레이어: 노이즈가 요소의 최상위 배경 레이어가 됩니다(background-blend-mode 사용, --grain 사용자 정의 속성에 저장됨). 모든 배경 목록에 하나의 값이 추가되므로 페이지의 자체 크기, 위치 및 블렌드가 유지됩니다. 텍스트를 덮을 수 없습니다.
배경이 페이드 인됨동일한 한 레이어이므로 그레인이 함께 페이드 인됩니다. 보고서는 페이드의 각 단계에서 그레인을 제공합니다.
아래에 단색 배경이 없는 반투명 그라데이션자체 레이어(사용 가능한 ::after/::before, 또는 자식 요소)를 사용하여 보이는 내용과 블렌드되어 회색으로 변하지 않습니다.
사진 또는 이미지 배경사용 가능한 의사 요소, 또는 둘 다 사용 중이면 자식 요소를 사용합니다.
요소를 채우는 <img>/<video> 또는 의사 요소의 배경격리된 호스트 내 z-index: -1의 자식 요소를 사용합니다.
순수한 검정 또는 흰색Overlay와 soft-light는 거기에 그레인을 추가할 수 없으므로 약간의 밝기 변화와 함께 screen 또는 multiply를 사용하며, 그렇게 명시합니다.
그라데이션 전체에 걸쳐 고르지 않은 그레인Even이 명확히 더 고른 경우 Even을 권장합니다. Even은 Medium과 동일한 경우 숨겨집니다.
높은 밴딩 위험선택한 그레인이 줄무늬를 얼마나 잘 깨는지 알려줍니다. Strong이 더 많은 효과를 냅니다.
동일한 배경에 기존 노이즈 레이어가 있는 경우이를 대체합니다. 기존 노이즈가 다른 곳(의사 요소)에 있으면 제거하라고 알려줍니다.
WebGL/캔버스 장면의 일부로 그려진 배경(3D 지면, 셰이더 배경)캔버스 뒤의 CSS 그레인이 거기에 도달할 수 없으므로 캔버스 부분은 그레인이 있는 하늘 옆에서 매끄럽거나 얼룩덜룩하게 보입니다. 당신이 추가해야 합니다: 해당 재료의 프래그먼트 셰이더에서, 색 공간 변환 후, 화면 공간에서 동일한 노이즈 타일을 soft-light로 블렌드합니다(gl_FragCoord.xy / tilePx, tile = 200 × 렌더러 픽셀 비율). 타일과 양은 페이지의 --grain 사용자 정의 속성에서 읽어서 휴대폰, HDR 및 고대비 양이 전달되도록 하고, 리사이즈 시 다시 읽으세요. 한 프레임을 렌더링하고 픽셀을 읽어 측정합니다.
HDR 화면, 고대비, 인쇄@media (dynamic-range: high) 및 @media (prefers-contrast: more)는 동일한 블렌드로 해당 화면에 맞게 양을 다시 계산합니다. @media print는 그레인을 끕니다. 동일하게 나오는 규칙은 생략됩니다.

색상은 그라데이션에서 차지하는 비율에 따라 가중치가 부여됩니다. 얇은 하이라이트는 큰 어두운 영역만큼 중요하게 간주되지 않으므로, 동일한 섹션의 휴대폰 및 데스크톱 버전이 동일한 처리를 받습니다.

5. 적용

  • 각 CSS 블록을 해당 배경이 정의된 위치에 주석과 함께 배치하세요.
  • 프로젝트의 자체 배경 표현식을 유지하세요. 엔진은 계산된 값으로 작업하므로, 출력이 긴 해석된 그라데이션을 반복하는 경우 var(--slate) 또는 원래의 linear-gradient(...)를 다시 넣으세요.
  • 각 배경의 모든 버전을 처리하세요(휴대폰, 다크 모드). 한 레이어 CSS는 동일한 미디어 쿼리 내의 동일한 선택자에 적용됩니다. 각 버전이 다르면 --phone 또는 --colours를 사용하여 측정하세요.
  • 자식 요소 방식: 주석에 지정된 위치에 <div class="grain-layer" aria-hidden="true"></div>를 추가하세요(컴포넌트 내 마크업에).
  • 반복되는 노이즈 URL에는 하나의 사용자 정의 속성을 사용하세요. 여러 규칙이 동일한 URL을 사용하면 한 번만 정의하세요.
  • 보고서에 "위에 페이드됨"이 나열되면, 설명된 대로 각각에 동일한 그레인을 제공하세요. 그렇지 않으면 가장 어두운 부분에서 다시 밴딩이 발생합니다.
  • 임시 항목(미리보기 태그, grain-page.js)을 제거하세요.

6. 매번 확인

완료했다고 말하기 전에, 각 배경을 기준과 비교하여 확인하세요:

node <스킬>/scripts/check.mjs --url http://localhost:3000/ --selector ".hero" --baseline <기준 폴더> [--option even]

페이지를 다시 촬영하고 각 항목에 대해 PASS/FAIL을 출력합니다:

  • 그레인 레이어가 페이지에 있음 (CSS가 로드되어 올바른 선택자에 적용됨).
  • 페이지에 새로운 오류가 없음.
  • 그레인이 예상 양에 근접함.
  • 밝기가 변하지 않음.
  • 줄무늬가 좁아짐.
  • 배경 외부의 아무것도 변경되지 않음.
  • 요소가 이동하거나 크기가 변경되지 않음.

check.png를 작성합니다(이전 vs 현재). FAIL이 발생하면 수정하고 다시 확인을 실행하세요. 실패 상태에서 성공을 보고하지 마세요. 수정할 수 없는 FAIL이 있으면 정확히 어떤 검사가 실패했는지와 이유를 사용자에게 알려주세요.

7. 보고

배경당 한두 문장으로, 또는 전체 사이트의 경우 짧은 목록으로 보고하세요: 배경이 무엇인지, 무엇이 선택되었고 그 이유는 무엇인지. 확인 결과(예: "그레인 0.83 L*, 줄무늬 80px → 0.7px, 다른 것은 변경되지 않음")를 추가하고 check.png 또는 compare 사진을 보내세요. 그레인이 HDR 화면과 고대비 설정에 적응하고 인쇄 시 꺼진다고 한 번 언급하세요. 보고서에서 해당 종류의 배경에 대해 목표가 육안으로 확인되지 않았다고 명시되면 간략히 언급하세요.

나중에 조정하기

  • "너무 많아요" 또는 "안 보여요": 한 단계 이동하세요.
  • "색상이 변했어요": 밝기가 잘못되었을 수 있습니다. Even을 시도하거나 양을 줄이세요. 영역이 회색으로 변했다면 요소 뒤에 단색 레이어가 없다는 뜻이므로 페이드 옵션을 확인하세요.
  • "다른 브라우저에서 다르게 보여요": 표준 CSS이므로 다를 수 없습니다. 다른 브라우저에서도 동일하게 보여야 합니다. HDR vs SDR 차이일 수 있습니다.
  • "제거해 주세요": 그레인 CSS를 제거하고, 추가된 자식 요소나 임시 파일을 제거하세요.

참고: 이 스킬은 디지털 그라데이션에 필름 그레인을 추가하여 프리미엄 느낌을 주고 색상 밴딩을 제거합니다. 모든 결정은 자동으로 이루어지며, 사용자는 최종 선택만 합니다.

관련 스킬