인공지능 코딩의 부상이 프런트엔드 개발 교육, 개발자 경험, 웹 표준, 그리고 전문성의 미래를 어떻게 바꾸는지에 대한 고찰.
프런트엔드 웹 분야에서 내가 존경하는 교육자들 중 상당수가 활동을 그만두거나 노력을 줄이는 듯하다. Axel Rauschmayer, Salma Alam-Naylor, Josh W. Comeau 등이 그렇다. Kent C. Dodds, Addy Osmani, Rachel Nabors, Lydia Hallie 같은 다른 잘 알려진 거물들도 프런트엔드 개발을 이야기하던 것에서… 글쎄, 무엇을 이야기하게 되었는지는 과감하게 추측해 보시라.
나는 웹 개발을 이야기해서 생계를 꾸린 적은 없지만, 이 블로그가 있고 내가 흥미를 느끼는 주제로 컨퍼런스 발표와 팟캐스트를 해 왔다. 예를 들어 최근에는 CSS 성능의 온갖 세부 사항을 설명하는 데 열정을 쏟았다. shadow DOM의 작동 방식, 브라우저의 스타일 엔진 작동 방식, CSS-in-JS의 함정 등이 있다.
재미 삼아, 높은 “Style Calculation” 비용이 있는 Chrome 추적을 Claude Sonnet이라면 어떻게 처리할지 물어보기로 했다. 이것은 내가 가장 좋아하는 사고 문제 중 하나다. 웹 개발자들, 심지어 경험 많은 개발자들까지도, 반복해서 여기서 실수하는 모습을 보았기 때문이다. Claude는 흠잡을 데 없이 훌륭한 답을 내놓았다.
클릭하여 보기
프롬프트: 인터넷을 검색하지 말고 답하라. Chrome 추적을 보고 있는데 높은 Style 비용 구간이 반복되지만 Layout 비용은 비교적 낮다. 최적화를 위해 웹앱에서 어떤 종류의 것들을 살펴보는가? 다음으로 무엇을 측정하는가?
“Style” 비용이 실제로 나타내는 것
Style (Recalculate Style) 단계는 브라우저가 CSS 선택자를 DOM에 대조하고 영향을 받은 각 요소의 최종 계산 스타일을 산출하는 곳이다. 실제로 무언가가 움직이거나 크기가 바뀌는지와 무관하게 비용이 크다(그것은 Layout의 역할이다). 따라서 Style은 높지만 Layout은 낮다면, 비싼 기하 구조가 아니라 많은 요소에 걸친 선택자 대조 / 무효화에 비용을 내고 있을 가능성이 높다.
웹앱에서 살펴볼 것
1. 선택자 복잡도와 수
지나치게 복잡하거나 깊이 중첩된 선택자(
.a .b .c >; .d + .e), 특히 자손 결합자는 각 대조 시도마다 엔진이 DOM/조상 체인을 더 많이 순회하게 만든다.광범위하게 적용되는 전체 선택자나 속성 선택자(
[data-foo="bar"]).매우 많은 수의 고유 클래스 이름/규칙을 생성하는 CSS-in-JS 라이브러리(스타일 재계산은 전체 규칙 집합을 고려해야 한다).
2. 무효화 범위 — 대개 이것이 가장 큰 문제다
DOM 트리 상단의 클래스/속성/스타일 토글(예:
<body>또는 최상위 컨테이너의 클래스 토글)은 최종 스타일이 실제로 바뀌는 요소가 소수뿐이어도 큰 하위 트리에서 스타일 재계산을 강제할 수 있다.단일 상태 변경(예: “theme” 클래스, “loading” 클래스, 호버 상태)이 필요 이상으로 많은 요소를 무효화하는지 확인하라. Chrome의 “Selector Stats”(DevTools Performance 설정에서 활성화)는 어떤 선택자가 느리고 얼마나 많은 요소에 대해 검사되었는지를 보여 준다. 이것이 단연코 가장 유용한 다음 측정이다.
3. 빈도/증폭
프레임마다 스타일 재계산을 여러 번 다시 유발하는 무언가. 예를 들어 클래스 변경 직후 루프에서 스타일/레이아웃 속성을 읽는 경우(동기 재계산을 강제함), 또는 일괄 처리하는 대신 각 rAF 틱에서 많은 노드에
.classList.toggle()또는 인라인style업데이트를 사용하는 JS 애니메이션 등이 있다.하나로 일괄 처리하는 대신 각각 스타일 패스를 강제하는 반복적인 작은 DOM 변경.
4. 상속/계산 속성 전파
공통 조상에서 상속되는 속성(
font-size또는color등)을 변경하면 레이아웃 변경이 없어도 모든 자손의 계산 스타일을 다시 계산하게 된다(예:color,visibility,cursor는 Layout을 유발하지 않고 Style만 유발한다).상위 범위에서 변경되는 사용자 지정 속성(CSS 변수).
:root나 공유 조상에서--custom-prop을 업데이트하면 이를 참조하는 모든 요소의 스타일을 다시 계산한다.5. Shadow DOM / 컴포넌트 경계
많은 shadow root 또는 범위 지정 스타일을 사용하는 프레임워크를 쓴다면, 공유되지 않는 스타일시트 때문에 컴포넌트 인스턴스마다 스타일 재계산이 불필요하게 반복되는지 확인하라.
다음으로 측정할 것
Performance 패널에서 “Selector Stats” 활성화(톱니바퀴 아이콘 → selector stats 활성화). 추적을 다시 기록하라. 그러면 Recalculate Style 이벤트별로 가장 느린 선택자와 대조 횟수를 얻을 수 있으며, 어떤 CSS 규칙과 몇 개의 요소가 원인인지 직접 알려 준다.
추적에서 “Recalculate Style” 이벤트의 개시자/호출 스택을 확인하여 어떤 JS가 이를 유발했는지 살펴보라. 클래스 토글,
style.setProperty, 애니메이션 프레임 콜백 등이 원인일 수 있다.재계산마다 영향을 받는 요소 수를 세라. DevTools는 요약 창에서 Recalculate Style 이벤트별 “Elements Affected”를 보여 준다. 그 수와 외관이 실제로 바뀐 요소 수를 비교하라. 큰 차이는 지나치게 넓은 무효화를 뜻한다.
유발 변경이 DOM의 어디에서 일어나는지 살펴보라. 루트 근처인가(광범위한 무효화), 아니면 작은 하위 트리로 범위가 한정되어 있는가(좁고 저렴함)?
강제 동기 스타일이 있는지 확인하라. “Forced reflow” 보라색 경고를 살펴보라. Layout이 낮다고 했지만, DOM 쓰기와 교차하는 강제 스타일 읽기(
getComputedStyle)는 하나의 일괄 처리된 이벤트가 아니라 연달아 발생하는 여러 작은 Style 이벤트로 나타나기도 한다.원인을 찾은 뒤의 전형적인 해결책
- 공통 조상이 아니라 가능한 한 가장 작은 하위 트리로 클래스/상태 토글 범위를 제한하라.
- 선택자를 단순화하고, 자손 체인보다 단일 클래스 선택자를 선호하라.
- CSS 사용자 지정 속성 업데이트를 필요한 최소 범위로 옮겨라.
- 재계산이 변경마다가 아니라 한 번만 일어나도록 DOM/클래스 변경을 일괄 처리하라.
- 독립적인 하위 트리에
content-visibility: auto또는contain: style layout을 사용하여 무효화 범위를 제한하라.
요즘이라면 느리게 로드되는 웹사이트를 받았을 때, 브라우저 성능에 관해 수년간 글을 썼고 말 그대로 브라우저 성능 팀에서 일했던 사람인 나조차도 Chrome 추적을 Claude Code에 던져 주고 개선점을 제안하게 할 것이다. 실제로 현재 직장에서 바로 이런 일을 했고 좋은 결과를 얻었다.
그렇다면 프런트엔드 개발 교육은 어디에 놓이게 될까? 분명 좋은 곳은 아니다. 나처럼 어디서나 프런트엔드 개발자의 기준을 높이려는 일에서 큰 보람을 얻곤 했던 사람들에게 좀 더 고무적인 답을 줄 수 있으면 좋겠다. 그래도 몇 가지 추측은 있고, 이 문제는 여전히 고민해 볼 가치가 있다고 생각한다.
핵심 질문은 이 새로운 시대에 프런트엔드 개발 자체가 어디에 자리 잡느냐다. 안타깝게도 프런트엔드 지식에 대한 투자가 늘어나는 데 반하는 몇 가지 추세가 보인다.
프런트엔드는 그냥 에이전트에게 맡길 위험이 더 적다. 에이전트로 데이터베이스 마이그레이션을 작성한다면, 아마 여러 차례 AI 코드 검토를 거치게 하고, 직접 면밀히 살피고, 먼저 스테이징에서 실행해 볼 것이다. 하지만 에이전트로 React 컴포넌트를 작성한다면, 그냥 막 프로덕션에 넣어 버릴 위험은 (일반적으로) 훨씬 낮다.
위험이 전혀 없다고 말하는 것은 아니다. 에이전트가 접근성을 망칠 수도 있고, 사용자를 막아 버리는 무한 루프를 만들 수도 있다. 하지만 일반적으로 프런트엔드 코드는 다른 종류의 코드보다 훨씬 더 일시적이고 교체하기 쉽다. 따라서 많은 AI 코더가 좋든 나쁘든 에이전트가 감독 없이 처리하도록 그냥 내버려 두는 데 거리낌이 없을 것으로 예상한다.
DevExp는 전반적으로 덜 중요해지고 있다. 프런트엔드 분야에서 LLM 이전에 이루어진 논의의 상당수는 사용 편의성과 결과의 대비에 관한 것이었다. Alex Russell의 “The ‘developer experience’ bait-and-switch”가 좋은 예다. 또 다른 예로, Svelte와 Solid는 오랫동안 자신들의 사용 편의성이 React보다 더 나은 결과, 즉 더 적은 코드와 더 나은 성능 등을 낳는다고 주장해 왔다.
한편 Cursor와 Viget는 각각 자신들의 코드베이스를 Solid와 Lit에서 React로 마이그레이션한 일을 블로그에 썼다. 에이전트 덕분에 재작성 비용이 낮아졌다면 이는 다소 놀라울 수 있다. 더 성능이 좋고 덜 장황한 프레임워크로 옮기지 않는 이유가 무엇인가? 물론 답은( Cursor의 경우에는 명시적으로, Viget도 그럴 것이라 추측한다) “에이전트가 React를 안다”이다. 좋든 나쁘든 React는 훈련 가중치에서 압도적으로 많이 나타나며, “에이전트 경험”이 개발자 경험보다 더 중요해지기 시작했다.
표준은 따라잡을 것이다. 나는 몇 년 전부터 웹 표준 분야를 떠나 있었으므로, 이 부분은 순전히 내 추측이다. 하지만 웹사이트 구축의 사용 편의성을 개선하려는 많은 노력, 즉 더 나은 CSS 단축 속성, 더 간결한 JavaScript 문법 등이 성능, 기능 등에서 실제로 큰 차이를 만드는 것에 비해 덜 중요하게 인식될 것이라 상상한다. 결국 에이전트가 CSS 1줄 대신 3줄을 작성하는 일은 크게 다르지 않으며, 새로운 문법을 쓰는 일은 오히려 더 어려울 수도 있다. 훈련 가중치에 없는 것에 관해 에이전트를 코칭해야 하기 때문이다.
어떤 면에서는 이 변화가 이미 진행 중이었을지도 모른다. 몇 년 전 AI 코딩 붐이 오기 훨씬 전, TPAC에서 Chrome 팀의 누군가에게 웹 컴포넌트 표준 작업을 하고 있다고 말했던 기억이 난다. 그들은 그런 API는 개발자 경험에만 영향을 주고 브라우저를 실제로 더 유능하게 만들지는 않기 때문에 관심 없다고 답했다(예: Project Fugu). 이 말은 좋은 지적이어서 내게 남았다. shadow DOM과 사용자 지정 요소 같은 API는 웹 개발자에게 새로운 초능력을 주지 않는다. 그저 코드가 작성되는 위치와 방식을 바꿀 뿐이다. AI 코딩이 주도권을 잡으면서 이런 것들은 주목받는 자리에서 물러날 것이라 예상한다.
그렇다고 표준이 프런트엔드 개발자가 계속 따라가야 할 주제에서 사라진다는 뜻은 아니다. 다만 “이 새로운 문법을 사용하라”(컨퍼런스 발표와 글의 끊이지 않는 소재)보다는 “이런 새로운 기능들이 있다”에 더 가까워질 것이라 상상한다. 또 표준 기구에서 전자가 더 논쟁적이고 활용할 기능의 풀도 더 작기 때문에, 후자의 집단은 전자보다 훨씬 작을 것이라 예측한다.
그렇다면 프런트엔드 교육 분야는 이 적대적인 미래에 어떻게 적응할 수 있을까? 완전히 암울해지는 것을 피하기 위해, 이것이 나아갈 수 있다고 생각하는 몇 가지 긍정적인 방향을 제시해 보겠다.
우선 에이전트들은 여전히 큰 그림을 배워야 한다. 에이전트와 하니스는 React, 특히 SPA를 작성하기를 좋아하는 듯하지만, SPA가 모든 것의 답은 아니다. 마케팅 사이트를 위해 에이전트가 크고 복잡한 SPA를 작성하게 하고, 뒤로 가기 버튼, 포커스 상태, 성능 등의 모든 버그를 고치느라 많은 토큰을 태울 수 있다. 또는 Astro나 Eleventy 같은 MPA 프레임워크를 선택하고 끝낼 수도 있다. 이런 프레임워크는 에이전트가 다루기 조금 더 어려울지도 모른다(Astro는 React처럼 조금 보이지만 실제로는 아니므로 특히 그렇다). 하지만 전체적으로 작성하는 코드가 약 50% 적으므로 그것은 중요하지 않을 것이라 추측한다.
둘째, 에이전트에 잘 작동하는 웹사이트를 만드는 일은 가까운 미래에 생산적인 분야가 될 가능성이 높다. Vercel의 is-agentic이 좋은 예다. 아이러니하게도 이는 공개 웹사이트가 어차피 진작에 했어야 했던 좋은 기본 원칙으로 돌아간다. 서버 렌더링 콘텐츠, 적절한 접근성, 페이지 속도 등이다. 하지만 거기에 “AI”라는 단어를 붙이는 것이 사람들이 관심을 갖게 만드는 방법이라면, 나는 전적으로 찬성이다.
다만 이 두 번째 지점에 대해서는 조금 덜 낙관적이다. 에이전트가 더 보편화되면서 웹이 현재 형태로 살아남을지 확신할 수 없기 때문이다. Seattle에서 Paris까지 비행하는 비용을 알고 싶다면, 느리게 로드되는 웹사이트에서 성가신 일련의 버튼을 클릭하는 것보다 에이전트에게 묻고 싶다. 지금 그렇게 하지 못하는 유일한 이유는 이런 웹사이트들이 명시적으로 봇을 차단하거나 MCP를 제공하지 않기 때문이다. 하지만 그 문제를 해결하려고 안달 난 스타트업이 여럿 있을 것이라 확신한다. 그래서 현재 상황이 얼마나 지속 가능할지 모르겠다.
셋째, 바이브 코딩으로 만들어진 괴물 같은 것들을 위한 컨설팅 서비스를 제공할 수 있다. 엄청난 양의 AI 생성 프런트엔드 코드가 지금 쏟아지고 있으며, 그중 일부는(Claude식 표현을 빌리자면) 분명 “구조를 지탱하는” 코드가 될 것이다. 그 웹사이트들이 느리고, 규정을 준수하지 않으며, 보안 구멍으로 가득하다면 에이전트에게 “내 웹사이트 좀 고쳐 줘”라고 묻는 것만으로는 충분하지 않을 수 있다. 특히 돈이 걸려 있고 바이브 코더의 웹 개발 지식이 “웹사이트는 인터넷에 호스팅된 앱이다”를 넘어서지 못한다면, 진정한 전문성에 기회가 있을 수 있다.
(2027년이나 2028년의 차세대 “자가 치유” 웹 앱이 평균적인 전문가를 능가하는 모습은 충분히 상상할 수 있으므로, 이것이 내 세 지점 중 가장 불안정하다는 점은 인정한다. 하지만 당분간은 그렇다. 전문성은 여전히 중요하다.)
이 글의 목적은 나 자신을 기분 좋게 만들거나, 최근 AI 붐으로 뒤집힌 모든 경력의 무덤 위에서 춤추려는 것이 아니었다. 나는 원래 우울한 사람이고, 이 글은 내 우울함에 빠져들도록 스스로 허락한 결과다. 수년에 걸쳐 쌓아 온 방대한 지식이 거의 쓸모없게 되었다는 사실에서 즐거움을 얻지도 않고, 훨씬 더 자격 있는 동료들에게 같은 일이 일어나는 모습을 보고 기쁘지도 않다. 하지만 그런 일이 일어나고 있지 않은 척하는 것 역시 유효한 전략은 아니다.
요즘 내가 읽는 일부 블로그에는 “AI 이야기하는 데 너무 지쳤다” 또는 “다시는 내게 AI를 언급하지 말아 달라” 같은 분위기가 있다. 그중 일부는 자신을 남다른 사람으로 드러내는 훈장처럼 달고 다니기 좋은, 세상사에 지치고 초연한 태도일 것이다. 하지만 상당 부분은 진짜 두려움에서 비롯된다고 생각한다. 1년 뒤 무슨 일이 일어날지 모른다는 것을 인정하는 일은 무섭다. 자신의 경력이 특정한 궤적을 따라 평온하게 은퇴에 도달할 것이라 상상했는데, 목표를 몇 년 앞두고 모든 것이 뒤집히는 모습을 보는 것은 불안정하게 만든다.
내가 사용해 온 비유는 소행성이 막 지구에 충돌했고, 우리는 아직 잔해를 조사하는 중이라는 것이다. 먼지가 가라앉은 뒤 무슨 일이 일어날지(어떤 작은 설치류가 포유류의 시대를 열게 될지는 더더욱) 예측하기는 어렵지만, 분화구 자체를 완전히 무시하는 것은 최악의 부정처럼 보인다. 또 다른 비유는 코로나다. 코로나가 닥쳤을 때 나는 “아, 코로나 이야기하는 데 너무 지쳤어”라고 생각했던 기억이 없다. 대신 바이러스, 역학, 마스킹 등에 관해 가능한 모든 것을 배우고 싶었다. 코로나가 이후 몇 년간 내 삶을 지배하게 될 것이었으므로, 이것은 좋은 생각으로 판명되었다(그러고 나서야 마침내 그 이야기에 지치기는 했다!).
나는 수정구슬을 가진 사람이 아니지만, 이 글은 내가 가장 아끼는 분야가 미래에 어디로 갈 수 있을지 생각해 보려는 시도였다. 요즘 나는 이 문제에 걸린 것이 훨씬 적다는 점을 인정한다. 웹 표준 분야를 떠났고, 현재 일자리에서는 프런트엔드 작업조차 하지 않으며, 내 블로그도 브라우저, 성능, 접근성 등에 관한 평소의 주제 대신 대부분 AI에 대한 울부짖음과 이를 악무는 이야기로 채워져 있다. 그렇다 해도 나는 여전히 프런트엔드 분야에 큰 애정과 존중을 품고 있으며, 미래에 이 분야에 무슨 일이 일어날지 신경 쓴다. 불과 몇 년 뒤에는 알아볼 수 없게 될지도 모르지만, 다른 것이 아니라면 내 동료들이 이 모든 변화를 헤쳐 나가고 이 기묘한 새 세계에서 번성할 방법을 찾기를 바란다.