프로젝트 기술 스택
- Next.js 16, zustand 5
이야기에 필요한 부분만 작성했다.
결론
페이지 이동시 이전 전역 상태(Store) 값이 사용되어 발생 된 에러를 조건문으로 방지
원인
React 화면 업데이트 순서(라이프사이클) 이해도 부족
AI에게 문제상황을 맡김
디자인패턴 시각화(애니매니션) 프로젝트를 진행 중이다. URL의 값을 통해 각 패턴을 특정하여 화면에 정보를 업데이트하는 과정을 거치게 된다.
예를 들어, /structural/adapter, /creational/builder 처럼 /structural/[pattern], /creational/[pattern]의 형태를 가진다.
이때 [pattern] 파라미터를 사용하여 해당 패턴의 정보를 Store에서 갱신하도록 하였다.
문제는 각 패턴에 방문을 하면서 발생했다. 페이지를 이동하면 첫 방문은 정상이지만 두번째 부터 에러를 보였다. AI에게 관련 컴포넌트 파일을 전달하며 문제를 찾아달라고 했으나 새로운 컴포넌트를 만들어 낼 뿐 원인을 찾거나 해결하지 못했다. AI에 맡겼던 이유는 useEffect를 사용해 Store를 관리하는 부분이 명확했기 때문에 알아서 처리를 해주리라 믿었기 때문이다.
그러나, 컴포넌트의 복잡도를 올리는 행위가 반복될 뿐이였고 직접 뜯어 보았다. console.log를 통해 어디까지 값이 전달되었는지 정확히 파악하고 문제 상황을 단순화 할 수 있었다.
요청에 필요한 정보는 전달되었으나 이전의 Store 정보를 사용하는 것이였다. 즉, 갱신이 되지 않았다.
패턴마다 방식에 차이가 있기 때문에 애니매니션도 서로 다른 데이터가 존재한다. 접근한 패턴에 대한 정보로 애니매니션을 렌더링 하는 것이 아니라 이전의 방문했던 패턴의 애니매니션 정보로 렌더링을 하면서 없는 속성에 접근할 때 에러가 발생하게 된 것이다.
아래는 원인 찾기위해 시작부터 에러발생 순간까지의 단계를 작성했다.
useEffect로 갱신이 될 줄 알았던 데이터가 시도조차 못하고 종료되고 있던 것이다.
1. Singleton 페이지 진입 (/creational/singleton)
2. Builder 페이지 진입(/creational/builder)
3. creational/[pattern] 경로 진입
4. page.tsx 진입
5. params로부터 `builder`키워드 확인
6. `return`을 PatternPage 컴포넌트 생성하러 출발
7. PatternPage는 `category, patternId`을 인자로 받음. category=creational, patternId=builder 할당됨
8. 로직을 거쳐 isImplemented=true 면 `PatternPageClient` 컴포넌트를 생성하러 출발
**중요**
9. 처음 `PatternPageClient` 컴포넌트로 들어 왔을 때 patternId=builder, selectedPatternId=singleton 할당되는 것을 확인. 코드를 읽어 내려가다 33번 라인에서 useEffect 처리를 해야하는데 라이프사이클 순서상 렌더링 이후에 실행됨.
10. 이어서 48번 라인부터 진행
11. 63번라인에서 patternId=builder 할당되었으므로 BuilderVisualizer 컴포넌트 받아옴
12. 반환을 위해 Visualizer(BuilderVisualizer) 생성하러 출발
13. patternData는 patternId를 통해 builder의 정보가 넘어 온 상태
**문제 발생 원인**
14. usePatternVisualizer() 호출시 아직 store는 **Singleton**의 정보를 가지고 있음. useEffect는 렌더링 이후 실행 되기 때문
15. 이 상태로 PatternVisualizerLayout 생성하러 출발 인수로 `animation`에 `BuilderAnimation` 컴포넌트를 받음. 이 컴포넌트는 state 인자가 필요한데 이때 store에 있던 singleton의 visualizer를 받게됨
16. `PatternVisualizerLayout`에서 58번 라인에서 다른 정보가 담긴 채로 리턴
** 에러 발생 순간 **
17. 이제 화면을 렌더링 하는 중에 `PatternVisualizerLayout` 58번 라인을 렌더링 하는데 `BuilderAnimation`을 생성 중 맞지 않은 visualizer로 렌더링을 시도하여 에러 발생
18. useEffect를 실행 조차 못하고 에러를 보게 됨
개선을 위해 요청값과 현재값이 다를 경우 렌더링을 하지 않도록 null을 리턴하는 방법을 취하여 첫 렌더링을 건너뛰게 하였다.
렌더링 이후 useEffect로 Store를 갱신한 후 변경된 데이터로 화면을 렌더링하여 원하는 화면을 보이도록 하였다.
fallback UI를 띄울 수도 있지만 깜박이는 화면이 보기 좋지 않아 빈 화면이 보이도록 했다.
Next.js 프레임워크는 React 라이브러리 기반으로 CSR의 렌더링 과정이 동일하다.
- 렌더(render)
- DOM 반영
- 브라우저 페인트(paint)
- useEffect 실행
- 의존성 배열의 값 변경 감지 시 1번 부터 다시 수행
이번에 발생한 문제는 렌더링 과정 중에 에러가 발생하여 뒷 단계를 수행하지 못했다는 점이다. 아래는 도식화한 부분이다.

step 2에서 Error 발생하여 뒷 단계를 수행하지 못하여 다음과 같이 수정한 것이다.

솔직히 얘기하면 굉장히 허무한 엔딩이다. 조건문 하나면 해결가능한 사안을 장황하게 늘어 놓은 것 뿐이라 코드를 제대로 해석하지 않은 탓이 가장 큰 원인이라고 볼 수 있다.
2시간 동안 AI와의 씨름이 디버깅 30분만에 해결되었다. 바이브 코딩을 하며 생산성은 분명 증대되었고 다양한 개발을 시도해 볼 수 있는 기회를 갖출 수 있었다.
이번 기회로 코드 해석의 중요성과 사용하는 기술에 대한 이해도가 정말로 중요하다는 것을 느낀다.
프롬프트 한번으로 방대한 양의 코드가 생성이 된다. AI가 만든 결과물에 대해 이해하려면 왜 이렇게 설계를 했고 다른 대안은 없었는지 고민하는 훈련으로 잘 만들어졌는지 판단할 수 있을거 같다. 그러기 위해서는 사용하는 기술에 대해서 지식이 갖춰야 분별할 수 있다는 배움을 얻는 계기가 되었다.
다른 관점에서는 하나의 개념만 사용하면 문제 없었지만 2개 이상의 개념이 사용되면 어떤 부수적인 효과가 발생할지 고려해야 한다는 것도 알 수 있었다.