AI에게 '좋게 움직여줘'가 통하지 않는 이유와, 동작 이름으로 요청하는 방법
요약
AI에게 추상적인 움직임 요청 대신, '이름 + 위치 + 숫자 + 배려'의 구체적 지침을 제공해야 원하는 웹 애니메이션 효과를 얻을 수 있습니다. 이 글은 CSS 기반으로 구현 가능한 6가지 웹 움직임을 소개하며, 개발자가 AI 프롬프트에 포함할 상세한 기술 사양을 제시합니다.
핵심 포인트
- 애매한 요청 대신 '이름 + 위치 + 숫자 + 배려'로 구체화하세요.
- CSS만 사용하도록 제약하고, 라이브러리 의존성을 막으세요.
- 스크롤 애니메이션 등은 IntersectionObserver를 활용하는 것이 핵심입니다.
- 사용자 접근성(prefers-reduced-motion)을 반드시 고려해야 합니다.
Claude나 ChatGPT에게 LP(랜딩 페이지)를 만들게 할 때, '멋지게 움직여줘', '좋은 애니메이션을 붙여줘'라고 부탁한 적이 없으신가요?
돌아오는 움직임은 매번 제각각입니다. 모든 요소가 흐물흐물 움직이거나, 첫 화면의 제목까지 늦게 나타나거나, 스마트폰에서는 의미 없는 호버(hover) 효과가 붙기도 합니다. 몇 번을 다시 말해도 원하는 움직임에 가까워지지 않습니다.
원인은 간단합니다. '좋은 느낌'에는 사양이 하나도 없기 때문입니다. AI는 '어떤 요소에', '어떤 움직임을', '몇 초 동안', '얼마나 움직일지'를 전부 스스로 결정하게 되고, 그 결과가 '평균적으로 화려한 무언가'가 됩니다.
이 글에서는 웹에서 자주 사용되는 움직임들을 이름으로 요청하는 방법과, 바로 사용할 수 있는 CSS 6가지를 소개합니다.
요청 방식의 틀: 이름 + 위치 + 숫자 + 배려
움직임 연출에는 거의 정해진 이름들이 있습니다. '스크롤로 페이드인(fade-in on scroll)', '스티키 헤더(sticky header)', '마키(marquee)' 등입니다. 이름을 사용해서 요청하면, AI는 학습한 내용 중에서 '그 이름으로 보통 어떻게 만드는지'를 끌어올 수 있기 때문에 일관성이 크게 떨어집니다.
하지만 이름만으로는 부족합니다. 다음 4가지를 갖추면 거의 한 번에 원하는 움직임을 얻을 수 있습니다.
- 이름을 한국어와 영어 양쪽으로 작성하기 예: '언더라인 애니메이션(underline animation)'. 한쪽만 쓰는 것보다 혼동이 줄어듭니다. - 어디에 적용할지 쓰기 예: '메뉴 링크에', '가격 카드에'. 모든 곳에 적용하면 산만해집니다. - 속도와 거리를 숫자로 쓰기 예: '0.25초', '아래에서 16px'. 작은 변화는 0.2초 전후, 장면 전환은 0.3초 전후가 적당합니다. - 움직임을 줄이는 설정에 대한 배려를 쓰기
prefers-reduced-motion: reduce
(OS의 '시차 효과 줄이기' 설정) 사용자에게는 움직이지 않게 하라고 한마디 덧붙입니다.
여기에 더해 '라이브러리는 사용하지 않는다', 'CSS만으로'와 같이 기술적인 제약을 명시하면, 불필요한 의존성이 들어오는 것을 막을 수 있습니다.
아래에서 자주 사용하는 6가지 움직임을 이 방식의 지침문과 실제 CSS로 살펴보겠습니다. 숫자는 모두 '이 정도면 읽는 데 방해가 되지 않을 것'이라고 판단한 초기값입니다.
1. 스크롤로 페이드인 (Fade-in on scroll)
화면에 들어온 제목이나 카드가 아래에서 살짝 나타나는 연출입니다. 가장 많이 요청되지만, 가장 과하게 적용되기 쉬운 움직임이기도 합니다.
지침문 예시
섹션의 제목과 카드에 '스크롤로 페이드인(fade-in on scroll)'을 적용해 주세요. 처음에는 opacity: 0으로 하고 16px 아래에 위치시키되, 화면 하단에서 10% 진입했을 때 0.5초의 ease-out 효과로 원래 위치에 표시해 주세요. 가로로 나열된 카드는 0.1초씩 지연시켜 순서대로 나타나게 해 주세요. 판정은 IntersectionObserver를 사용하고, 한 번 표시되면 관찰을 중단해 주세요. 라이브러리는 사용하지 말아 주세요. prefers-reduced-motion: reduce 사용자에게는 처음부터 보이게 하고, JavaScript가 작동하지 않는 환경에서도 내용이 볼 수 있도록 처리해 주세요.
<script>document.documentElement.classList.add('js');</script>
<section>
<h2 class="reveal">선택되는 3가지 이유</h2>
...
/* JavaScript가 작동했을 때만 숨김 (실패해도 내용은 보임) */
.js .reveal {
opacity: 0;
...
const io = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
...
포인트
- 숨김 처리를
.js클래스 아래에 두는 것이 은근히 중요합니다. CSS만으로opacity: 0으로 설정하면, 스크립트 로딩에 실패했을 때 내용이 사라진 채로 남을 수 있습니다. 지침문에 명시해두면 확실합니다. - 첫 화면 요소에는 적용하지 마세요. 페이지를 열자마자 순간적으로 비어 보이고, 표시가 느리다고 느끼게 합니다. - 거리는 50px 이상, 시간은 1초 이상이면 '기다리고 있다'는 느낌이 강해집니다. 1624px, 0.30.5초 정도가 무난합니다.
2. 호버로 떠오르기 (Hover lift)
카드에 마우스를 올리면, 약간 떠오르면서 그림자가 진해지는 연출입니다. '눌릴 수 있음'을 전달하는 움직임이므로 CSS만으로 충분합니다.
지시문 예시
카드 목록에 '호버 시 솟아오름(hover lift)' 연출을 적용해주세요. 마우스를 올리면 transform: translateY로 6px 위로 이동시키고, box-shadow로 아래쪽에 부드러운 그림자(진하기 0.35, 떠오른 거리에 맞춰 아래로 이동하며 넓게 흐리게)를 추가합니다. 시간은 0.2초, 이징 곡선은 ease-out을 사용합니다. CSS만으로 만들고 JavaScript는 사용하지 말아 주세요. :hover는 @media (hover: hover) 안에 작성하고, 스마트폰에서는 떠오르게 하지 않고 누르는 순간(:active)에만 scale(0.98)로 살짝 줄여서 가라앉은 것처럼 보이게 합니다. 키보드 조작을 위해 :focus-visible에서도 같은 모양으로 하고, prefers-reduced-motion: reduce일 때는 움직이지 않고 그림자만 변경해 주세요.
.card {
display: block;
border-radius: 12px;
...
포인트
:hover를 @media (hover: hover) 안에 넣는 것을 잊으면, 스마트폰에서는 터치 후 '떠 있는 상태로 돌아오지 않는' 현상이 남습니다. - 떠오르는 거리와 그림자를 연동시키면(그림자는 거리의 2배 아래・4배 흐리게) 숫자를 바꿔도 시각적 파괴가 일어나지 않습니다.
3. 밑줄 애니메이션 (Underline animation)
메뉴 링크에 마우스를 올리면, 밑줄이 왼쪽에서 늘어나는 연출입니다. 마우스를 올렸을 때는 왼쪽부터, 벗어났을 때는 오른쪽으로 줄어들며 사라지게 하면 훨씬 정교해 보입니다.
지시문 예시
메뉴 링크에 '밑줄 애니메이션(underline animation)'을 적용해주세요. 링크에 position: relative를 주고, ::after로 높이 2px의 선을 글자 아래 4px에 배치합니다. 평소에는 transform: scaleX(0)으로 하고, 올리면 scaleX(1)로 하여, 0.25초의 ease-out으로 왼쪽에서 늘어나게 합니다(올렸을 때는 transform-origin: left, 벗어났을 때는 right로 설정하여 오른쪽으로 줄어들며 사라지게 함). :hover는 @media (hover: hover) 안에 작성하고, :focus-visible에서도 선이 나오도록 합니다. 현재 페이지(`aria-current=
.marker {
color: inherit;
background-color: transparent; /* mark의 노란색 배경을 제거 */
...
JavaScript는 페이드인과 거의 같으며, 클래스명을 `is-on`으로, 옵션을 `{ threshold: 1 }` (모든 단어가 보인 후에 실행)로 설정하기만 하면 됩니다.
**포인트**
- `::after`로 선을 그리는 방식은 2줄로 줄 바꿈 되었을 때 첫 번째 줄에만 그려집니다. 인라인 요소의 `background`로 그리면, 줄 바꿈 되어도 자연스럽게 연결됩니다. - `<mark>`를 사용하면 스크린 리더나 검색 엔진에도 "강조된 단어"로 전달됩니다.
## 5. 스크롤 프로그레스 바 (Scroll progress bar)
기사를 읽은 비율을 화면 상단의 가는 선으로 보여주는 연출입니다. 긴 기사에서 "남은 분량"을 전달하는 데 효과적입니다.
**지시문 예시**
기사 페이지에 "스크롤 프로그레스 바 (reading progress bar, 독서 완료 바)"를 추가해 주세요. 화면 상단(고정 헤더 바로 아래)에 두께 4px, 색상 #f06a35의 선을 `position: sticky`로 고정하고, 읽어 나간 비율(스크롤 양 ÷ 스크롤 가능한 최대량)만큼 왼쪽에서 늘려주세요. 길이를 조절할 때는 width가 아닌 `transform: scaleX`를 사용하고, scroll 이벤트는 `requestAnimationFrame`으로 간격을 두고 처리해 주세요. 선에는 role="progressbar"와 aria-valuenow를 추가하여 음성 읽기에서도 비율이 전달되도록 해 주세요. 라이브러리는 사용하지 마세요. transition은 적용하지 않고 스크롤에 그대로 맞추어 주세요.
```html
<div class="progress" role="progressbar" aria-label="기사 읽은 비율"
aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<span class="progress-bar"></span>
...
.progress {
position: sticky;
top: 0;
...
const progress = document.querySelector('.progress');
let ticking = false;
function update() {
...
포인트
- JavaScript에서는 비율을 CSS 변수
--p로 전달하기만 하고, 시각적인 부분은 CSS에 맡기면 색상이나 두께 변경이 CSS만으로 가능합니다. - 선에transition을 적용하면 "따라오는" 느낌이 나지만, 스크롤과 어긋나 보입니다. 적용하지 않는 것이 좋습니다.
6. 마키 (Marquee)
도입 기업의 로고나 이름이 가로로 계속 흐르는 배너입니다. 끊김 없이 흘러가게 하려면 "같은 배열을 두 번 나열하고, 절반만큼 움직이면 처음으로 돌아오게 하는" 것이 일반적인 제작 방식입니다
이것을 넣지 않으면, 한 바퀴 돌 때마다 순간적으로 간격이 좁아져 '뚝' 끊겨 보입니다 - 오래된 <marquee>
태그는 비권장(deprecated)입니다. 이름이 같아서 혼동을 막기 위해 'CSS의 @keyframes로'라고 덧붙여둡니다.
이름을 모를 때
여기까지의 6가지는 이름을 알고 있으면 요청할 수 있지만, 곤란한 경우는 '저 사이트의 저 움직임, 뭐라고 했더라?' 할 때입니다.
그 때문에 자주 사용하는 움직임 32종을 움직이는 예시와 함께 이름으로 찾아볼 수 있는 웹 움직임 도감(Webの動きの図鑑)을 만들었습니다. 각 페이지에는 '사용하는 상황/사용하지 않는 상황', '비슷한 움직임과의 차이'와 이 기사에서 같은 형식의 지시문이 실려 있습니다.
각 페이지 예시 아래에는 슬라이더가 있어서, 예를 들어 페이드인(fade-in)의 '나타나는 속도'를 0.5초에서 0.3초로 움직이면, 예시 움직임・CSS 코드・AI에 대한 지시문 수치가 동시에 변합니다. 눈으로 보고 적당한 수치를 결정하여 그대로 복사해 AI에게 붙여넣을 수 있습니다. 페이드인 페이지에서 시도할 수 있습니다.
요약
- '좋게 움직여줘'에는 사양이 없습니다. AI는 매번 다른 '평균적으로 화려한 무언가'를 반환합니다.
- 이름(영/일어) + 적용할 위치 + 숫자 + 움직임을 줄이는 설정에 대한 배려의 4가지 세트로 요청하면, 흔들림이 거의 없어집니다. - 구현 측면에서는 '
transform으로 움직인다', ':hover는@media (hover: hover)안에 넣는다', 'JS가 작동하지 않을 때 내용물이 사라지지 않는다'의 3가지를 지시문에 넣어주면, AI 출력의 질이 눈에 띄게 올라갑니다.
움직임뿐만 아니라 모달(modal)・드로어(drawer)・바텀 시트(bottom sheet) 같은 화면 구성 요소에 대해서도 동일한 형식으로 30종을 정리한 UI 부품 도감(UI部品の図鑑)이 있습니다. 부품의 이름과 사용처를 고민할 때 참고하세요.
토론 (Discussion)

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기