반응형

엄청 헷갈리는 개념이라 메모해두려고 한다.

 

 

URI (Uniform Resource Identifiter - 통합 자원 식별자)

 

웹 기술에서 사용하는 논리적 or 물리적 리소스를 식별하는 고유한 문자열 시퀀스

주소보다는 '식별자'의 개념

 

URL (Uniform Resource Locator)

 

네트워크 상에서 웹 리소스에 대한 참조

흔히 웹 주소라고 한다.

우리가 주로 쓰는 주소가 URL

 

URL은 URI의 서브셋이다.

URI - 식별자

URL - 위치

 

 

URN (Uniform resource name)

 

URI의 특정 포맷중 하나로 이름으로 리소스를 특정하는 URI 

프로토콜을 제외하고 리소스의 name 을 가리키는데 사용

URN에는 접근 방법 & 위치가 표기 X

 

 

참고) URL 구조

 

scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]

 

scheme : 사용할 프로토콜을 뜻하며 웹에서는 http 또는 https를 사용

user와 password : (서버에 있는) 데이터에 접근하기 위한 사용자의 이름과 비밀번호

host와 port : 접근할 대상(서버)의 호스트명과 포트번호

path : 접근할 대상(서버)의 경로에 대한 상세 정보

query : 접근할 대상에 전달하는 추가적인 정보 (파라미터)

fragment : 메인 리소스 내에 존재하는 서브 리소스에 접근할 때 이를 식별하기 위한 정보

 

reference

 

https://www.charlezz.com/?p=44767 

 

URI랑 URL 차이점이 뭔데? | 찰스의 안드로이드

URI 그리고 URL을 혼용해서 사용하는 경우가 있다. 대부분의 경우 문제가 없지만 정확하게 이 둘의 차이점이 존재한다. 그러므로 각 용어의 정의와 용도에 대해서 알아본다. URI URI는 특정 리소스

www.charlezz.com

 

https://mygumi.tistory.com/139

 

URI vs URL vs URN :: 마이구미

이번 글은 URI, URL, URN 을 다뤄본다. URI와 URL은 아직도 많이 혼동되고 있다. 우리는 대부분 URL이라는 표현을 하고 있다. 우리가 보고 있고, 사용하고 있는 대부분이 사실 URL이기 때문이다. URI, URL, U

mygumi.tistory.com

 

반응형

'CS > 네트워크' 카테고리의 다른 글

AnyCast란?  (0) 2022.04.11
HTTP 메소드 멱등성, 안전한 메소드  (0) 2022.01.31
[TCP] 3-way handshake와 4-way handshake  (0) 2022.01.23
Pooling, Long Pooling, Streaming  (0) 2022.01.23
반응형

개인적으로 DB 내용은 어렵기도 하고 안쓰고 있으면 자꾸 까먹는거 같습니다.

이 블로그의 주 목적이기도 하고 메모용으로 간단하게 글을 써보려 합니다.

 

*틀린게 있으면 피드백 주시면 감사하겠습니다!

 

index란?

 추가적인 쓰기 작업과 저장 공간을 활용하여 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조

1000페이지의 책이 있다고 쳐봅시다. 특정 키워드를 찾고 싶은데 1쪽부터 1000쪽까지 전부 순회하며 찾으려면 매우 큰 시간 낭비일것입니다.

 

그래서 책에는 키워드를 빨리 찾기 위해서 보통 맨뒤에 색인이 있습니다.

데이터베이스에서도 인덱스는 책의 색인과 비슷한 역할을 한다고 보면 좋습니다.

 

(보통 Index는 PK에 기본적으로 걸려있습니다.)

 

Index의 구조

 

Balanced Tree인 B+(B) tree를 많이 사용합니다.

 

A: 트랙 B: 기하학적 섹터 C: 트랙 섹터 D: 클러스터

왜 tree 형태냐면 하드 디스크에서 데이터를 가져올때 섹터 단위(block 단위)로 가져오게 되는데 데이터를 효율적으로 관리하기 위해서 포인터로 참조하는 트리 형태를 띄게 됩니다.

 

*  b tree는 모든 노드에 key와 데이터를 가지지만 B+ tree는

branch node에서는 leaf node에 대한 key를 가지고, leaf node에만 데이터를 가집니다. 

 

Index의 장점

 

- 테이블 조회 속도 & 성능 향상

- 시스템 부하 감소

 

Index의 단점

 

- 인덱스를 사용하기 위해 대략 10%의 추가 저장공간이 필요하다

- 잘못 사용할 경우 성능 저하

- index 관리를 위해 추가 작업 필요 

 

보통 create, update, delete는 빈번하게 일어나지 않고 조회(select)만 자주 일어나는 속성에 사용하는게 좋습니다

-> DELETE, UPDATE 시 인덱스를 '사용하지 않음' 처리 

빈번하게 DELETE, UPDATE가 일어난다면 인덱스의 크기가 매우 커져서 오히려 성능이 줄어든다.

 

* select문에서 like '%문자' 같이 %를 앞에 넣어서 사용하는 경우 index를 타지않아서

검색 구현시 형태소 분석이나 elasticsearch를 사용하는것을 권장한다고 합니다

 

사용하면 좋은경우 

 

- 규모가 매우 큰 테이블

- INSERT, UPDATE, DELETE가 빈번하지 않은 컬럼

- 자주 SELECT문(특히 join, where, order by)에 쓰이는 컬럼

- 데이터의 중복도가 낮은(=cardinality가 높은) 테이블

- 데이터 분포도 10~15%(1/해당 컬럼의 distinct 데이터 개수 * 100)인 칼럼

 

Cardinality란?

 

전체 행에 대한 특정 컬럼의 중복 수치를 나타내는 지표입니다

 

-> 중복도 낮다 = 카다널리티 높다.

-> 중복도 높다 = 카다널리티 낮다.

 

중복도는 어떤 절대적인 수치가 아니라 '상대'적인 수치입니다.

id name location
1 park seoul
2 lee seoul
3 park busan
4 kim busan

 

id가 distanct값이 4개이므로 가장 카다널리티가 높습니다.

name은 distant 값이 3개이므로 id보다는 카다널리티가 낮고, location보다는 카다널리티가 높습니다.

location은 distant 값이 2개이므로 가장 카다널리티가 낮습니다.

 

인덱스를 걸때 중복이 최대한 없어야 데이터가 많이 걸러질것입니다. (중복이 많을수록 full scan에 가까워짐)

그래서 카다널리티가 높은 컬럼을 인덱스 우선순위로 추천한다고 합니다. 

 

Clustered Index 

 

Index를 생성할때 데이터 페이지 전체를 물리적으로 재배열 합니다.

 

테이블 당 한개만 존재합니다.

-> 가장 효율적인 칼럼을 Clustered Index로 지정 

테이블 크기의 3%정도 추천

 

Non-Clustered Index

 

군집화 되어있지 않은 인덱스 타입? (순서대로 정렬되있지 않다)

물리적으로 데이터를 배열하지 않고, 별도의 장소에 데이터 페이지가 구성됩니다.

테이블 당 여러개 존재 가능합니다.

 

Non-clusered index는 clustered Index보다 검색 속도는 느리지만 입력/수정/삭제는 더 빠릅니다.

(clustered Index의 경우 그 반대)

테이블 크기의 20%정도 추천

 

reference 

 

index 

 

https://mangkyu.tistory.com/96

 

[Database] 인덱스(index)란?

1. 인덱스(Index)란? [ 인덱스(index)란? ] 인덱스란 추가적인 쓰기 작업과 저장 공간을 활용하여 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조이다. 만약 우리가 책에서 원하는

mangkyu.tistory.com

 

b tree 

 

https://velog.io/@seanlion/btree

 

B트리,B+트리, B*트리 개념 정리

오늘은 트리 종류 중 하나인 B트리 시리즈를 정리해보려고 합니다. 이 포스팅에서는 B트리 시리즈 개념에 대해서 다룹니다.

velog.io

 

카디널리티

 

https://itholic.github.io/database-cardinality/

 

[database] 카디널리티(cardinality)란?

cardinality

itholic.github.io

 

반응형
반응형

내가 이걸 이해하고 있나? 싶어서

책읽는걸 그만두고 다른걸 해보다가 다시 내가 정리한 글들을 읽어봤다

 

체감상 10~30%만 실제로 응용하고 나머지는 안하고 있는 기분인데

%를 더 끌어올리게 노력해야겠다.

class

* SOLID

 

S : SRP(Single Responsibility Principle, 단일책임원칙)

하나의 객체는 하나의 책임(객체간 영향을 최소화하고 한가지 동작만을 수행)만을 가지도록 설계.

 

O : OCP(Open Closed Principle, 개방폐쇄원칙)

변경에는 닫혀있고 개방에는 열려있다.

→ 기존의 코드를 변경하지 않으면서 기능을 추가할 수 있도록 로직이 설계되어야 한다.

→ 클래스, 객체를 변경하지 않고도 클래스 환경을 변화할 수 있도록 구성한다.

 

L : LSP(Liskov Substitution Principle)

부모 클래스와 자식 클래스 간의 일관성이 있어야 한다.

→ 클래스를 재정의하지 않으며, 자식 클래스는 최소한 부모 클래스의 행위는 수행할 수 있어야 한다.

 

I : ISP(Interface Segregation Principle)

구체화보다는 추상화

→ 범용 인터페이스로 인해 여러 클라이언트(클래스)가 영향을 받기 보다는, 개별적인 클라이언트에 특화되어 서로의 영향을 최소화할 수 있도록 구성

 

D : DIP(Depedency Inversion Principle)

의존관계 역전 원칙

상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인 의존관계를 반전(역전)

→ 상위 모듈은 하위 모듈의 구현 내용에 의존하면 안 되고 상위 모듈과 하위 모듈 모두 추상화된 내용에 의존 

 

 

깨끗한 클래스를 만드는법에 대해 다루는 챕터

그렇다면 깨끗한 클래스란?

캡슐화 

클래스 외부 사용자는 사용하면서 내부 구현을 알 필요가 없고, 알아야할 이유도 없다.

 

클래스에서 꺼내와서 데이터 처리 X

객체에게 처리할 행위(method) 요청 O

 

캡슐화를 유지해야 좋은 클래스

풀어주는건 최후의 수단?

작은 클래스 

클래스는 함수와 마찬가지로 하나의 역할만(SRP), 작은 크기

 

- 만능 클래스보다는 하나의 책임

- 이름은 해당 클래스의 책임

- 모호한 이름 금지(Processor, Manager, Super 등) -> 여러 역할을 한다는걸 내포

- and, but 등 사용금지 -> 여러 역할을 한다는것 내포

 

응집도 up

보통 응집도를 높은 클래스 선호

클래스에 속한 메소드, 변수가 서로 의존하며 논리적인 단위로 묶인다

 

-> 큰 함수(클래스)를 여러개의 작은 역할로 나누면 응집도가 높아짐

 

변경하기 쉬운 클래스 & 변경으로부터 격리된 클래스

 

상세한 구현은 구현 요구사항이 바뀔때마다 위험에 빠진다 -> 인터페이스 & 추상 클래스를 통해

구현

 

클래스가 SRP, OCP 등 SOLID 원칙을 잘 만족했다면 요구사항이 변경되어도 유연한 대처가 가능 

 

결합도가 낮다 -> 변경에 영향받는 클래스가 격리되어 있어서 대처가 유연하다

 

ex) 레포지토리 패턴

https://0391kjy.tistory.com/39

 

Repository Pattern 이해하기

Repository Pattern? Repository(리포지토리) 패턴은 디자인 패턴 중 하나로, 데이터가 있는 여러 저장소(Local, Remote)를 추상화하여 중앙 집중처리 방식을 구성하고, 데이터를 사용하는 로직을 분리시키기

0391kjy.tistory.com

 

템플릿 메소드 패턴

https://gmlwjd9405.github.io/2018/07/13/template-method-pattern.html

 

반응형

'독서 > cleancode' 카테고리의 다른 글

cleancode - unit test  (0) 2022.01.25
clean code - 경계  (0) 2022.01.24
cleancode - 오류처리  (0) 2022.01.22
cleancode - 객체와 자료구조  (0) 2022.01.21
clean code - 주석 & 형식 맞추기  (0) 2022.01.20
반응형

1. 생성(Creational) 패턴

 

객체 생성 방식에 대한 패턴

생성 & 조합을 캡슐화해 특정 객체가 생성-변경되도 프로그램 구조에 영향을 

크게 받지 않게해서 유연성 제공

 

2. 구조(Structural) 패턴

클래스 & 객체를 조합해 더 큰 구조를 만드는 패턴

 

3. 행위(Behavioural) 패턴

객체 사이 상호작용하는 방식이나 관심사를 분리하는 방법

 

 

 

'바퀴를 재발명하지 말자'라는 말이 있는데 구현때 소프트웨어의 복잡성을 줄이려면 아는만큼 보이는거 같아서

앞으로 조금씩이라도 디자인패턴에 대해 공부하고 기록해놓으려고 한다.

 

tmi로 디자인 패턴을 몰라도 경험적으로 체득하고 사용한 경우도 있기는 있었다.

 

reference

 

https://medium.com/@nitinmuteja/part-1-gang-of-four-gof-software-design-patterns-9a2d1abe4dba

 

Part-1 Gang of Four (GOF) Software Design Patterns

Gang Of Four Design Patterns

medium.com

 

https://gmlwjd9405.github.io/2018/07/06/design-pattern.html

 

[Design Pattern] 디자인 패턴 종류 - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

 

반응형
반응형

요즘 갈 방향을 잃은 느낌이라 주의 환기 및 내가 주로 쓰던 명령어들을 복습겸 적어볼려고 한다.

git reset 

깃 공간을 크게 3가지로 나눈다면

 

1. Working Directory (create, update, Delete해서 작업한 파일이 반영되어 있는 디렉토리)

2. Staging Area(git add후 곧 commit 하기 이전의 디렉토리)

3. Git Directory(staging Area에 있는 작업이 commit되어 반영된 공간)

 

이라 할 수 있다.

이때 작업을 하다보면 각 공간(1->2, 2->3)에 잘못 반영될때도 있는데 이때 유용한 명령어가 바로 git reset이다.

 

git reset때 지워지는 영역

git reset은 크게 3가지이다.

 

사용 ex) git reset --soft HEAD^1(바로 이전 커밋(head)에 반영됨)

1. git reset --soft

 

commit을 잘못 반영했을때 Staging Area로 되돌릴 수 있는 명령어이다.

주로 commit명에 오타를 냈을때 많이 사용했다.

 

2. git reset --mixed

git reset의 default

해당 커밋의 repository~staging area의 영역에 있는 코드들을 전부 working directory에 반영한다.

(git add 이전 상태로 되돌린다)

 

주로 이전 커밋으로 돌아가서 staging area에 반영할 코드들을 기능별로(커밋을 나누고 싶을때)쪼개 commit할때 사용했다.

 

3. git reset --hard

작업을 아예 rollback할때 사용한다.

 

구현할때 어떤 이론을 세우고 작업을 했는데 내 이론이 틀렸을때 주로 사용했다.

 

git reflog

 

이걸 사용한경우는 손에 꼽히기는 한데 git reset --hard나 git 작업을 하다 잘못했을경우 롤백할 수 있는 매우 유용한 기능을 제공한다.

 

git rebase/git reset 등으로 커밋 이력이 삭제되었을때 git reflog를 하면 볼 수 있다

 

git cherry-pick 

 

다른 브랜치에 있는 commit을 선택적으로 반영할때 사용된다.

깃은 diff 가 아니라 각 커밋이 스냅샷이긴 한데 체리픽을 할때는 diff만 반영되는거(커밋 하나의 변경점) 같다.

 

tmi로 경험적으로 깨달은건데(틀릴수도 있음)

local에서 작업할때 git fetch 로 remote repository의 브랜치들을 가져와 있으면 local branch에 git cherry-pick 적용이 된다는 점이다. 

 

git rebase/merge/squash and merge

 

merge

 

왼쪽 3-way merge, 오른쪽 fast-forward merge

1. 3-way merge : 분기점이 있는경우 3-way merge를 해서 브랜치 두개를 합친다. (중간에 매개 commit인 merge commit이 하나 남는다)

2. fast-forward merge : 현 커밋보다 앞선 커밋들이 있는경우 fast-forward merge를 해서 앞선 커밋들을 충돌없이 따라간다.

그리고 commit id 는 그대로 남는것으로 알고 있다.

 

squash and merge

 

두개의 브랜치를 합칠때 합쳐지는 대상이 여러개의 커밋이라도 '하나의 커밋'으로 합쳐져서 반영되게 된다.

ex) squarsh and merge를 했을경우

그리고 그 커밋들은 커밋 내역에 합쳐져서 보이게 된다. 

 

rebase

 

일종의 되감기인데 두개의 브랜치가 한 줄로 이어지게 된다.

커밋 내역을 깔끔하게 보여줘서 rebase 팬들도 은근히 많이 있더라..

 

예시로

 

같은 부모 0 에서 시작한 1-2-3 이라는 A branch와

a-b-c라는 B 브랜치가 있다면

rebase 시 1-2-3-a-b-c 이런식으로 한줄로 된다.

 

그리고 Merge는 Commit ID가 보존되고, Rebase는 새로운 Commit이 생성되므로 Commit ID가 바뀐다

https://learngitbranching.js.org/?locale=ko 에서 테스트해보자. 

C3에서 나온 rebase branch(C4, C5)에서 C8을 rebase 했더니 C4', C5'로 각각 새로운 commit Id가 생성된것을 확인 가능하다. 

 

C3에서 나온 mege branch(C6, C7)에서 C9를 merge 하면 C10 가 새로 생기고(merge commit) 

C9의 commit Id가 바뀌지 않고 그대로 이어진것을 확인 가능하다.

git log --graph

이런식으로.. cui에서 그래프 형태로 보여주게 된다

협업할때 이걸 써서 브랜치 현황을 보여주면 소스트리를 쓰는 팀원이 아주 좋아죽는다

 

소스트리같은 소프트웨어로 브랜치를 더 깔끔하게 보는 방법이 있으니

이런거 쓰지말고 착한 깃린이 여러분들은 이걸 쓰세여ㅠㅠ

 

소스트리 링크) https://www.sourcetreeapp.com/

 

Sourcetree | Free Git GUI for Mac and Windows

A Git GUI that offers a visual representation of your repositories. Sourcetree is a free Git client for Windows and Mac.

www.sourcetreeapp.com

 

git push origin main -f 

 

reference

 

git reset

 

https://opentutorials.org/module/4032/24533

 

git reset --hard vs --mixed vs --soft - GIT4 - Reset & Revert

수업소개 reset은 head가 가르키는 branch가 가르키는 커밋을 변경하는 작업입니다. 이때 옵션을 --hard, --mixed, --soft 중 무엇으로 주느냐에 따라서 stage, working directory의 상태가 달라집니다. 여기서는

opentutorials.org

 

https://im-developer.tistory.com/182

 

[Git] Merge 이해하기 (Merge / Squash and Merge / Rebase and Merge)

회사에서 Git을 사용해서 형상 관리를 하고 있다. 그 동안 내가 개인 repository branch에 commit, push등을 해본 적은 많지만 다른 사람과 협업을 하면서 branch를 생성하고 master에 merge를 해본 적은 없어서

im-developer.tistory.com

 

https://stackoverflow.com/questions/34019195/git-pull-doesn-t-fast-forward-merge-even-though-there-are-no-conflicts

 

Git pull doesn’t fast-forward merge, even though there are no conflicts

I just performed a git pull from my master branch on a remote repo into the branch I'm currently working on locally via the command line. Unexpectedly Vim opened. I quit Vim. Following this, I che...

stackoverflow.com

https://www.tuwlab.com/ece/22218

 

[GIT] 병합하고 Commit 재정렬하기: cherry-pick, rebase, merge - ECE - TUWLAB

병합과 재정렬은 대개 한 Topic(작업 단위)의 작업이 끝난 다음, 작업 내용을 Master branch에 반영해야 할 경우 수행하는 작업입니다. 새로운 Topic에 대한 작업을 할 때는 대개 Master Branch에서 새로운 B

www.tuwlab.com

 

반응형
반응형

jest로 테스트를 공부해보고 있는데 몇개 안넣었는데 3~4초 이상이 걸리길래 

한번 찾아봤다

 

https://if1live.github.io/posts/escape-from-jest-jest-is-slow/

 

Jest 탈출기 - Jest는 느리다 · /usr/lib/libsora.so

개요 요새 작업하는 프로젝트에서 jest를 사용해서 유닛테스트를 돌린다. 프로젝트가 진행될수록 테스트가 점점 느려지더니 이제 유닛 테스트 한번 돌리는데 1분이 걸린다. 라이젠 붙은 좋은 컴

if1live.github.io

 

요약) 

jest는 각 VM (Executing JavaScript) - test case에서 import를 각각 하기 때문에 느리다..

 

홀리..

반응형
반응형

See the Pen Untitled by lodado (@lodado) on CodePen.

 

css으로 직접 만들어본 loading spinner

 

출처 : https://codepen.io/mandelid/pen/kNBYLJ

 

Super Simple CSS Spinner

Just recreating http://codepen.io/scottkellum/pen/tzjCK to learn how he did it....

codepen.io

반응형

'Front-end > CSS' 카테고리의 다른 글

font-family 상속 시키기  (0) 2022.11.04
css 챌린지  (0) 2022.10.05
[CSS] box-sizing  (0) 2022.07.11
[CSS] Gap  (0) 2022.06.13
CSS 애니메이션 성능 개선  (0) 2022.01.27
반응형

* 잘못된점이 있으면 피드백 주시면 감사하겠습니다!

 

예시 화면(by react-query로 제작)

 

react-query를 보면 data, loading, error 상태가 있고 로딩 화면, 에러 화면을 각각 보여줄 수 있다

리둑스와 리둑스 사가로 비슷한걸 연습겸 한번 만들어 보았다.

 

*혹시 redux-saga 가 익숙하지 않다면

https://mskims.github.io/redux-saga-in-korean/introduction/BeginnerTutorial.html

추천

 

우선 초기 constant 를 정의한다.

/* constrant.ts */

export const START_LOADING = 'loading/START_LOADING';
export const FAIL_LOADING = 'loading/FAIL_LOADING';
export const FINISH_LOADING = 'loading/FINISH_LOADING';

export const GET_ITEM = 'GET_ITEM';
export const GET_ITEMS = 'GET_ITEMS';

export const RESPONSE_STATUS = {
  REQUEST: {
    data: undefined,
    error: false,
    empty: false,
    loading: true,
  },
  FAILURE: {
    data: undefined,
    error: true,
    empty: false,
    loading: false,
  },
  SUCCESS: {
    error: false,
    loading: false,
  },
} as const;

 

RESPONSE_STATE는 각 비동기 조건(data, loading, error)때 가지고 있을 상태이다.

SUCCESS의 경우엔 fetch된 data를 가지고 있어야 하기 때문에 나중에 상태를 만들때 주입할 예정이다.

 

~LOADING constrant들은 각 조건때의 action이다.

GET_ITEM, GET_ITEMS는 각각 아이템 하나, 아이템 리스트를 받아오는 비동기 요청 action이다.

 

이제 action를 제작해보자.

// action.ts

export const LOADING_STATUS = {
  GET_ITEM,
  GET_ITEMS,
} as const;

export type LoadingStatusType = typeof LOADING_STATUS[keyof typeof LOADING_STATUS];

function getVaildRequestType(requestType: string): LoadingStatusType {
  return LOADING_STATUS[requestType];
}

export const startLoading = (requestType: string) => ({
  type: START_LOADING,
  payload: getVaildRequestType(requestType),
});

export const failLoading = (requestType: string) => ({
  type: FAIL_LOADING,
  payload: getVaildRequestType(requestType),
});

export const finishLoading = (requestType: string, response: []) => {
  return {
    type: FINISH_LOADING,
    payload: getVaildRequestType(requestType),
    response,
  };
};

 

getVaildRequestType을 쓴 이유는 action과 reducer를 추상화하고 비동기 요청때마다 기본 템플릿으로 재사용하기 위해서 저런 번거로운 방식을 사용한것이다. (requestType로 type를 보내준다.)

 

(사실 getVaildRequestType을 안쓰고 그냥 payload:requestType해도 되긴 하는데 확장성을 위해서(혹시 상태의 이름을 변경하고 싶을때 사용하라고) 넣었다)

 

 

reducer를 만약 재사용을 하지 않는다면 비동기 요청 하나하나마다 각각 reducer를 제작해야하는 번거로움이 존재한다. 

 

이것은 reducer를 보면서 자세히 설명한다.

LOADING_STATE의 역할도 reducer를 보면서 설명한다.

각 action에 넣어주는 requestType는 redux-saga에서 넣어준다

 

// reducer.ts

function setInitState() {
  const init = {};

  const { REQUEST } = RESPONSE_STATUS;
  // eslint-disable-next-line no-return-assign
  Object.keys(LOADING_STATUS).map((key) => (init[LOADING_STATUS[key]] = REQUEST));
  return init;
}

interface LoadingActionType {
  type: string;
  payload: string;
  response?: [];
}

export function asyncLoadingReducer(state = setInitState(), action: LoadingActionType) {
  const { type, payload, response } = action;
  const { REQUEST, FAILURE, SUCCESS } = RESPONSE_STATUS;

  switch (type) {
    case START_LOADING:
      return {
        ...state,
        [payload]: REQUEST,
      };

    case FAIL_LOADING:
      return {
        ...state,
        [payload]: FAILURE,
      };
    case FINISH_LOADING:
      return {
        ...state,
        [payload]: { ...SUCCESS, data: response, empty: isEmpty(response) },
        //isEmpty는 그냥 fetch된 데이터가 비었나 확인해주는 함수
      };
    default:
      return state;
  }
}

 

[payload] : ~~상태 를 사용해서 아까 보낸 getVaildRequestType의 파라미터마다 상태를 가질 수 있다. 

 

예를 들어 LOADING_STATE에 지금 GET_ITEM 과 GET_ITEMS라는 type를 지정해두고 이후 redux-saga에서 실행할때 해당 type를  requestType(payload)로 받아온다면 type마다 { data, loading, error } 결과값을 가지는 상태를 가질 수 있다!

(이게 무슨말인지 혼동된다면 아래의 redux-saga까지 보고오면 이해가 빠를것 같다)

 

GET_ITEM, GET_ITEMS 각각 type 하나마다 { START_LOADING, FAIL_LOADING, FINISH_LOADING } case 상태(RESPONSE_STATE)를 가진다. 

ex) GET_ITEMS만 ajax 요청을 받아오고 완료되었을때 상태 출력(case FINISH_LOADING), GET_ITEMS는 아직 요청을 보내지 않았다(case START_LOADING-(default)).

SUCCESS(case FINISH_LOADING)땐 아까 만든 상태에 data를 주입해서 반환해주자.

 

이제 redux-saga를 보자.

function* abstractGenerator({ ACTION, axiosRequest }) {
  yield put(startLoading(ACTION));

  try {
    const response = yield axiosRequest;
    yield put(finishLoading(ACTION, response.data));
  } catch (error) {
    yield put(failLoading(ACTION));
  }
}

function *getItemListGenerator() {
  yield abstractGenerator({ ACTION: GET_ITEMS, axiosRequest: call(getItemList) });
}

function *getItemByIdGenerator(status: { id: number; type: string }) {
  const { id } = status;
  //yield put ~~ 
  yield abstractGenerator({ ACTION: GET_ITEM, axiosRequest: call(getItemById, id) });
}

function* getItemLIstSaga() {
  yield takeLatest(GET_ITEMS, getItemListGenerator);
}

function* getItemByIdSaga() {
  yield takeLatest(GET_ITEM, getItemByIdGenerator);
}

export function* rootSaga() {
  yield all([getItemLIstSaga(), getItemByIdSaga()]);
}

 

비동기의 기본 로직을 잘 보면

function* abStractGenerator({ ACTION, axiosRequest }) {
  yield put(startLoading(ACTION));

  try {
    const response = yield axiosRequest;
    yield put(finishLoading(ACTION, response.data));
  } catch (error) {
    yield put(failLoading(ACTION));
  }
}

 

1. 데이터 fetch를 시작한다 - START_LOADING(action)

2. action(GET_ITEM, GET_ITEMS)에 따라 ajax 요청을 보내고,  - START_LOADING 

3. 데이터를 받아오는데 성공했다면 성공 action을 반환한다. - FINISH_LOADING 

4. 실패했다면 실패 action을 반환한다. - FAIL_LOADING

 

비동기 요청시 대다수의 redux-saga는 비슷한 로직으로 실행될것이다.

그럼 이 비동기 로직도 달라지는 값인 action과 ajax 함수 값만 파라미터로 주입해준다면 재사용을 할 수 있다.

 

그리고 여기서 action인 startLoading, finishLoading, failLoading에 넣는 ACTION이 아까 보았던 requestType의 정체다.

그렇게 넣으면 payload로 action이 들어가게 되고... asyncLoadingReducer에서 [payload]마다 로딩, 에러, 성공시 알맞은 상태를 반환한다.

 

이런식으로 1개의 reducer, 1개의 saga를 재사용해 n개 이상의 다른 비동기 요청을 처리할 수 있다.

 

그리고 ajax 함수들은 이런식이다.

export const getItemList = () => axios.get(API.GET.ITEMLIST); // API.GET ~ 는 주소

export const getItemById = (itemId: number) => {
  return axios.get(API.GET.ITEM, {
    params: {
      itemId,
    },
  });
};

 

예시 component) 

export function ItemBox() {
  const { asyncLoadingReducer } = useSelector((state: RootStoreType) => state);
  const disPatch = useDispatch();

  const itemRequest = asyncLoadingReducer[LOADING_STATUS[GET_ITEM]];
  const { data, empty, loading, error } = itemRequest;

  useEffect(() => {
    disPatch({ type: GET_ITEM, id: 1 });
  }, []);

  if (loading) return <div>loading</div>;
  if (empty) return <div>emptyData</div>;
  if (error) return <div>error</div>;

  return <div>{JSON.stringify(data)}</div>;
}

 

추가) 

import { createStore, combineReducers, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { asyncLoadingReducer } from './reducer';
import { rootSaga } from './saga';

const configureStore = () => {
  const sagaMiddleware = createSagaMiddleware();
  const rootReducer = combineReducers({
    asyncLoadingReducer,
  });

  const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));
  sagaMiddleware.run(rootSaga);
  return store;
};

const rootStore = configureStore();

export type RootStoreType = ReturnType<typeof rootStore.getState>;
export default rootStore;

 

해본 후기)

 

그냥 react-query 쓰자

 

같이 읽으면 좋은 글)

 

https://techblog.woowahan.com/6339/

 

Store에서 비동기 통신 분리하기 (feat. React Query) | 우아한형제들 기술블로그

오늘은 주문에서 사용하는 FE 프로덕트의 구조 개편을 준비하며 FE에서 사용하는 Store에 대해 개인적인 고민 및 팀원들과 검토하고 논의했던 내용을 소개합니다. 이 과정에서 생긴 여러 가지 의

techblog.woowahan.com

 

반응형

'Front-end > React' 카테고리의 다른 글

react 17(개인 공부용)  (1) 2022.06.09
React18(개인 공부 메모용)  (0) 2022.06.09
react TMI  (0) 2022.04.13
drag and drop으로 창 크기 조절  (0) 2022.03.18
redux 기본 구조  (0) 2022.02.02

반응형

 

CORS는 많이 들어봤는데

CORB란것을 '사이트 격리'에 대해 알아보다가

새로 알게 되었다.

 

참고) 사이트 격리

 

- It ensures that pages from different websites are always put into different processes.

- It also blocks the process from receiving certain types of sensitive data from other site

 

즉, Chrome's Site Isolation effectively makes it harder for untrusted websites to access or steal information from your accounts on other websites.

 

Cross-Origin Read Blocking(CORB)

 

Cross-Origin Read Blocking (CORB) is an algorithm that can identify and block dubious 
cross-origin resource loads in web browsers before they reach the web page.

 

For example, it will block a cross-origin text/html response requested 
from a <script> or <img> tag, replacing it with an empty response instead.

 

출처 : https://developers.google.com/web/updates/2018/07/site-isolation

 

즉, 웹에서 cross origin의 data resource(xml, html, json 등)를 읽어와 사용하지 못하도록 브라우저에서 막는 동작이다.

 

원리 

 

CORB가 어떻게 동작하는지 알아보자.

보통 web client는 서버에 두가지의 요청을 보낸다.

 

  1. data resources such as HTML, XML, or JSON documents
  2. media resources such as images, JavaScript, CSS, or fonts

보통 1번은 SOP & CORS 설정에 따라 브라우저에 의해 blocking 되거나 보이게 된다.

(참고로 2번 media resources들은 cors에 상관없이 요청 가능하다. ex-JSONP)

 

조건 

그리고 CORB는 위 조건을 만족한다면

renderer processa cross-origin data resource를 받아와 사용하는 것을 금지한다.

(a new security feature that prevents the contents of balance.json from ever entering the memory of the renderer process memory based on its MIME type.)

 

참고)

X-Content-Type-Options: nosniff는 Microsoft에서 제안하는 확장 헤더이며 웹서버가 보내는 MIME 형식 이외의 형식으로 해석을 확장하는 것을 제한하는 크로스사이트스크립트 방어법이다.

 

즉, nosniff 옵션이 켜있다면 브라우저는 이게 HTML, XML, JSON중 하나인것으로 Content-type 종류로 인하여 헷갈리지 않고 바로 확정 지을 수 있다.

(가끔 어떤 서버는 이미지에 대해 text/html로 잘못 분류하기도 한다. 이걸 방지 가능)

 

이점 

 

CORB를 사용하면 다음과 같은 이점이 있다.

 

- Mark responses with the correct Content-Type header.

- out of sniffing by using the X-Content-Type-Options: nosniff header.

- 보안! (In browsers with Site Isolation, it can keep such data out of untrusted renderer processes entirely, helping even against side channel attacks like Spectre)

예시

그럼 예시 데모를 한번 보자.

 

https://anforowicz.github.io/xsdb-demo/index.html

 

CORB demo

Demo of CORB This page demonstrates how Cross-Origin Read Blocking (CORB) works. Please see one of the following resources for more information about CORB: Repro steps to trigger CORB: Make sure that CORB is active In Chrome M68 and later CORB is active by

anforowicz.github.io

 

<button> Add 1 <img src="https://www.chromium.org/"> </button>
<button> Add 2 <img src="https://www.w3.org/.../dummy.pdf"> </button>

 

들어가서 버튼을 한번 눌러보면

CORB 차단이 뜬다.

 

위 버튼들은 data resource(text/html, application/pdf) 요청을 cross-origin 서버에 보내는 버튼들이고, CORB에 의해 막히게 된다.

그리고 CORS와 동일하게 정상적인 요청이 왔어도 (status 200) 브라우저에서 막도록 구현된 것을 확인할수 있다.

 

 

tmi)

현재 tistory 스킨에서 영어를 읽으려니 눈이 아프다 -_-;

 

 

함께 읽으면 좋은 글)

 

CORS

https://beomy.github.io/tech/browser/cors/

 

[Browser] CORS란?

이번 포스트에서는 교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)에 대해 이야기해보도록 하겠습니다. 아래 사진과 같은 에러를 보신 적이 있으셨을 수도 있습니다.

beomy.github.io

 

reference 

 

https://chromestatus.com/feature/5629709824032768

 

https://stackoverflow.com/questions/18337630/what-is-x-content-type-options-nosniff

 

https://webhack.dynu.net/?idx=20161120.001&print=friendly 

 

https://bingbingba.tistory.com/8

 

https://developers.google.com/web/updates/2018/07/site-isolation

 

Site Isolation for web developers  |  Web  |  Google Developers

Chrome 67 on desktop has a new feature called Site Isolation* enabled by default. This article explains what Site Isolation is all about, why it’s necessary, and why web developers should be aware of it.

developers.google.com

 

반응형

+ Recent posts