[Portfolio] 스크롤 시 색상 변경하기

yujin·2025년 11월 13일

프로젝트

목록 보기
22/26
post-thumbnail

⭐ page.tsx, 각 섹션 변경하기

1: 준비

  1. 배경색 상태관리 (useState): 지금 현재 배경색을 기억하고, 그 색을 바꿀 수 있는 setBgColor를 만든다. 초기값은 #111827로 설정한다.

    const [bgColor, setBgColor] = useState('#111827');
  2. 각 섹션별 useRef 7개: 'Home', 'About' 등 7개 섹션에 각각 붙여줄 빈 이름표(ref)를 만든다. 이 이름표의 .current 속성은 null이다.

    const sectionRefs = {
        home: useRef<HTMLElement>(null),
        about: useRef<HTMLElement>(null),
        // ... (총 7개)
    };
    • useRef: 'React야, 빈 상자를 하나 만들어줘.
    • (null): '이 상자의 초기값은 null이야.
    • <HTMLElement>: "그리고 이 상자의 .current 에는, 나중에 HTMLElement 타입의 객체만 담을 거야!"

2: 각 섹션에 ref를 전달한다.

  • page.tsxreturn 문 안에서, 7개의 섹션 컴포넌트를 호출하며, 1에서 준비한 '이름표'(ref)를 각자에게 나눠준다.

3: 각 섹션이 '이름표'를 붙이고 배경색을 설정한다.

  • 각 섹션 컴포넌트는 ref를 받아서, 자신이 그리는 실제 <section> HTML 태그에 ref={ref} 코드로 부착한다.
  • 동시에, 그 <section> 태그에 data-color="#111827" 속성을 추가한다.

4: 스크롤 센서 (useEffect)가 'ref'가 붙은 실제 태그들을 감시한다.

  • page.tsx가 처음 렌더링을 마친 직후, useEffect(..., []) ('딱 한 번만 실행')가 실행된다.

    • "스크롤 센서"(new IntersectionObserver)를 만든다.
    • 이 센서에게 "만약 감시하던 게 50% 보이면(isIntersecting), 그 녀석의 data-color 값을 읽어서 setBgColor로 state 값을 설정한다.
    • sectionRefs 7개를 모두 뒤져서, .current에 실제 태그가 채워진 것들을 찾아낸다.
    • 센서에게 이 7개의 실제 태그들을 지금부터 observe 감시하라고 명령한다.

코드 설명 1

// 콜백 함수 시작: 스크롤 센서가 감지한 항목들의 배열(entries)을 받는다.
(entries) => {
    // 발견된 항목들(entries)을 하나씩 순회한다.
    entries.forEach((entry) => {
      
      // 화면에 들어왔는지(Intersecting) 확인한다
      if (entry.isIntersecting) {
        
        // 실제 HTML 태그(target)에서 'data-color' 속성값을 읽어온다.
        const color = entry.target.getAttribute("data-color");
        
        // 만약 유효한 색상값(color)이 존재하면
        if (color) {
          // page.tsx의 상태(State)를 변경하여 리렌더링을 유발한다.
          setBgColor(color); 
        }
      }
    });
},
// 센서 민감도 설정 50%가 보여야 작동한다.
{ threshold: 0.5 }

코드 설명 2

// 이름표 상자들만 모두 배열로 추출한다.
const refs = Object.values(sectionRefs);

// 추출된 이름표 상자들(ref)을 하나씩 확인한다.
refs.forEach((ref) => {
  
  // 만약 이 이름표 상자 안에 실제 HTML 태그가 채워져 있다면
  if (ref.current) {
    
    // 스크롤 센서(observer)에게 이 실제 태그를 감시하기 시작하라고 한다.
    observer.observe(ref.current);
  }
});

  • Object.values(...):객체에서 값들만 뽑아내서 배열로 만들어준다.
// sectionRefs의 모양 (객체)
{ 
  home: { current: <section id="home"> },
  about: { current: <section id="about"> },
  // ...
}


// refs의 모양 (배열)
[ 
  { current: <section id="home"> },
  { current: <section id="about"> },
  // ...
]

5: 배경색 상태가 바뀔 때마다 실제 배경을 바꾼다.


전체 흐름의 완성:
1. 사용자가 스크롤한다.
2. About 섹션이 50% 보인다.
3. 스크롤 센서(Observer)가 감지하고 setBgColor("#1f2937")를 호출한다.
4. page.tsx가 리렌더링된다. (bgColor의 '현재 값'이 #1f2937로 바뀐다.)
5. 리렌더링이 끝난 직후, 배경색 변경 useEffect 함수(useEffect(..., [bgColor]))가 실행된다.
6. document.body.style.backgroundColor = "#1f2937"이 실행된다.
7. 결과: 사용자는 배경색이 바뀌는 것을 본다.


🩷 결과

  • 화면

0개의 댓글