지지직 거리는 Glitch 효과 만들기

최씨·2025년 6월 1일
28

Frontend

목록 보기
11/12
post-thumbnail

⏰ 5분만 투자하면 아래 내용을 알 수 있어요!

☑️ Glitch 효과란 무엇인지.

☑️ Glitch 효과 구현을 위한 핵심 CSS 속성들.

☑️ Glitch 효과를 단계별로 구현하는 방법.


🍀 시작

요즘 틈틈히 개인 페이지를 만들고 있습니다.
우주 컨셉으로 구성 중인데, 글자 부분이 정적인게 아쉬웠습니다.

그러다, 텍스트에 지지직 거리는 애니메이션 효과를 추가하면 예쁘겠다는 생각이 들었습니다.
찾아보니 이 효과를 Glitch 효과라고 하더라고요.

버그가 발생하면 화면이 지직거리는 일이 많기 때문에 이런 지직거리는 화면을 “글리치 스크린(화면)”이라고 부르기도 합니다. 이것이 이미지 편집에서는 “글리치 스크린”을 의도적으로 발생시키는 이펙트를 지칭하는 ”글리치” 효과로 불리고 있습니다.

생각보다, 글리치 효과는 종류도 다양하고, 구현 난이도도 천차만별이었습니다.

23 CSS Glitch Effects → 여기에 여러 종류가 잘 나와있습니다.

단순 종류만이 아니라, 각각 HTML, CSS 코드로 쉽게 구현한 코드가 같이 들어있어서 이해하기 좋습니다.
그 중에서도 제가 원한 것은 가로로 지지직 거리는 효과입니다.

필요 지식 부터 가볍게 알고, 구현해보겠습니다.


🍀 필요한 지식

  • @keyframes

    • CSS에서 애니메이션의 동작 흐름을 정의합니다.

    • 시간(%)에 따라 어떤 스타일 변화가 일어날지를 순차적으로 지정합니다.

    • 여기서는 텍스트 X축에 기울기(skewX) 효과를 줘서 흔들리는 애니메이션을 연출합니다.

    • MDN - skewX() -> 여기서 skewX()에 대한 자세한 예시를 더 확인할 수 있습니다.

      @keyframes wiggle {
        0% { transform: skewX(0deg); }
        100% { transform: skewX(20deg); }
      }
  • animation

    • 애니메이션을 요소에 실제로 적용합니다.

    • 어떤 @keyframes를 사용할지, 몇 초 동안, 몇 번 반복할지를 지정합니다.

    • ex) animation: wiggle 3s infinite;

      → 3초 간격으로 따로 설정한 wiggle이라는 동작이 무한(infinite)히 반복됩니다.

  • transform

    • 요소에 회전, 기울기, 크기 조정 등의 2D/3D 변형을 적용합니다.

    • 여기선 skewX(deg)를 사용해 텍스트를 좌우로 기울입니다.

    • ex) transform: skewX(-20deg);

  • text-shadow

    • 텍스트에 그림자를 주는 속성입니다.

    • 그림자 위치(x, y), 색상, 투명도를 다양하게 조절해 입체감 또는 중첩 효과를 만들 수 있습니다.

    • Glitch 효과에선 같은 글자를 여러 색상으로 겹쳐 보이게 하기 위해 사용합니다.

    • ex) text-shadow: 0.3rem 0.1rem red, -0.2rem -0.1rem blue;


🍀 구현

✏️ animation 설정

먼저 정적인 글자를 하나 만들어줍니다.

기본 세팅은 다음과 같습니다.

GlitchText.tsx

import "./GlitchText.css";

const GlitchText = () => {
  return <div className="glitch-text">Welcome To Choi Space</div>;
};

export default GlitchText;

GlitchText.css

.glitch-text {
  font-size: 2rem;
  margin-bottom: 5rem;
  color: white;
}

글자에 애니메이션 효과를 주려면 css에서 animation 속성을 주면 됩니다.

.glitch-text {
	...
  animation: wiggle 3s infinite;
}
  • 맨 밑에 animation: wiggle 3s infinite; 이 한 줄이 추가됐습니다.

  • animation을 주겠다고 선언한 것이고 : 뒤에 오는 방식으로 선언하겠다고 정의한 것입니다.

  • wiggle은 우리가 직접 정의할 애니메이션 이름이고, 3s는 지속 시간, infinite는 무한 반복입니다.


그렇다면 제가 직접 만든 wiggle을 선언해야겠죠.
(wiggle 이름은 고정이 아니라, 아무거나 원하는 이름으로 하면 됩니다.)

@keyframes wiggle {

}
  • 이렇게 따로 @keyframes로 wiggle을 만들어줬습니다.

이제 이 안에서 어떻게 적용할지를 커스텀해보겠습니다.
(설명을 위해 간단한 예시로 만들었습니다.)

@keyframes wiggle {
  0% {
    transform: skewX(0deg);
  }
  100% {
    transform: skewX(45deg);
  }
}

  • 먼저 0% 일때는 애니메이션이 동작하는 3초에서의 0% 이므로 0초일 때 이고, 100%는 3초에서의 100%이므로 3초일 때 입니다.

  • 이때 skewX 라는 속성을 사용해서 현재 위치에서 각도로 몇도 기울여질지를 정해주면 됩니다. 그 안의 deg는 각도의 단위인 ‘도’라고 생각하면 됩니다. 그러면 여기서는 0% 일때 0도에서 시작해서 45까지 3초에 걸쳐서 반시계 방향으로 서서히 기울어진다고 선언한 것입니다.

  • 3초간 애니메이션이 동작하고, 이후에는 이것을 무한 반복합니다.


0%와 100% 사이에 다른 각도도 추가해 보겠습니다.

@keyframes wiggle {
  0% {
    transform: skewX(0deg);
  }
  80% {
    transform: skewX(-45deg);
  }
  100% {
    transform: skewX(45deg);
  }
}

  • 애니메이션이 3초로 설정해 두었으니, 80%이면 2.4초일때 입니다.

  • 그럼 0~2.4초까지는 시계방향으로 0도에서 45도로 서서히 기울어지고, 2.4초에서 3초까지는 반시계 방향으로 총 90도가 (45 - (-45) = 90) 기울어지게 되겠네요.

  • 여기서, 시계방향으로 2.4초간 45도 기울어지는 것보다 0.6초간 반시계 방향으로 90도 기울어지는게 더 빠르게 기울어지는 것도 볼 수 있습니다.


각도를 좀 더 꺽어보겠습니다.
100%일때의 각도를 45도에서 90도로 더 크게 키웠습니다.

@keyframes wiggle {
  0% {
    transform: skewX(0deg);
  }
  80% {
    transform: skewX(-45deg);
  }
  100% {
    transform: skewX(90deg);
  }
}

  • 글자가 90도로 아예 누워질때 길~게 보이면서 좀 더 역동적이게 되는 것을 볼 수 있습니다.

이제 원리는 다 했으니,
중간 %와 각도를 좀 다양하게 적용해서 wiggle을 완성해보겠습니다.

@keyframes wiggle {
  0% {
    transform: skewX(24deg);
  }
  2.5% {
    transform: skewX(-8deg);
  } 
  5% {
    transform: skewX(55deg);
  }
  7.5% {
    transform: skewX(-90deg);
  }
  10% {
    transform: skewX(29deg);
  }
  12.5% {
    transform: skewX(-90deg);
  }
  15% {
    transform: skewX(3deg);
  }
  17.5% {
    transform: skewX(-2deg);
  }
  20% {
    transform: skewX(1deg);
  }
  22.5% {
    transform: skewX(10deg);
  }
  100% {
    transform: skewX(0deg);
  }
}

원래는 그럴듯하게 지지직 거리는데 gif로는 프레임 한계가 있네요 ㅠㅠ

(한 번 직접 구현해서 확인해 보세요!!!)

  • 저는 계속 움직이는 글자보다는, 지지직 거렸다가 잠깐 원래 글자로 돌아오고, 이후 또 지지직 거리는 모습을 원했습니다.
  • 그래서 22.5% 정도까지 애니메이션을 주고 이후는 큰 애니메이션 없게 세팅했습니다.

만약 애니메이션을 좀 더 천천히 동작시키고 싶다면 아까 animation 속성에서 초수를 길게 하면 됩니다.
바로 위 코드는 3s로 설정이 되어있는데, 밑처럼 30s로 설정한다면 더 느리게 동작합니다.

.glitch-text {
	...
  animation: wiggle 30s infinite;
}


✏️ text-shadow 설정

그런데 뭔가 밋밋하지 않나요?

밑의 예시를 보면 뭐가 필요한지 느껴질 것 같습니다.

저는 단일 색상인 흰색으로 글자에 애니메이션을 줬는데,
이처럼 지지직 거릴때 여러 색상의 같은 글자가 겹쳐야지 좀 더 우리가 아는 모습이면서 그럴듯 합니다 ㅎㅎ

이 부분은 CSS에서 text-shadow 속성을 통해서 구현할 수 있습니다.
원래 이 속성은 일반 글자들에 대해서 3D처럼 입체적으로 보여주기 위해서 주로 사용하는 것입니다.

위 사진이 text-shadow를 적용한 글자인데, 그림자 색상으로 설정해서 입체적으로 보이게 한 것을 확인할 수 있습니다.


이것을 활용해서 글리치 효과에 활용해 보겠습니다.
일단 text-shadow만 확인해 보기 위해 animation은 주석처리하고 구현해 보겠습니다.

.glitch-text {
  font-size: 2rem;
  margin-bottom: 5rem;
  color: white;
  /* animation: wiggle 30s infinite; */
  text-shadow: 0.5rem 1rem red;
}

  • text-shadow: (x축으로 이동할 거리) (y축으로 이동할 거리) (색상)

  • 위와 같은 구조로 되어있고, 기본적으로 x축 양수는 우측, y축 값 양수는 아래로 움직입니다.

  • 또한 기본 색상인 white가 가장 위에 있게 됩니다.


그림자를 하나 더 추가해 보겠습니다.

.glitch-text {
  font-size: 2rem;
  margin-bottom: 5rem;
  color: white;
  /* animation: wiggle 30s infinite; */
  text-shadow: 0.5rem 1rem red, -0.8rem -1.2rem blue;
}

  • 겹치는 글자의 순서는 원래 글자가 가장 위고, 그 뒤는 text-shadow에서 선언된 순서대로 위에 보이게 됩니다.
    원래 글자 > red > blue

동작 방식은 다 알았으니, 원하는 모습으로 설정해 보겠습니다.

.glitch-text {
  font-size: 2rem;
  margin-bottom: 5rem;
  color: white;
  /* animation: wiggle 3s infinite; */
  text-shadow: 0.3rem 0.1rem rgba(189, 33, 106, 0.8),
    -0.2rem -0.1rem rgba(255, 145, 0, 0.8), -0.3rem 0rem rgb(88, 75, 238);
}

  • 저는 3개의 그림자를 아주 조금만 겹치게 해줘서, 흐릿한 모양으로 만들었습니다.

  • 또, 원하는 디테일한 색상을 위해 rgba 값을 사용했습니다.


이제 주석 처리해 둔 animation 값을 풀어보겠습니다.

.glitch-text {
  font-size: 2rem;
  margin-bottom: 5rem;
  color: white;
  animation: wiggle 3s infinite;
  text-shadow: 0.3rem 0.1rem rgba(189, 33, 106, 0.8),
    -0.2rem -0.1rem rgba(255, 145, 0, 0.8), -0.3rem 0rem rgb(88, 75, 238);
}

  • 얼추 다 했군요!

  • 아래 CodePen을 통해 직접 다뤄보세요!


✏️ (선택) 폰트 설정

글리치 효과와 직접적으로 관련은 없지만,
효과에 어울리는 폰트를 적용하면 시각적인 완성도를 높일 수 있습니다.


✏️ 작은 트러블슈팅

글리치 효과가 적용될 때, 순간적으로 스크롤바가 생겼다가 사라지는 현상이 있었습니다.
짧은 순간이지만, UX적으로 상당히 별로였습니다.

이는 애니메이션으로 인해 요소의 가로/세로 크기가 일시적으로 확장되면서 발생한 현상으로,
화면 밖으로 튀어나간 부분을 숨기기 위해 overflow: hidden 속성을 적용했습니다.

body {
  overflow: hidden;
}

최종적으로는 다음과 같은 결과가 나왔습니다 :)
(실제 화면은 더 그럴듯하게 지직입니다!)


🍀 결과

복잡한 애니메이션은 그동안 주로 AI의 도움을 받아 적용했는데,
이번에는 CSS 속성 하나하나의 의미와 수치 변화를 직접 이해하고 구현해보니 정말 재미있었습니다.
생각보다 간단해서 더 그렇게 느껴졌던 것 같고요.

어찌보면 이런 것의 프론트의 묘미가 아닐까란 생각이 듭니다.
물론, 제가 구현한 글리치는 여러 효과 중 가장 쉬운 축에 속하지만
입문용으로 감을 잡기엔 정말 좋은 예제였다고 생각합니다.

긴 글 읽어주셔서 감사합니다 :)


🌐 참고 자료

profile
정답은 없지만, 가까워지려고 노력하고 있습니다 :)

2개의 댓글

comment-user-thumbnail
2025년 6월 1일

재밌게 잘 읽었습니다! css로 정말 다양한 걸 할 수 있구나 생각했는데 결과물을 만들어가는 과정까지 있으니까 저도 한번 해봐야겠다 생각이 드네요.

1개의 답글