onClick 이벤트 전파

카테고리 Daily

onClick 이벤트 전파

React에서 onClick 이벤트 핸들러를 등록하여 클릭 이벤트가 발생하면 이벤트가 발생한 요소 뿐만 아니라 부모 요소까지 이벤트가 전파된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function App() {
return (
<div className="App" onClick={() => console.log("container clicked.")}>
<div className="parent" onClick={() => console.log("parent clicked.")}>
<button
className="child"
onClick={() => {
console.log("child clicked.");
}}
>
버튼
</button>
</div>
</div>
);
}

export default App;
1
2
3
child clicked
parent clicked
container clicked
  • child를 클릭하면 console 창에 다음과 같이 출력된다.
  • 이벤트가 발생한 요소부터 이벤트 핸들러가 호출되고 부모 방향으로 이벤트가 전파된다.

간혹 부모 요소에서 이벤트가 발생하기를 원하지 않을 경우 이러한 이벤트 전파를 막아야한다.

그 방법으로는 event.stopPropagation()이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function App() {
return (
<div className="App" onClick={() => console.log("container clicked.")}>
<div className="parent" onClick={() => console.log("parent clicked.")}>
<button
className="child"
onClick={(e) => {
e.stopPropagation();
console.log("child clicked.");
}}
>
버튼
</button>
</div>
</div>
);
}

export default App;
1
child clicked.
  • 이벤트 전파가 발생하지 않고 이벤트가 발생한 요소만 이벤트 핸들러가 호출된다.

댓글 공유

sticky 잘 사용하기

카테고리 Daily

sticky 잘 알고 사용하기

position:stickyposition:static 처럼 일반적인 흐름을 따르지만, 일정 스크롤을 내렸을 때 해당 임계점에 도달하였을 때, position:fixed 처럼 구현하기 위한 속성이다.

1
2
3
4
5
6
.sticky {
position: -webkit-sticky; /* 사파리 브라우저 지원 */
position: sticky;
top: 4px;
background: red;
}
  • sticky 속성을 설정하면 top, bottom, right, left 속성 중 하나는 반드시 설정해줘야한다.

또한 sticky가 기준으로 하는 임계점은 overflow:auto, overflow:scroll 속성을 가진 가장 가까운 조상 컨테이너 박스이다.

예시

1
2
3
4
5
6
7
8
9
10
11
<div class="scroll">
<div class="parent">
<b class="static">.static</b>
<b class="sticky">.sticky</b>
<b class="fixed">.fixed</b>
</div>
<div class="parent">
<b class="static">.static</b>
<b class="sticky">.sticky</b>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.scroll {
display: inline-block;
width: 200px;
height: 400px;
overflow: auto;
padding: 0 4px;
vertical-align: middle;
border: 4px solid #000;
}
.parent {
height: 300px;
margin: 4px 0 200px;
border: 4px solid #666;
}
.static {
position: static;
background: gray;
}
  • 위 코드에서 sticky가 fixed로 고정되는 임계기준점은 scroll 클래스를 가진 div 박스이다.
  • scroll 클래스가 있는 박스는 스크롤이 할 수 있을 만큼 길이가 길어서 스크롤 하여 해당 임계점에 도달하는 순간 fixed로 변하게 된다.

처음에 헷갈린 점은 overflow:auto 속성을 parent 클래스를 가진 박스로 옮겼는데 아무런 일도 일어나지 않아서 당황했다. 그 이유는 parent 클래스를 가진 박스 내부가 스크롤이 되었을 때 해당 박스를 기준으로 고정되는 것인데, parent 클래스를 가진 박스는 스크롤이 될만한 높이를 가지고 있지 않아서 아무런 일도 발생하지 않았던 것이다.

댓글 공유

이번에 프로젝트를 진행하다가 아이콘을 사용하기 위해 svg 파일을 css background:url()로 불러와서 사용한 적이 있다.

그런데 로컬환경에서는 제대로 불러와지던 svg 파일들이 build를 하고 난 후, 확인해보니 불러와지지 않는 것을 확인하였다.

그래서 찾아보니 Vite에서는 다음 asset을 가져오기 위해 2가지 방법을 사용한다고 한다.

Vite에서 assets 가져오기

1. URL을 통해 가져오기

1
2
import imgUrl from "./img.png";
document.getElementById("hero-img").src = imgUrl;
  • Webpack의 file-loader와 비슷한데, 차이점이 있다면 Vite는 절대경로와 상대 경로 둘 다 사용가능하다.
  • 일반적인 이미지, 미디어, 폰트 파일 타입은 자동으로 asset 목록에 포함된다.

2. public 디렉터리에서 가져오기

  • robots.txt 같이 소스 코드에서 참조하지 않는 asset
  • 해싱 없이 항상 같은 이름을 갖는 asset
  • URL을 얻기 위해 굳이 import 할 필요가 없는 asset

위 3가지의 경우에는 public 디렉터리에 asset을 위치시킨다. 이곳에 위치한 asset은 개발 시 / 경로에, 배포시에는 dist 디렉터리에 위치한다.

1
2
3
.arrowDown {
background-image: url("/assets/img/Arrow.svg");
}
  • public 디렉터리에 있는 asset을 가져올 경우에는 항상 루트 기준으로 하는 절대경로에서 가져와야한다. (public/Arrow.svg asset은 소스 코드에서는 /Arrow.svg으로 접근 가능하다.)
  • public 디렉터리에 있는 asset은 JavaScript로 가져올 수 없다.

가급적 import를 사용하자.

React Router를 사용하여 중첩 라우팅을 구현하였다.

/mypage/history 라우팅에서 Header 컴포넌트를 불러왔다.

Header 컴포넌트에는 public 폴더에서 불러온 logo가 있다.

하지만 이 때의 경로는 /img/logo.svg 였기 때문에 /mypage/history 라우팅에서는 해당 경로의 파일을 찾을 수 없다.

해당 경로의 파일을 찾기 위해서는 /mypage/history/img/logo.svg 로 경로를 바꿔줘야 한다.

즉, public 폴더에서 이미지를 가져올 경우, 라우팅이 바뀔 때마다 경로를 생각해줘야한다.

그러므로 import 구문을 사용하여 src 폴더 안에 이미지를 가져오도록 하자.

댓글 공유

Recoil에 들어가기 전...

카테고리 Daily

상태란?

상태(state)는 애플리케이션의 작동 방식을 설명하는 모든 데이터를 말한다. 상태 관리는 시간의 흐름에 따라 상태가 변경되는 방식이다.

상태 관리를 위해서는 다음 기능이 필요하다!

  • 초기값(initial Value)을 저장할 수 있어야 한다.
  • 현재 값(Current Value)을 읽을 수 있어야 한다.
  • 값을 업데이트 할 수 있어야 한다.

React 상태관리의 한계

  1. 컴포넌트 상태는 연관된 상위 컴포넌트까지 끌어올려야 공유가 가능하고 이 과정에서 Props Drilling 이슈가 발생하고 불필요한 리렌더링 발생한다. (성능저하)

  2. Context로 Props Drilling 이슈 해결할 수 있지만, Context는 단일 값만 저장할 수 있고 여러 값들의 집합을 담기가 어렵다.

  3. React의 Context, Props 만으로는 최상단에서 최하단 까지의 state 코드 분리가 어렵다.

Recoil 장점

유연한 상태 공유

Redux처럼 복잡한 과정이 없다. 간단한 get/set 인터페이스를 사용해 상태 공유가 쉽다.

파생된 상태

데이터는 간단하고 또 안전하게 상태나 다른 파생된 데이터로부터 파생될 수 있다. 또한, 상태에 접근하는 방법과 동일하게 파생된 상태에 접근 가능하다.

파생된 상태는 동기, 비동기 처리가 가능하다.

광범위한 앱 상태 관찰

Recoil 상태의 전체 또는 일부의 상태를 읽거나 상태가 변경된 것을 감지할 수 있다. 앱의 상태를 유지할 수도 있고 다시 수화(Hydration)하는 기능을 제공한다.

비교적 낮은 러닝 커브

Recoil은 React API와 유사하여 Redux에 비해 쉽고 Recoil은 기본적으로 비동기 처리 기능을 가진다.

Recoil 핵심 개념

1. atoms

  • atoms은 공유 상태
  • 컴포넌트가 구독할 수 있는 상태 단위

atom은 상태단위이며 구독과 업데이트가 가능하다. atom이 업데이트되면 구독중인 컴포넌트는 새 값을 반영해 다시 렌더링된다.

1
2
3
4
const authUserState = atom({
key: "authUserState",
defualt: null,
});
  • atom은 고유한 key를 가져야 한다.
  • default 속성으로 초깃값 설정한다.

컴포넌트에서 atom을 읽거나 쓰려면 useRecoilState 훅을 사용한다.

1
2
3
4
5
6
7
function SignIn() {
const [authUser] = useRecoilState(authUserState);

return (
!authUser ? <SignInForm /> : <Browse />;
);
}

뿐만 아니라 상태 업데이트를 위한 업데이트 함수만 추출할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function SignInButton() {
const [, setAuthUser] = useRecoilState(authUserState);

const handleSignIn = () => {
// ...
setAuthUser({ name, email });
};

return (
<button type="button" onClick={handleSignIn}>
로그인
</button>
);
}

2. selectors

selector는 atom이나 다른 selector를 입력받아 파생된 상태를 생성하는 순수함수이다. 상위의 atom, selector가 업데이트되면 하위의 selector도 다시 실행된다. 컴포넌트는 atom과 마찬가지로 selector가 변경되면 다시 렌더링된다.

최소한의 상태만 atom에 저장하고 selector로 파생된 상태를 효과적으로 계산하여 불필요한 상태 보존을 방지한다.

selector는 어떤 컴포넌트가 필요로하는지, 어떤 상태에 의존하는지 추적하므로 함수적인 접근 방식을 매우 효율적으로 만든다.

1
2
3
4
5
6
7
const authUserNameState = selector({
key: "authUserNameState",
get:({ get }) {
const authUser = get(authUserState);
return authUser.name;
},
});
  • get 메서드 내부의 get함수는 atom 또는 다른 selector를 전달받을 수 있다.
  • 전달받게 되면 자동적으로 종속 관계가 생성되며 참조했던 다른 atom, selector가 업데이트 되면 다시 실행된다.

댓글 공유

1
2
3
4
5
6
7
8
9
10
11
import styled from "@emotion/styled";

const StyledButton = styled.button`
width: 100px;
height: 50px;
color: ${(props) => (props.isClicked ? "green" : "white")};
`;

function Btn() {
return <StyledButton isClicked>선택하기</StyledButton>;
}
  • 위와 같이 사용하게 되면 StyledButton 에 커스텀 props를 타입 선언을 해주지 않았기 때문에 에러를 발생한다.

이를 해결하기 위해 커스텀 props 타입을 단언해주면된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
import styled from "@emotion/styled";

const StyledButton = styled.button<{ isClicked: boolean }>`
width: 100px;
height: 50px;
color: ${(props) => (props.isClicked ? "green" : "white")};
`;

function Btn({ isClicked }: { isClicked: boolean }) {
return (
<StyledButton isClicked={isClicked}>선택하기</StyledButton>
);
}

댓글 공유

image sprite 실전 사용기

카테고리 Daily

image sprite 실전 사용기

기존 프로젝트에서는 돋보기 아이콘을 불러올 때, png 파일을 통해서 각각 한개씩 불러왔다.

이렇게 되면 돋보기 이미지는 상태에 따라 default, focus, disabled 총 3가지 상태를 가진 이미지가 있기 때문에 이미지를 3번 불러와야한다.

하지만 이미지 스프라이트를 사용하면, image sprite를 사용하여 3가지 상태의 이미지를 svg 파일 한 곳에 넣어두고 이를 배경이미지로 불러와서 원하는 위치의 이미지에 position을 주어 보여주도록 하였다.

1
2
3
4
5
img {
width: 46px;
height: 44px;
background: url("img_navSprites.png") 0 0;
}
  • 이미지를 배경으로 불러온 뒤 left, top 속성으로 배치한다.
1
2
3
4
5
6
7
function App() {
return (
<div>
<img src="img_trans.png" >
</div>
)
}
  • src 속성을 비워두게 되면 img 태그에 테두리가 생기게 되는데, 이는 제거하려해도 제거할 수가 없다. (border, outline, padding, margin 여러 방법을 써봐도 안됐다.)

그래서 src 속성을 비워두지 않기 위해 투명한 이미지 경로를 넣어준 것이다.

1
2
3
.next {
background: url("img_navSprites.png");
}
1
2
3
4
5
6
7
8
// 또는 img 태그 대신 i 태그 사용하기
function App() {
return (
<div>
<i className="next">
</div>
)
}

오늘 프로젝트를 진행하면서 icon을 불러오는 용도로 사용했기 때문에 img 태그 대신 i 태그를 사용하여 불러오니 src 속성없이도 불러올 수 있어서 편리하였다.

댓글 공유

Remote SSH로 원격 코딩하기

우리가 로컬에서 개발한 프로젝트를 서버 컴퓨터에서 실행하고 싶으면 어떻게 해야할까?

방법은 서버 컴퓨터에서 해당 프로젝트를 실행해주면 된다.

말로는 정말 쉬워보이지만 막상 하려고 하면 뭐부터 해야할지 모르겠다.

그래서 단계를 나눠서 도전해보자.

과정

remotessh

  1. 우선 VSCode에서 “Remote - SSH”라는 익스텐션을 다운받는다. 해당 extension을 사용하여 서버 컴퓨터에서 원격으로 프로젝트를 실행할 것이다.

sshSettings1

  1. 톱니바퀴를 눌러서 config 파일을 연다.

  2. config 파일 설정은 다음과 같다.

sshSetting2

  • Host는 원격 서버의 이름을 나타낸다.
  • User는 계정 이름으로 보통 “ubuntu”
  • ssh 파일 경로는 SSH키가 담긴 .pem 파일의 경로
  1. 이제 VSCode를 사용하여 서버를 원격으로 조종할 수 있다.

sshSetting3

우측에 새창으로 열기를 클릭하면 서버환경에서 VSCode가 열리게 될 것이다.

이 후 VSCode에서 터미널을 켜서 git clone을 하여 github 레포지토리를 클론한 다음

프로젝트를 실행하면 원격으로 서버 컴퓨터에서 프로젝트를 실행할 수 있게된다.

댓글 공유

loco9939

author.bio


author.job