SEOP124 safe triangle target area로 컨텍스트 메뉴 사용성 높이기 Prologue최근 리뉴얼 프로젝트에 참여해 서비스 전체 레이아웃 및 디자인을 개편하는 작업을 진행했습니다. 기존의 콘텐츠를 세분화하고 메뉴를 확장하며 GNB 구성에도 변화가 있었는데요. 1차 메뉴로만 구성된 단순한 GNB에서 1차-2차 메뉴의 depth로 확장되면서 메뉴 이동 시 유저 경험을 향상하기 위해 safe triangle target area를 적용하게 되었습니다. 이번 글에서는 이것이 무엇인지, 그리고 어떻게 적용했는지에 대한 경험을 소개해보고자 합니다. 👉🏻 2차 메뉴 선택 방식 위 이미지처럼 2차 메뉴에 접근할 때 1차 메뉴를 벗어나 대각선으로 접근한 경험이 있을 거라 생각합니다. 그런데 생각해 보면 타겟이 되는 1차 메뉴에서 마우스가 벗어나면 2차 메뉴가 닫혀야 정상인데 멀쩡하게 이.. 2024. 8. 15. useReducer + custom hook으로 state 관리하기 PrologueuseState는 참 편리한 훅입니다. 초기값 할당과 업데이트, 사용 방식이 매우 직관적이고 단순하죠. 하지만 한 컴포넌트 안에 state가 많이 존재한다면, 그리고 한 함수에서 여러 state를 업데이트해야 한다면 컴포넌트 규모는 금새 커지게 됩니다. 이번 글에서는 이 문제를 해결하기 위해 useReducer를 활용한 custom hook 제작 사례를 소개하려 합니다. 발단대부분의 서비스에는 로그인, 회원가입과 같은 인증 페이지가 존재합니다. 그리고 그 페이지에는 아이디, 이름, 비밀번호 등 단순한 입력값뿐만 아니라 휴대폰 인증 여부, 비밀번호 양식 검증 등 유효성 검사를 관리하기 위해 많은 상태와 비즈니스 로직이 존재합니다. 제가 담당했던 서비스 또한 많은 상태로 인해 꽤 복잡해진 상태.. 2024. 7. 26. emotion to scss module 도입기 Prologue emotion 도입 이후 도메인별로 작성된 스타일시트를 컴포넌트 레벨로 분리하며 가독성과 생산성이 향상하는 성과를 이뤘습니다. 하지만 최근 프로젝트부터는 scss module을 도입하는 방향으로 변경했는데, 그 이유와 과정, 결과에 대해 작성해보고자 합니다. 문제점 시작은 Next.js의 app router 적용부터였습니다.Next.js 13.4 릴리즈와 함께 app router의 안정화가 이루어졌고, 이에 맞춰 전체 서비스를 마이그레이션 하는 프로젝트를 진행했습니다. 클라이언트-서버 컴포넌트라는 새로운 패러다임에 맞춰 전체 구조를 변경하는 과정에서 초기 렌더 시 스타일이 주입되지 않는 이슈가 있었는데, 문제는 다음과 같았습니다. 런타임 자바스크립트가 필요한 css-in-js 라이브러리.. 2024. 7. 25. 모던 리액트 Deep Dive - 12장 웹사이트와 성능 웹사이트에 기대하는 사항 웹사이트 방문 목적 달성 달성 시간 최소 개인정보 누출 등 보안 철저 개발자들이 성능에 크게 관심을 갖지 않는 이유 개발자의 기기가 평균 기기보다 성능이 뛰어나다. 성능 개선 작업은 쉽지 않고, 눈에 띄는 성능 향상을 기대하기 어렵다. 핵심 웹 지표 Core Web Vital LCP (Large Contentful Paint) FID (First Input Delay) CLS (Cumulative Layout Shift) TTFB (Time To First Byte) FCP (First Contentful Paint) LCP 페이지가 처음으로 로드를 시작한 시점 ~ 뷰포트 내부에서 가장 큰 이미지 또는 텍스트를 렌더링하는데 걸리는 시간 사용자의 기기가 노출하는 뷰.. 2024. 3. 3. 리팩터링 - 7장 Chapter 07. 캡슐화 ✏️ 레코드 캡슐화하기 배경 대부분의 프로그래밍 언어는 데이터 레코드를 표현하는 구조를 제공한다. 이 구조에는 장, 단점이 있는데, 데이터를 직관적인 방식으로 묶을 수 있어서 의미 있는 단위로 전달할 수 있게 해준다는 장점이 있다. 계산해서 얻을 수 있는 값과 그렇지 않은 값을 명확히 저장해야 하는 단점이 있다. e.g.) { start: 1, end: 5, length: 5 } → 값의 범위에 해당하는 length는 연산 값일 수 있다. 이에 가변 데이터를 저장하는 용도로는 레코드보다 객체가 나을 수 있다. 객체를 사용하면 어떻게 저장했는지를 숨긴 채 각각의 값을 메서드로 제공할 수 있다. 레코드 구조는 두 가지로 구분할 수 있다. 필드 이름을 노출하는 형태 (필드를 외부로.. 2024. 3. 2. 리팩터링 - 12장 Chapter 12. 상속 다루기 ✏️ 메서드 올리기 배경 메서드 올리기를 적용하기 가장 쉬운 상황은 메서드들의 본문 코드가 똑같을 때다. 이럴 땐 그냥 복사 - 붙여넣기면 끝이다. 보통 메서드 올리기를 적용하려면 선행 단계가 필요하다. e.g. 서로 다른 두 클래스의 두 메서드를 같은 메서드로 만들기 각각의 함수를 매개변수화한 후 메서드를 상속 계층의 위로 올리기 절차 같은 동작의 메서드인지 확인한다. 메서드 안에서 호출하는 다른 메서드와 참조하는 필드들을 슈퍼클래스에서도 호출하고 참조할 수 있는지 확인한다. 함수 선언 바꾸기로 슈퍼클래스에서 사용하고 싶은 형태로 통일한다. 서브클래스 중 하나의 메서드를 제거한다. 모든 서브클래스의 메서드가 없어질 때까지 하나씩 제거한다. 예시 Before // 코드 .. 2024. 3. 2. 리팩터링 - 11장 Chapter 11. API 리팩터링 ✏️ 질의 함수와 변경 함수 분리하기 배경 우리는 외부에서 관찰할 수 있는 겉보기 부수효과(Observable Side Effect)가 전혀 없이 값을 반환해주는 함수를 추구해야 한다. 순수 함수: 같은 입력에 대해서 같은 결과를 반환하며 함수의 바깥 영역에 side effect를 초래하지 않는 함수 겉보기 부수효과가 있는 함수와 없는 함수는 명확히 구분하는 것이 좋은데, 이를 위한 한 가지 방법은 ‘질의 함수(읽기 함수)는 모든 부수효과가 없어야 한다’ 는 규칙을 따르는 것이다. 이를 명령-질의 분리라 한다. 명령-질의 분리 원칙 - 어떤 메서드는 명령을 실행(부작용을 생성하는 어떤 작업을 함)하거나 질의에 대답(어떤 값 반환)할 수 있으며, 두 작업을 모두하면 안.. 2024. 3. 2. 리팩터링 - 10장 Chapter 10. 조건부 로직 간소화 ✏️ 조건문 분해하기 배경 복잡한 조건부 로직은 프로그램을 복잡하게 만든다. 다양한 조건, 그에 따라 동작도 다양한 코드를 작성하면 순식간에 꽤 긴 함수가 탄생한다. 거대한 코드 블록이 주어지면 코드를 부위별로 분해한 다음 각각 의도를 살린 이름의 함수 호출로 바꿔주자. 이렇게 하면 해당 조건이 무엇인지 강조하고, 그래서 무엇을 분기했는지 명확해진다. 절차 조건식과 그 조건식에 딸린 조건절 각각을 함수로 추출한다. 예시 Before // 함수 내용 : 여름 기간 여부에 따라 할인율이 달라지는 함수 // 목표: 조건식을 별도 함수로 추출해 조건문 정리하기 if (!aDate.isBefore(plan.summerStart) && !aDate.isAfter(plan.s.. 2024. 3. 2. 리팩터링 - 8, 9장 Chapter 08. 기능 이동 ✏️ 함수 옮기기 배경 좋은 소프트웨어 설계의 핵심은 모듈화가 얼마나 잘 되어 있느냐이다. 이를 모듈성(modularity)라고 한다. 모듈성: 프로그램의 어딘가를 수정하려 할 때 해당 기능과 깊이 관련된 작은 일부만 이해해도 가능하게 해주는 능력. 모듈성을 높이려면 서로 연관된 요소들을 함께 묶고, 요소 사이의 연결 관계를 쉽게 찾고 이해할 수 있도록 해야 한다. 독립적으로 고유한 가치가 있는 함수는 분리하고, 관련이 있는 함수끼리는 묶어준다. 이를 결정하기 위해서는 대상 함수의 컨택스트(해당 함수가 호출하는 함수는 무엇이 있는지, 사용하는 데이터가 무엇인지)를 살펴본다. 절차 선택한 함수가 현재 컨택스트에서 사용중인 모든 요소를 살펴본다. 그리고 이 중 함께 옮길만한 .. 2024. 3. 2. 리팩터링 - 5, 6장 Chapter 05. 리팩터링 카탈로그 보는 법 ❗️ 리팩터링 설명 형식 이름 리팩토링 용어 지칭 개요 리팩터링의 핵심 개념을 간략히 표현 개념도 + 코드 예시 배경 해당 기법이 왜 필요한지, 또는 적용하면 안되는 상황이 어떤건지에 대해 설명 절차 리팩터링 과정을 단계별로 제시 예시 리팩터링 실제 적용 예시 & 효과 Chapter 06. 기본적인 리팩터링 ✏️ 함수 추출하기 배경 코드 조각을 찾아 무슨 일을 하는지 파악한 다음, 독립된 함수로 추출하고 목적에 맞는 이름을 붙인다. 이렇게 했을 때 함수 이름만으로 목적을 빠르게 파악할 수 있고, 본문 코드에 크게 신경쓰지 않아도 되기 때문이다. 이 방식으로 여러 짧은 함수가 만들어져 호출량의 증가로 성능 저하가 있다고 생각할 수 있지만, 함수가 짧으면 캐싱.. 2024. 3. 2. 리팩터링 - 2장 Chapter 02. 리팩터링 원칙 💡 리팩터링의 정의 ✏️ 리팩터링 [명사] 소프트웨어의 겉보기 동작은 그대로 유지한 채, 코드를 이해하고 수정하기 쉽도록 내부 구조를 변경하는 기법 동작을 보존하는 작은 단계들을 거쳐 코드를 수정하고 이러한 단계들을 순차적으로 연결하여 변화를 만들어 내는 일 리팩터링하는 동안에는 코드가 항상 정상 작동하기 때문에 전체 작업이 끝나지 않았더라도 언제든 멈출 수 있다 성능 최적화와 비슷하다. 둘 다 코드를 변경하지만 리팩터링의 목적은 코드를 이해하고 수정하기 쉽게 만드는 것이기 때문에 성능이 좋아질 수도, 나빠질 수도 있는 반면, 성능 최적화는 오로지 속도 개선에만 신경을 쓴다 🎩 두 개의 모자 기능을 추가할 때는 기존 코드를 건드리지 않고 새 기능을 추가하기만 한다 리팩.. 2024. 3. 2. 모던 리액트 Deep Dive - 11장 Next.js 13과 리액트 18 app directory의 등장 13 버전 이전 페이지 _document: 페이지에서 쓰이는 html, body 태그 수정, SSR 시 style 주입 _app: 페이지 초기화 용도 13 버전 layout.js: 주소별 공통 UI 포함 / 웹 페이지 시작에 필요한 공통 코드 삽입 children을 props로 받아 렌더링 page.js: 리액트 컴포넌트 노출 error.js: 공통 에러 컴포넌트 에러 바운더리는 클라이언트에서만 작동 (client component) 루트 에러 처리는 global-error.js로 not-found.js: 404 페이지 렌더링 서버 컴포넌트 loading.js: Suspense 기반으로 컴포넌트 불러오는 중임을 나타냄 route.js: h.. 2024. 3. 2. 이전 1 2 3 4 ··· 11 다음 반응형