개요 개발을 하다 보면 무의식적으로 `` 태그를 남발하게 되는 경우가 많다. 당장 스타일링하기 편하고, 별다른 고민 없이 레이아웃을 잡을 수 있기 때문이다. 하지만 ``로 점철된 코드는 Div Soup(div만 가득한 죽)이라고 불리며, 검색 엔진(SEO)과 스크린 리더(접근성)에게는 최악의 구조다. 이와 관련한 글을 이전 포스트로 작성했었다. 이번에 서비스의 SEO 최적화와 웹 접근성 향상을 목표로, 기존의 ``로 떡칠된... 코드를 시맨틱 태그로 대대적으로 리팩토링 했다. (사실 div 태그 제거 작업은 할당된 업무에 없었는데 어차피 해야하는 작업이라 같이 해결했다.) 결과적으로 Lighthouse 점수가 유의미하게 상승했는데, 그 과정과 기준을 정리해본다. 시맨틱 태그 적용과 기준`` vs ``..
개요 Sentry에서 INP(Interaction to Next Paint) 지연 경고가 간헐적으로 발생하고 있다. 로그를 분석해 보니 특정 페이지(eventDetail)에서 사용자의 클릭 반응 속도가 눈에 띄게 느려지는 현상이 포착되었다. 범인을 추적해 보니 피크(Peak)가 튀는 순간은 MUI(Material UI) 컴포넌트가 렌더링 될 때였다. Deep Dive : 왜 MUI v5가 범인인가? 최적화를 시작하기 전에, 도대체 왜 MUI v5가 느린지 근본적인 원인을 파악해 보자. 범인은 바로 편리함의 상징인 sx 문법이다. v5의 sx가 문제라는 것이지 지금 버전의 sx도 문제라고 오해하지 않는 것이 좋다. 런타임 오버헤드 (Runtime Overhead) 우선 sx로 작성된 스타일이 실제 DOM..
개요 컴포넌트를 만들다 보면 필연적으로 간격을 어디에 줄 것인가에 대한 고민에 빠지게 된다. 예를 들어, 리스트에 들어갈 `UserCard`라는 컴포넌트를 만든다고 가정해보자. 리스트 아이템 사이에는 20px의 간격이 필요하다. 이때 가장 쉬운 방법은 `UserCard` 자체에 `margin-bottom: 20px`을 주는 것이다. "어차피 이 카드는 리스트에서만 쓰니까, 알아서 간격을 가지고 있으면 편하잖아?" 하지만 프로젝트가 커지고 `UserCard`를 다른 곳(가로 스크롤 뷰, 모달 내부, 그리드 레이아웃 등등)에서 재사용하려고 할 때, 내부에 심어둔 이 margin은 굉장히 거슬리는 무언가가 돼버린다. ▼ 나는 "자식 컴포넌트는 패딩이나 마진 같은 외부 간격에 대해 전혀 몰라야 한다"는 ..
개요 유지보수를 하면서 이전에 작성된 코드를 보는데 `{...props}` 문법이 정말 많이 보였다. 리액트의 문법들에 대해 다 알지 못했기에 무슨 이런 해괴한 문법이 있나... 하면서 찾아보니 꽤나 유용한 문법이었다. 처음 봤을 때는 솔직히 조금 불편했다. 명시적으로 어떤게 있는 지 모르니 말이다... 그러면서 이건 아무래도 안티 패턴인거 같다는 생각이 들었고, 커뮤니티랑 글들을 찾아보니 내 생각이 맞았다. 얼핏 보면 코드도 간결하고, 고수처럼 코딩하는 것 처럼 보인다.// 이렇게 간단하게 props를 넘길 수 있다니!function ParentComponent() { const userProps = { name: '노근', age: 25, job: 'Developer' }; return ;} ..
개요 React로 폼을 개발하다가 꽤나 당황스러운 버그가 나타났다. 새로고침(F5)을 누르면 분명 State는 초기화되는데, Input에는 이전에 입력했던 값이 그대로 남아있는 것이다. 더 황당한 건 입력 값은 보이는데 Preview 영역에는 아무것도 표시되지 않는다는 점이었다. 처음에는 '내가 State 관리를 잘못한 건가?' 싶어서 코드를 여러 번 확인했다. 하지만 크롬에서는 문제없이 잘 작동했다. 문제는 Firefox와 Firefox 기반 브라우저(Floorp, Librewolf 등)에서만 발생했다. 문제 상황구체적인 상황은 이랬다. ▼사용자가 폼에 데이터를 입력입력한 데이터가 Preview 영역에 실시간으로 표시됨새로고침(F5) 실행React State는 정상적으로 초기화됨그런데 Input/Te..
HI-ARC intra.hiarc-official.com 개요대규모 웹 프로젝트를 진행하다 보면 누구나 한 번쯤 이런 고민에 빠진다. "서비스가 여러 개일 때, 프로젝트 구조는 어떻게 나눠야 할까?" 특히 여러 명의 개발자가 동시에 작업하는 협업 환경이라면, 구조적 통일성과 생산성, 유지보수 효율성은 무시할 수 없는 요소다. 이때 흔히 등장하는 해답이 바로 모노레포(Monorepo) 구조다. 한 레포에서 여러 앱을 관리하고, 공통 UI와 유틸리티를 공유하고, 통합된 빌드 환경과 테스트, 린트를 적용할 수 있다. 한 번에 관리되는 코드베이스라는 것은 꽤나 매력적으로 다가온다. (필자는 플러터를 했을 때 부터 느낀 거지만, 한 번에 많은 것이 관리되는 코드베이스에 매력을 느끼는 것 같다.) 이 글에서는 ..
개요 프론트에서 사진이 제대로 보이지 않는 문제가 발생했다. ▼ S3에는 분명히 이미지가 업로드 되어 있고, Postman으로 요청을 날려봐도 응답이 200으로 잘 오는데, 실제 화면에서는 이미지가 보이질 않았다. 처음엔 당연히 백엔드 문제라고 생각했고, 이게 뭐지 싶어 로깅도 켜고 요청 흐름도 추적해봤지만 서버에는 이미지가 잘 올라가 있었다. 클라이언트도 요청 값에 누락하는 일 없이 보내고 있었고, URL도 뭔가 이상 없어 보였다. 그럼 도대체 어디서 잘못된 걸까? 문제 상황아래는 Postman에서 확인한 이미지 URL이다. ▼https://aws_bucket/20240413%25EF%25BC%25BF165238.jpg 하지만 url에 직접 접속해서 보려고 하면 이런 오류가 나왔다. '백엔드에서 ..
개요프론트엔드 개발을 막 접했을 시점에 VScode에서 이런 경고 문구를 보게 되었다. ▼ JS에 대해 잘 모르기도 했고, 애초에 ES 모듈이 뭔지 그리고 CommonJS 모듈이 뭔지도 몰랐기도 하고 잘 동작하기에 그냥 넘어갔었다. 그런데 이런 사소한 것들을 그냥 지나치면 나중에 큰 문제가 될 수 있을 거 같아 한 번 찾아보면서 정리를 해봤다. CommonJSCommonJS란 CommonJS는 Node.js의 초기 모듈 시스템으로, 모듈을 로드하고 관리하기 위해 설계된 시스템이다. 주로 서버사이드에서 사용이 된다. 상당히 레거시한 느낌이 강하지만 Node.js 생태계 전반에서 사용되고 있으며 많은 라이브러리에서 지원이 된다. (개요에서 필자가 뭔지도 모르고 썼음에도 동작할 수 있었던 이유다.) Commo..