useRef 예시

카테고리 Daily

useRef hook은 DOM에 접근하기 위해 사용한다.

useRefcurrent 프로퍼티를 포함한 객체를 반환한다.

current 프로퍼티를 포함한 객체는 컴포넌트 전체 생명 주기에서 사용될 수 있고 리렌더링을 발생시키지 않으면서 데이터를 유지할 수 있도록 한다.

즉, useRef 값은 렌더링 중에도 같은 값을 유지할 수 있다.

  • 리렌더링 없이 참조값을 갱신하는 것

문법

1
const newRefComponent = useRef(initialValue);
  • 주로 변형가능한 데이터를 리렌더링 없이 저장하기 위해 사용된다.

예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function App() {
const [anyInput, setAnyInput] = useState(" ");
const showRender = useRef(0);
const randomInput = useRef(null);

const toggleChange = (e) => {
setAnyInput(e.target.value);
showRender.current++;
};
const focusRandomInput = () => {
randomInput.current.focus();
};

return (
<div className="App">
<input
className="TextBox"
ref={randomInput}
type="text"
value={anyInput}
onChange={toggleChange}
/>
<h3>Amount Of Renders: {showRender.current}</h3>
<button onClick={focusRandomInput}>Click To Focus On Input </button>
</div>
);
}

export default App;
  • showRender 데이터는 toggleChange 이벤트가 발생할 때마다 값이 증가하고 해당 값이 화면에 렌더링된다. 이 때, 리렌더링 없이 showRender 값을 변형할 수 있다.
  • current 프로퍼티로 DOM에 접근하여 focus를 적용할 수 있다.

댓글 공유

CSS import 피하기

카테고리 Daily

CSS는 어떻게 동작하는가?

  1. CSS는 존재만으로 CSS가 파싱되기 전까지 브라우저 렌더링을 막는다.
  2. CSS는 HTML 파싱도 막는다. 스크립트가 페이지 스타일에 영향을 줄 수 있기 때문에, 브라우저가 CSS 관련 작업 중에는 작업이 완료된 후 script를 실행한다.

그러므로 이러한 상황을 피하기 위해서는 CSS를 최대한 빠르게 불러와야 하며 리소스를 최적의 순서로 불러와야 한다.

CSS import 피하기

@import는 CSS 파일의 렌더링 속도를 느리게 한다.

브라우저 렌더링 순서

  1. HTML 다운로드
  2. HTML이 CSS 요청
  3. CSS가 또 다른 @import에 있는 CSS 요청
  4. 위 단계가 끝나면 Render Tree 생성

@import 사용 시 네트워크 흐름

import css

파일 별개로 분리 시 네트워크 흐름

css split

결론

  • @import 사용 피하기
  • 파일 별개로 분리하여 관리
  • CSS 작성 시 속성을 알파벳 순서대로 작성

댓글 공유

Grid Layout 알아보기

카테고리 Daily

푸터를 만들 때, Grid를 사용하여 설계를 해보자.

1
2
3
4
5
<div class="grid">
<div class="item grid-item1">1</div>
<div class="item grid-item2">2</div>
<div class="item grid-item3">3</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
}
.item {
height: 100px;
border: 1px solid black;
}
.grid-item1 {
background: yellow;
grid-area: 1/2/2/4;
}
.grid-item2 {
background: green;
}
.grid-item3 {
background: pink;
grid-area: 1/1/1/1;
}

Grid 레이아웃

  • 전체적인 레이아웃은 grid를 사용하고 내부의 세부적인 레이아웃은 flex를 사용한다.
  • grid 내부의 크기를 grid-area로 지정할 수 있다.
  • grid-area: 열,행
  • grid는 margin-collapse 일어나지 않는다.

댓글 공유

컨테이닝 블록

  • 요쇼의 크기, 위치를 결정하는 요인이다.
  • width, height, padding, margin 속성값과 절대적 위치(absolute, fixed)로 설정된 요소의 offset 속성값은 자신의 컨테이닝 블록으로부터 계산된다.
  • 대부분의 경우 요소의 컨테이닝 블록이 가장 가까운 블록 레벨 조상의 컨텐츠 영역이지만 예외가 있다.

컨테이닝 블록 식별

position의 속성에 따라 완전히 달라진다.

1. position 속성이 static, relative, sticky 인 경우

  • 컨테이닝 블록은 가장 가까운 조상 블록 컨테이너 또는 서식 맥락을 형성하는 조상 요소(flex,table,grid)의 컨텐츠 영역 경계를 따라 형성된다.

2. position 속성이 absolute 인 경우

  • 컨테이닝 블록은 속성값이 static이 아닌 가장 가까운 조상의 내부 여백 영역
  • 그래서 주로 조상 영역에 relative를 추가하여 조상을 기준으로 position을 조절한다.

3. position 속성이 fixed 인 경우

  • 컨테이닝 블록은 viewport, 페이지 영역이다.

예외

position 속성이 absolute, fixed 인 경우, 다음 조건을 만족하는 가장 가까운 조상 내부 영역이 컨테이닝 블록이 될 수 있다.

  1. transform이나 perspective 속성이 none이 아닐 때, transform 속성을 none으로 바꾸면 viewport 기준으로 바뀐다.

  2. will-change 속성이 transform이나 perspective 일 때, will-change는 요소의 예상되는 변화의 힌트를 브라우저에게 제공한다.

  3. filter 속성이 none이 아닐 때

  4. contain 속성이 paint 일 때

1
2
3
4
5
<body>
<div class="container">
<div class="p-absolute">1</div>
</div>
</body>

컨테이닝 블록 예시

  • container 클래스에 아무런 값을 주지 않고 있어 p-absolute 값이 static이 아닌 조상 영역을 기준으로 위치하는데, static이 아닌 조상 요소가 없어서 최상위 브라우저를 기준으로 위치해있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
body {
margin-top: 100px;
margin-left: 100px;
}
.container {
width: 500px;
height: 500px;
background: blue;
position: relative;
/* transform: rotate(0deg); */
/* perspective:0; */
/* transform: rotate(0deg); */
/* perspective: 10px; */
/* will-change: perspective; */
/* will-change: transform; */
/* filter:opacity(); */
}
.p-absolute {
width: 100px;
height: 100px;
background: yellow;
position: absolute;
top: 10px;
left: 50px;
}

컨테이닝 블록 예시2

  • 앞서 설명한 예외를 추가하면 position:relative를 추가한 것과 똑같이 동작하게 된다.
  • 해당 속성을 가진 요소를 기준으로 위치를 조절한다.

댓글 공유

flex vs inline-flex

카테고리 Daily

flex vs inline-flex

  • flex로 지정된 flex container는 block 요소 성향
  • inline-flex로 지정된 inline-flex container는 inline 요소 성향

inline-flex

댓글 공유

정의

hr 태그는 콘텐츠 내용에서 주제가 바뀔 때, 사용하는 수평 가로선이다.

HTML 문서에서 주로 내용을 구분하거나 주제의 변화를 정의한다

HTML5에서 변경된 사항

  • HTML5 이전에서는 단순히 가로선을 나타냈지만, HTML5에서는 주제의 흐름 변경을 나타내도록 변경되었다.
  • 시각적인 의미보다는 의미적 용어(semantic term)로 사용된다.

또한, HTML5에서는 hr 요소의 layout을 더 이상 지원하지 않으며 CSS를 대신 사용하도록 변경되었다.

CSS

1
2
3
4
5
6
7
8
9
.news::before {
content: "";
position: absolute;
top: 30px;
left: 0;
width: 80%;
height: 1px;
background: #aaa linear-gradient(to right, #aaa, #fff)
}
  • news라는 클래스의 가상 선택자로 css 스타일링 해줄 수 있다.

댓글 공유

텍스트 말줄임표 처리

카테고리 Daily

한줄이 길어서 말줄임표 (…) 처리 해주고 싶을 경우

1
2
3
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

멀티라인인 경우

1
2
3
4
5
6
7
.element {
height: 3em;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
  • Webkit 기반 브라우저 (Chrome, Safari 등)에서 적용 가능하다.

댓글 공유

웹 폰트 적용하기

카테고리 Daily

1. @import 방식으 CSS 최상단에 복붙

1
@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.4/dist/web/static/pretendard.css");

2. font-family 설정

1
2
3
4
5
6
body {
font-family: Pretendard, -apple-system, BlinkMacSystemFont, system-ui, Roboto,
"Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic",
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif;
font-weight: 400;
}
  • font-family는 하나로 정해두고 굵기는 원하는 부분에서 font-weight로 조절한다.

댓글 공유

HTML이란?

카테고리 Daily

HTML5 역사

  • W3C가 XHTML 2.0을 만들고 있었는데 하위 호환상 문제가 있어서 개발을 접었다

  • 이후 2004년 브라우저 3대장(애플,모질라,오페라 sw)이 공동으로 설립한 WHATWG(Web Hypertext Application Technology Working Group)가 W3C와 별개로 Web Application 1.0과 Web Forms 2.0 만들어 냈다.

  • 그리하여 WHATWG의 표준안을 대부분 수용하여 HTML5가 탄생하게 되었다.

  • 초기의 웹은 단순히 하이퍼텍스트 문서(HTML)를 웹 브라우저에 나타내는 수준으로, 웹표준 기술이 지원하지 못하는 부분을 비표준적인 태그들과 Active X, Flash, Flex, SilverLight 등의 써드파티(Third Party) 플러그인이 대신하였다.

  • 이로 인해 여러 웹브라우저별로 화면이 다르게 보이거나 특정 웹브라우저에서만 동작하는 웹 애플리케이션이 만들어지는 등 각종 호환성 문제가 발생하였습니다. 그 결과 개발자에게는 개발의 어려움을, 사용자에게는 웹 브라우저 선택 제한과 각종 플러그인의 설치라는 불편함을 안겨주었다.

  • 이러한 문제점과 기능적인 한계를 안고 있던 기존 HTML은 HTML5에서 새롭게 추가된 요소와 다양한 API들을 통해 한 단계 발전된 웹 구현과 접근성 및 호환성 극대화를 목표로 삼게 되었다.

XHTML과 HTML 차이점

둘다 표준이지만 문법이 다르다. XHTML이 조금 더 엄격한 특징을 가진다.

XHTML은 XML로 재구성된 문법이다.

HTML XHTML
DOCTYPE 반드시 명시
<html> 태그의 xmlns 속성 반드시 명시
<img> <img />
대소문자 구분 x 태그는 반드시 소문자 사용
반드시 하나의 root 요소를 포함해야 한다.
속성 이름도 반드시 소문자 사용
속성값 반드시 따옴표로 감싼다
속성값 생략 가능 <input checked> 속성값 생략 불가 <input checked = “check” />
<img> 태그에 alt 반드시 명시
텍스트는 반드시 태그로 감싸야한다.

댓글 공유

흔히 웹을 사용하면서 select 태그를 클릭해서 options 들이 나타났을 때, select 태그 내부의 option을 클릭하면 해당 option이 선택되고, option 외부를 클릭했을 때, 나타났던 option들이 사라지도록 구현된 웹을 많이 경험했을 것이다.

나도 그래프를 CustomLegend의 요소를 클릭했을 때, 클릭한 Legend의 Line 그래프를 highlight 시켜주고, CustomLegend 내부의 요소 이외의 영역을 클릭했을 때, 클릭한 요소를 해제하도록 구현해보았다.

1. 선택된 그래프의 x축 값을 상태로 관리한다.

1
const [clickedGraph, setClickedGraph] = useState("");

2. CustomLegend에 이벤트 위임을 해준다.

1
2
3
4
5
6
7
8
9
const CustomLegend = () => {
return (
<ul id="CUSTOM_LEGEND">
{payload.map((elem) => (
<li key={elem.name}>{elem.value}</li>
))}
</ul>
);
};
  • CustomLegend의 ul 태그에 id를 부여한다.
  • li 요소를 클릭 이벤트를 이벤트 위임을 통해 이벤트 발생을 캐치할 수 있다.

3. 이벤트 핸들러 생성

1
2
3
4
5
6
7
8
9
10
11
12
const handleClickGraph = (e: any) => {
const value = e.target.innerHTML;
setClickedGraph(value);
};

const handleClickOutside = (e: any) => {
const parentElem = e.target as HTMLElement;

if (!targetElem.closest("#CUSTOM_LEGEND")) {
setClickedGraph("");
}
};
  • 클릭이벤트가 발생한 요소의 가장 가까운 요소 중 id가 CUSTOM_LEGEND인 요소가 없으면 clickedGraph의 값을 빈 값으로 초기화 시킨다.

4. 브라우저에 이벤트 등록

1
2
3
4
5
6
7
useEffect(() => {
document.addEventListener("click", handleClickOutside);

return () => {
document.removeEventListener("click", handleClickOutside);
};
});
  • 내가 지정한 영역은 ul 태그 안이고 내가 지정하지 않은 외부의 영역을 모두 다루기 위해서는 브라우저에 이벤트를 등록해줘야한다.
  • useEffect는 함수형 컴포넌트에서 리액트 컴포넌트의 라이프사이클에 원하는 함수를 실행할 수 있도록 도와주는 훅이다.
    • return으로 함수를 반환하면 해당 함수는 컴포넌트가 소멸할 때, 실행된다.

렌더링 되기 이전에 브라우저에 이벤트를 등록해주고 해당 컴포넌트가 소멸할 때, 이벤트를 제거해줘야 컴포넌트가 렌더링 될 때마다 이벤트가 중복으로 등록되지 않아 성능상 문제를 해결할 수 있다.

댓글 공유

loco9939

author.bio


author.job