728x90

다룰 내용

switch, rebase, merge

 

switch

branch를 switch하는 역할을 한다.

# 다른 방법
git checkout -b [변경 할 브랜치명]

# switch
git switch -c [변경 할 브랜치명]

 

rebase

이름 그대로 re-base하는 "베이스를 재설정 하는 작업"을 의미한다.
(서아라는 블로그에 잘 정리가 되어있어서 링크를 첨부한다)

예를 들어,
main이라는 base가 되는 브랜치에서 협업하고 있다면
한 브랜치의 base를 다른 브랜치의 최신 커밋으로 브랜치의 base를 옮기는 작업이다.

merge, rebase 작업 예시

# b 브랜치를 a로 merge 할때 (current branch -> main)
git switch a
git merge b

# b 브랜치를 a로 rebase 할때
git switch b
git rebase a

# b 브랜치를 a로 rebase 후 merge
git switch b
git rebase a

git switch a
git merge b


rebase에 대해서 더 얘기해보자.

협업을 하다보면 작업 도중에
동료 개발자들이 올린 commit들을
내가 진행중인 사항에 반영해야 될 경우가 많다.

이때 rebase를 사용하면
즉각 반영할수가 있다.

이러한 행위를 rebase없이
merge로 진행한다면 commit 히스토리가 모두 남아
복잡한 히스토리를 갖게된다.

rebase를 사용한다면
base를 옮김(혹은 재정의 라고 생각함)으로써
아주 깔끔하고 직관적인 history로 프로젝트를 관리할 수 있게된다.


검증

말로만 하면 너무나도 이해가 안되어
테스트 프로젝트를 만들어 한단계씩 밟아보았다.
(예제의 기준 branch는 main)

 git switch -c feature/a
 echo "blah blah" >> aa.js
 git add .
 git commit -m 'feature: aa 파일 추가'

 

git switch main
git switch -c feature/b

echo 'blah blah' >> b.js
git add -A
git commit -m 'feature: b.js 파일 추가'

여기까지.
A,B라는 두명의 개발자가 각각
feature/a, feature/b 브랜치에서
각 기능들을 개발하고 있다고 가정한다.

이제 A개발자는 해당 기능의 개발자는
개발을 마쳐 push하고 c라는 기능을 개발하러 갈것이다.
그런데 B라는 개발자는 A가 개발한 a라는 기능을 가져와
개발을 이어가고 싶은 상황이다.

rebase를 이용해 브랜치를 깔끔하게 유지하면서
문제를 해결해나가보자.

git switch main

git switch feature/a
git push origin feature/a

git switch main
git switch -c feature/c

echo "blah blah" >> c.js
git add .
git commit -m 'feature: c 기능 작업시작'

 

git switch main
git switch feature/a
git rebase feature/b

git switch feature/b
git merge feature/a



뭐가 좋아진건지 여기까지 보면 티가 안난다.
작업을 계속 진행해보자.

git push origin feature/b

echo 'blah blah' >> main.js
git add .
git commit -m 'feature: main 서비스 작업완료'
git push origin feature/b


개발자들이 위 처럼 개발을 진행하고 있을때
플젝 관리자가 중간에 PR(Pull Request)을 확인하고
먼저 검토가 완료된 feature/a를 merge한다.

git switch main
git merge origin/feature/a

 

feature/b도 확인이 완료되어 merge한다.

git merge origin/feature/b

feature/c 작업이 완료되어
A개발자는 feature/c를 push한다.

git switch feature/c
echo "mapmap" >> map.js

git add .
git commit -m 'feature: map 기능 작업완료'
git push origin feature/c


관리자가 feature/c PR을 검토 후
merge한다.

git switch main
git merge origin/feature/c



(여기부터 결과 비교가능!!)

git push

자, 결과를 보면
브랜치가 굉장히 깔끔하게 정돈된것을 볼수있다

a -> b로 병합하고
b -> main으로 병합하는 등
여러 과정이 있었음에도

마치 하나의 branch만 추가해 작업한듯이
깔끔한 커밋 히스토리가 완성되었다.
결과 확인하기


같은 과정을 rebase없이 했다면

위와 같은 결과를 받아 볼수있다: 링크

비슷해 보인다면

비교해 볼 포인트는 main 브랜치이다!


rebase없이 작업했을때는 안했을때와 달리
feature:b.js, feature:main서비스 등이
main 브랜치에 히스토리로 남고있다.

그 히스토리가 main으로 관리되지 않고
서브 브랜치로 관리되어,
main브랜치를 상대적으로
깔끔하게 관리할수있음을 확인할 수 있다

728x90
반응형

'개발, 코딩' 카테고리의 다른 글

git 기본기_백과사전(2)  (0) 2022.10.26
git 기본기_백과사전 (1)  (0) 2022.10.24
Webpack 구성 이해하기  (0) 2022.10.04
Rest API 정리  (0) 2022.09.29
java zulu jdk11 설치  (0) 2022.07.31
728x90

Bootstrap은 css, javascript 프레임워크이다

쉽게 그리드 시스템을 이용해 화면을 통일성 있게 디자인할 수 있으며,

많이 쓰이는 모달, 팝업 등의 액션을 별개의 코드없이 만들 수 있다.

 

크게 css, js 파트로 나뉘는데

오늘 css 파트에 대해 정리해본다.

 

1. 그리드 옵션

부트스트랩은 12개의 조각으로 화면을 구성한다.

위와같이 8:4, 4:4:4, 6:4 등

다양한 비율로 컴포넌트를 배치할 수 있다.

 

위에 보이는 md는 viewport에 따른 브라우저 크기 구분을 의미한다.

아래의 5가지 옵션이 있다. (Breakpoints)

1. col- (< 576px, 모바일)

2. col-sm- (>= 576px, 모바일 + 태블릿)

3. col-md- (>= 768px, 태블릿)

4. col-lg- (>= 992px, 랩탑)

5. col-xl- (>= 1200px, PC)

 

하나의 컴포넌트에도

sm, md, lg 등의 클래스를 부여함으로써

모바일, 태블릿, pc 등 각각에 알맞는 그리드 스타일 처리를 할 수 있다.

 

각 컴포넌트를 동일 크기 비율로 설정하고싶으면

클래스 col을 부여하면 된다.

(flex: 1)

보면 볼수록

Bootstrap의 docs는 퀄리티가 미친것같다.

 

2. Container

화면 디자인을 하다보면

각 컴포넌트들을 감싸기위한

Container들을 수도없이 만들게 된다.

 

Bootstrap의 컨테이너를 사용하면

통일성 있는 디자인이 가능해진다.

위와같이 클래스에 container를 부여하면

각 화면 비율에 따라 컨테이너 크기를 변경할 수 있다.

(솔직히 숙련된 퍼블리셔가 아니라면 다 외워서하기는 어려움이 있을듯한...)

 

3. Column

container

- row

-- col

-- col

의 구조로 만들어지는 bootstrap 스타일.

이번에 col에 대해서 살펴본다.

 

클래스로 row를 주면

display가 flex로 설정된다.

따라서 row와 함께 align속성을 주면

그에 맞게 컴포넌트가 배치된다.

 

flex 그리드 디자인에 대해 알고있다면

위 내용이 무슨 말인지 이해될것이다.

 

예시를 살펴보자.

align-items: flex-start

align-items: center

align-items: flex-end

를 준것과 동일하게 디자인 된것을 확인할 수 있다.

(align-items는 한 row에 있는 컴포넌트들의 위아래[Vertical] 높이 배열에 대한 속성이다.)

 

각기 별도의 css를 주지않아도

통일성있는 디자인을 할수있다니

너무나도 편리한것 같다.

 

 

align-items뿐만 아니라

justify-content 옵션도 class를 통해 줄수있다.

위와 같은 엉터리 스타일링을 할일은 없지만

justify-content를 자유롭게 적용할 수 있음을

확인할 수 있다.

(justify-content는 한 row에 있는 컴포넌트들의 좌우[Horizontal] 넓이에 대한 속성이다.)

 

 

flex디자인을 하다보면

overflow되지 않은 상황에서도

row를 분리하고싶을때가 있다.

이럴때 원래라면 row를 분리해서 배치해야겠지만

 

bootstrap에서는

중간에 div에 w-100클래스를 부여하면

row를 분리(줄바꿈)를 해줄 수 있다.

보는것처럼 overflow상황이 아님에도

flex-wrap이 없음에도!!

row가 분리되어 나오는걸 볼 수 있다.

 

 

이쯤되면 눈치챘겠지만

bootstrap은 flex 그리드 스타일에 기본을 둔다.

따라서, order옵션도 부여할 수 있다.

order는 컴포넌트의 순서를 바꿀수 있는 옵션이다.

(작은 수가 앞으로 온다.)

 

그런가하면,

align-items속성이나 justify-content로 배치하는것 외에도

offset을 이용해 좌측 margin을 줄수도있다.

offset도 마찬가지로 12개의 그리드에 기반을 둔다.

위 이미지에서 보는것처럼

offset을 준 컴포넌트에 offset만큼 좌측 margin이 들어간다.

 

margin에 auto값을 주어

좌측 혹은 우측으로 최대한 떨어뜨리는 방법도 있다.

ms-auto(컴포넌트 기준 좌측 margin),

me-auto(컴포넌트 기준 우측 margin)

(이에 대해서는 하단에서 더 자세히 다룰예정)

 

화면 비율에 따라 적용하는

ms-md-auto,

me-md-auto 등도 가능하다.

 

row로 감싸지않고

col을 쓰면 각 col은 한 열에서

그 공간 만큼만 차지한다 (예: width: 25% 등)

 

4. Spacing

bootstrap을 이용하면

클래스만으로도 쉽게

margin, padding을 부여할 수 있다.

위 이미지에 나와있지만

m으로 시작하면 margin을

p로 시작하면 padding을 주는것이다

 

m이나 p 다음에 알파벳이 온다면

t, b(top, bottom) : 위/아래

s, e(start, end) : 좌/우

x, y(x axis, y axis) : 좌우 / 위아래

 

마지막으로 size를 살펴보자

 

0과 auto는 말그대로의 수치를 의미하지만,

1,2,3,4,5는 기준이 되는 spacer에 따른 수치이다.

(1rem은 html/body에 부여된 font-size를 말함)

 

즉, 1rem=16px로 설정되어있다면

m-1은 margin: 4px

m-5는 margin: 48px

이 되는것이다.

 

 

알아야할 내용은 많지만

알아두면 굉장히 강력한 Bootstrap

이직하는 회사에서 쓰고있는것으로 보여

미리 준비해보았다.

 

728x90
반응형

'개발, 코딩 > CSS' 카테고리의 다른 글

반응형 작업 돌아보기 (+ flex)  (1) 2022.09.27
jQuery - easescroll, chrome issue  (0) 2022.02.17
HTML, div를 input으로 쓰기  (0) 2021.11.16
css, transition all 깜빡임 (flickering)  (0) 2021.07.08
viewport에 대하여  (1) 2021.01.21
728x90

최신 웹 생태계에서는 번들러가 필수적이다

typescript, scss를 파싱해야하며

코드의 압축, 난독화를 진행하기위해서도

번들러를 쓰게된다

 

그 중에서도 가장 인기있고

계속 업데이트 되고있는 Webpack에 대해 알아본다

 

핵심 4가지 요소

Webpack의 구성요소는 아래의 4개로 나눠볼 수 있다.

1. entry

2. output

3. loader

4. plugin

 

entry

entry는 webpack에서 웹 자원을 변환하기 위해

필요한 최초의 진입점이자, javascript 파일 경로다.

 

즉, entry에서 지정한 파일 경로를 대상으로

webpack이 빌드를 진행한다.

 

entry(진입점)가 되는 js에는

웹 어플리케이션의 전반적인 구조와 내용이 담겨있어야 한다.

 

SPA가 아닌 경우 object형태로 여러개의 진입점을

형성해두는것도 가능하다.

// 예시
module.exports = {
  entry: './src/index.ts',
}

 

output

output은 webpack이 빌드를 진행한 후

결과물들을 어디에 만들것인가, 즉 파일 경로를 의미한다.

 

output은 entry와 달리 object 구조를 갖는다.

(filename, path 등의 속성을 갖음)

 

output은 파일 경로를 의미하기 때문에 최소한

filename은 지정해주어야 한다.

 

filename을 지정함에 있어 4가지 옵션을 적용할 수 있다.

module.exports = {
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: [name].bundle.js,
    // filename: [id].bundle.js
    // filename: [name][hash].bundle.js
    // filename: [chunkhash].bundle.js
  }
}

1. name: entry 속성과 같은 이름을 적용

2. id: 웹팩 내부적으로 모듈 ID를 적용

3. name,hash: 매 빌드시 마다 고유 해시 값을 적용

4. chunkhash: 웹팩의 각 모듈 내욜을 기준으로 생성된 해시값을 붙임

 

위 내용들이 제법 중요하다.

실제로 프로덕트를 운영하다보면 새 코드를 배포후

새로고침 하였을때, 즉시 적용되지 않는 경우가 발생한다.

 

코드가 바뀌었음에도 파일명이 변하지않아

기존 브라우저 캐시로 인해 업데이트 사항을 인식하지 못하는 케이스다.

사용자가 강제 새로고침을 통해 해결할 수 있지만...

그런 사용자가 얼마나 있겠는가, 파일 버전관리를 잘해주어야한다.

 

loader

webpack이 웹 어플리케이션을 해석할 때,

js가 아닌 웹 자원들을 변환하려면 loader를 적용해주어야한다.

(웹 자원: html, css, image, font 등)

 

loader는 module이라는 속성명을 갖는다.

module 속성 내 rules에 배열 구조로

loader를 설정하게된다.

 

rule은 test, use의 속성을 갖는다.

test는 loader를 적용할 파일 유형이고,

use는 해당 파일에 적용할 loader의 이름이다.

module.exports = {
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: [name].bundle.js,
  },
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
            option: {
              module: true
            }
          },
          { loader: 'sass-loader' }
        ]
      },
      { 
        test: /\.ts$/, 
        use: 'ts-loader' 
      }
    ]
  }
}

주로 많이 사용하는 loader로는

babel-loader, sass-loader, file-loader, ts-loader 등이 있다.

 

위 예시에서 보는것 처럼 하나의 rule에

여러개의 loader를 설장할수도 있는데, 이 때 loader의 순서도 매우 중요하다.

loader는 코드 순서 상, 기본적으로 우 -> 좌 (아래 -> 위)로 적용한다.

예시로 보면 sass-loader > css-loader > style-loader 순으로 적용된 다는것이다.

 

plugin

웹팩의 기본적인 동작 외에,

추가적인 기능을 제공하기 위한 특성이다.

 

plugin 속성에 배열 구조로 값을 받는다.

plugin은 생성자 함수로 생성된 인스턴스 객체만을 추가할 수 있다.

 

주로 사용되는 plugin으로는

split-chunk-plugin, clean-webpack-plugin, image-webpack-plugin 등이 있다.

module.exports = {
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: [name].bundle.js,
  },
  module: {
    rules: [
      { 
        test: /\.ts$/, 
        use: 'ts-loader' 
      }
    ]
  },
  plugin: [
    new webpack.progressPlugin(),
    new htmlWebpackPlugin({ template: './public/index.html' })
  ]
}

 

 

webpack의 동작 방식

지금까지 webpack 설정을 위한 구성요소를 알아봤다면

마지막으로 동작방식에 대해 알아본다.

 

1. webpack이 entry에서 부터 해석을 시작

2. 해석에 있어 각 loader들을 적용한다.

3. loader를 적용한 결과물을 산출한다.

4. 산출된 결과물에 plugin을 적용한다.

5. 산출된 결과물이 output 경로에 생성된다.

728x90
반응형

'개발, 코딩' 카테고리의 다른 글

git 기본기_백과사전 (1)  (0) 2022.10.24
git 협업하기 - 실무편  (0) 2022.10.23
Rest API 정리  (0) 2022.09.29
java zulu jdk11 설치  (0) 2022.07.31
M1 Mac, homebrew install (Warning: /opt/homebrew/bin is not in your PATH.)  (0) 2022.07.31
728x90

문제 상황

// _app.tsx

function App({ Component, pageProps }) {
  useEffect(() => {
    console.log('rendering')
  }, [])
  
  return <Component {...pageProps} />
}

영향을 줄만한 코드 일체없이

_app.tsx에서 위와 같이 코드를 설정했음에도

useEffect가 두번도는 큰 문제가 발생했다.

 

이것을 나중에 api요청과 처리 과정에서 발견했는데,

redux 코드에 문제가 있는건지

re-rendering 과정에 사이드 이펙트가 발생하는건지

한참을 돌고 돌아 문제의 원인을 찾았다.

(15분은 낭비한듯..)

 

문제 원인

바로, react의 strict모드 설정 이슈였다.

strict모드의 어떤 부분에서 이슈가 발생했는지

stict모드가 무엇인지 살펴보자.

 

react docs에 보면 아래와 같은 문장이 있다.

Strict mode can’t automatically detect side effects for you, 
but it can help you spot them by making them a little more deterministic. 
This is done by intentionally double-invoking the following functions:

1. Class component constructor, render, and shouldComponentUpdate methods
2. Class component static getDerivedStateFromProps method
3. Function component bodies
4. State updater functions (the first argument to setState)
5. Functions passed to useState, useMemo, or useReducer

사이드 이펙트를 방지하는데 도움을 주기위해

5가지 경우에 대해 함수를 두번 호출한다고 명시되어있다.

 

그 중에서도 내 눈에 띈것은 Function component body...

함수형 컴포넌트의 Body구문에서 두번 호출된다면

어지간하면 두번 호출된다는 것이라 생각된다.

 

문제 해결

그렇다. strict 모드를 해제하면 일단

두번 호출되는 문제는 해결된다.

// next.js 기준
// next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
    reactStrictMode: false, // <-- 이 부분 false로 변경
    swcMinify: true
};

module.exports = nextConfig;

 

Strict 모드란?

strict모드가 어떤 도움을 주는지

해제했을때 어떤 문제가 발생할 수 있는지

가볍게 살펴보자

 

문서 첫 줄에 이렇게 명시되어있다.

"StrictMode는 애플리케이션 내 잠재적인 문제를 알아내기 위한 도구이다."

그리고 "Strict 모드는 개발 모드에서만 활성화되며, 프로덕션에 영향을 주지는 않는다."

 

즉 위의 문제도 사실 프로덕션에서는 발생하지 않을 이슈였던것이다.

그럼에도 개발단에 거슬리긴 했다.

 

다른 도움되는 부분이 없다면 해제하고 마무리하는것으로 하자.

Strict가 도움을 주는 부분 6가지 (확장 예정)

1. Identifying components with unsafe lifecycles
2. Warning about legacy string ref API usage
3. Warning about deprecated findDOMNode usage
4. Detecting unexpected side effects
5. Detecting legacy context API
6. Ensuring reusable state

 

사이드 이펙트 방지가 마음에 드는데

방지를 위해 두번 요청하는 (우리가 부작용이라 생각했던) 동작이

아래와 같은 경우에 발생한다고 한다.

렌더링 단계 생명주기 메서드는 클래스 컴포넌트의 메서드를 포함

1. constructor
2. componentWillMount (or UNSAFE_componentWillMount)
3. componentWillReceiveProps (or UNSAFE_componentWillReceiveProps)
4. componentWillReceiveProps (or UNSAFE_componentWillReceiveProps)
5. getDerivedStateFromProps
6. shouldComponentUpdate
7. render
8. setState

 

 

결론

아직 대부분 class component의 생명주기 메서드들에 해당하는 내용으로 보인다.

그러므로 나는 일단 strict mode는 해제하도록 하겠다.

 

 

참고

728x90
반응형
728x90

Recoil 배경

Recoil은 Facebook이 만든 상태관리 라이브러리로

리액트의 상태관리를 위해 만들어진 라이브러리다.

매우 React스러운 Recoil에 대해 알아보자.

 

Recoil 구성요소

Recoil은 크게 2가지 요소로 나뉜다.

Atom과 Selector

 

Atom은 상태의 단위로, 상태를 정의하거나 불러올 수 있다.

Atom이 업데이트 되면 Atom을 구독하는 컴포넌트들이 업데이트된다.

Atom은 고유한 key와 default 값을 갖는 객체로 구성된다.

const phoneState = Atom('UserPhone', {
  key: 'Phone',
  default: ''
});

const [phone, setPhone] = useRecoilState(phoneState);
// const phone = useRecoilValue(phoneState);
// const setPhone = useSetRecoilState(phoneState);

useEffect(() => {
  getUserPhone()
}, [])

const getUserPhone = async () => {
  const { data } = await axios.get(uri);
  setPhone(data);
}

 

Selector는 고유한 key와 get과 set으로 구성되어 순수 함수로써 동작한다.

순수함수로써 동작한다는 것은 같은 입력이 주어진다면 항상 같은 결과를 반환해야 한다는 것이다.

내부의 다른 요소로 인해 결과가 바뀌는 등의 상황이 없어야 한다는 것.

const phoneState = Atom('UserPhone', {
  key: 'Phone',
  default: ''
});

const getPhoneSelector = () => selector({
  key: 'UsePhone',
  get: async ({ get }) => {
    try {
      const { data } = await axios.get(uri);
      return data;
    } catch(error) {
      throw error;
    }
  },
  set: ({ set }, newValue) => {
    set(phoneState, newValue);
  }
})

반드시 비동기 요청을 위해 쓸 필요는 없지만

위와 같이 비동기 요청을 위해 사용할 수 있다.

 

비동기 요청 로직을 분리하여

요청 후 결과를 atom에 set하는 형태를 갖출수도 있지만,

selector를 이용해  응집도를 높일 수 있다.

 

뿐만 아니라, selector는 캐싱 기능이 있다.

캐싱 기능의 장점은 이미 받아왔던 값을 기억하고 있어

같은 응답을 보내는 api call에 대해서는 추가적으로 요청하지 않아

성능적으로 훨씬 유리하다.

 

* 캐싱과 관련해 주의할 부분

사용자가 항상 최신의 데이터를 확인해야 하는 화면에서

캐싱 기능은 데이터 무결성을 초래하는 위험 요소가 될 수 있다.

따라서, 항상 최신의 데이터를 확인해야 할만한 상황에 대해서 미리 파악 해두어야한다.

예를들어

  - 사용자가 화면을 보고있을 때

  - 페이지가 전환되며 새 페이지에 진입했을 때

  - 페이지 전환없이도, 무언가 추가적인 데이터를 요청할 때

등이 있을 수 있다.

이러한 상황 외에는 적극적으로 캐싱 기능을 활용한다면

자원을 아끼고 효율을 높일 수 있을 것이다.

Recoil 비동기 처리?
Recoil에서도 비동기 요청 처리에 있어

Redux에서 처럼 error, loading 등의 상태를 확인할 수 있을까?

selectoruseRecoilValudLoable을 함께 쓴다면 가능하다.

 

const phoneLoadable = useRecoilValueLoadable(getPhoneSelector);

phoneLoadble.state
// hasValue, hasError, loading 세가지의 현재 상태를 갖음

phoneLoadable.contents
// hasValue 상태 일때: value 정보
// hasError 상태 일때: error 정보
// loading 상태 일때: Promise

 

참고1

참고2

728x90
반응형
728x90

수년간 사용해왔지만

누군가 내게 Rest API가 도대체 무엇이냐 묻는다면

어떻게 설명할 수 있을까

 

REST

Representational State Protocol의 약자이다

네트워크 아키텍쳐 원리의 모음이며, "자원을 정의하고", "자원에 대한 주소를 지정" 하는 방법을 통칭한다.

 

 

REST API

REST를 따르는 API

URI를 이용하여 정보의 자원을 지정하고

HTTP METHOD를 통해 자원에 대한 행위를 표현하는

설계 아키텍쳐 방법을 말한다.

 

 

REST API 구조

1) 자원 (resource) - URI

2) 행위 - HTTP METHOD

3) 표현 - Presentation

 

URI는 정보의 자원을 표현해야 한다.

자원에 대한 행위는 HTTP METHOD로 표현해야 한다.

 

나쁜예, 좋은예를 통해 Rest API를 확실히 정리하자

[ 나쁜예 ]
POST /api/poster/delete/:id
[ 좋은예 ]
DELETE /api/post/:id

 

아주 단순하지만

REST하다는 것이 무엇인지 충분히 와닿는 예시라고 생각한다.

 

이런 식으로 설계된 API를 보고

REST하다고 하여 Restful API라고 부르기도 한다.

 

 

** 한걸음만 더! **

REST API의 또 다른 장점

-> HTTP Protocol이 stateless protocol이기 때문에, REST API 역시 무상태성을 가진다.

무상태성을 가진다 함은 Client의 context를 서버에 저장하지 않는다는 뜻이다.

즉, 세션이나 쿠키같은 contect정보를 신경쓰지 않아도 된다는 것이고 그만큼 구현이 단순해 진다는 장점을 갖는 것이다.

728x90
반응형
728x90

누군가 내게 이런 질문을 해주었고,

다시 한번 고민해보고 공부해볼 좋은 기회가 되었다.

(보다 정확한 공부를 위해 React Docs를 살펴보았다.)

 

useEffect

둘을 비교하기 위해서는 useEffect를 먼저 이해할 필요가 있다.

 

useEffect를 이렇게 설명할 수 있을것 같다.

1) 특정 조건이 발생할 때(인자),

2) 지정된 명령을 수행하라(실행함수).
3) 컴포넌트가 제거될때 수행할것이 있다면 return을 작성하라.

 

(구조)

useEffect(실행 함수, 인자);


(사용 예시)

useEffect(() => {

}, [])

useEffect(() => {
  return () => {
  }
}, [])

useEffect(() => {
  return () => {
  }
}, [state.user])

 

 

useEffect의 동작 기준

1. 인자가 빈 배열인 경우: 모든 레이아웃 배치와 그리기를 마친 후 실행됨

2. 인자가 빈 배열이 아닌 경우: 배열의 state나 props가 변경될 때 실행됨

 

 

모든 레이아웃 배치와 그리기를 마친 후 실행된다고 했는데,

이 부분에 대해서 더 자세히 살펴보자.

 

useEffect 상세 실행순서

1) component render가 시작됨

2) rendered component가 화면에 그려짐

3) useEffect가 실행됨

 

자, 여기까지 살펴보고아래의 코드가 동작했을 때

사용자가 어떤 경험을 하게될지 예상해보자.

const [username, setUsername] = useState('')
useEffect(() => {
  setUsername('홍길동')
}, [])

return (
  <p>{username || '비회원'}</p>
)

사용자 경험에 어떤 문제가 있었을지

대충 눈치챘을 것이다.

 

사용자는 비회원이 아님에도

비회원을 목격한 뒤 홍길동이라는 이름이 보여지는 것을

목겨하게 될것이다.

 

 

useLayoutEffect

이러한 상황을 위해 useLayoutEffect가 존재한다.

 

useLayoutEffect 상세 실행순서

1) component render가 시작됨

2) useLayoutEffect가 동기적으로 실행됨

3) rendered component가 화면에 그려짐

4) (useEffect가 실행됨)

 

실행 순서 덕분에 위와 같은 상황에서는

useLayoutEffect를 쓴다면

조금 더 좋은 사용자 경험을 제공할 수 있다.

 

 

 

그렇다면 언제 useEffect를 써야할까?

일반적으로는 useEffect를 쓰는것이 퍼포먼스 면에서 유리하다.

 

왜냐면 위에서 언급했듯이 useLayoutEffect는

동기적으로 동작하기 때문에 퍼포먼스면에서는

권장되지 않기 때문이다.

 

일반적으로 useEffect를 사용하도록 하며

특히나 구독이나 이벤트 핸들러의 설정 등의 상황에서는

useEffect를 통해 필요한 시점에서만 실행되도록 하고

메모리 누수 방지를 위해 return을 통해 구독 해지시키는 것이 좋다.

 

 


(번외)

그 외에 react를 처음 사용하다보면

한번쯤 useEffect로 인해 겪게되는 이슈가 있다.

 

"어? 왜 자꾸 상태 값이 초기값으로 나오지?"

 

Docs를 자세히 보면 위 문제의 원인을 확인할 수 있다.

원인은 바로 useEffect에서 다루는 state, props가 인자에서 누락되었기 때문이다.

(useEffect에서 변경된 state,props를 확인하려면 인자에 useEffect에서 다루는 모든 state,props가 있어야함)

 

이것을 달리 말하면,

useEffect에서 인자로 빈 배열을 받았다면

useEffect에서 다루는 state나 props는 항상 초기값을 갖는다는 뜻이다.

 

심지어 이 사항은

useEffect에서 호출하는 함수에도 모두 적용되는 사항이니

명확히 알고 사용해야한다.

 

 

 

(수정할 사항이 있다면 제발 알려주세요. 저에게 큰 도움이 됩니다.)

728x90
반응형
728x90

css를 수년간 써왔지만

처음 공부할때를 제외하고는

실무 사용과 관련해 정리해보지 못했다.

 

너무 일상적으로 사용해

체득되어 "당연하다"라고 생각하고 썼기때문.

 

분명히 이러한 사용법은

훗날 문제를 야기할것이라는 생각이들어

반응형 작업과 Flex에 대해 정리해본다.

 

1. Viewport

반응형의 시작은 Viewport이다.

Viewport는 웹페이지에서 사용자에게 보여지는 영역에 대한 속성을 말한다.

<meta name='viewport' content='width=device-width; initial-scale=1'>

웹개발을 했다면 누구나 봤을 위 코드.

vscode에서 기본 자동 생성 될만큼 핵심적인 meta 속성이라고 볼 수 있다.

 

Viewport의 요소들을 짚어보자

1. width: 브라우저 스크린의 기본 넓이를 말함

2. device-width: 디바이스의 가로 넓이를 말함

3. initial-scale: 페이지 접속시 보여질 화면 배율을 말함

4. maximum-scale: Viewport 최대 배율을 말함

5. minimum-scale: Viewport 최소 배율을 말함

 

2. media query

다음은 media query이다.

media query는 css 반응형 코드를 작성할 때, 기준을 잡는 역할을 한다.

미디어 유형 / 논리 연산자 / 특성
@media (max-width: 768px) & (min-width: 1024px) {
}

@media only screen (max-width: 768px) and (min-width: 1024px) {
}

@media only screen (max-width: 768px) and (min-width: 1024px) and (orientation: landscape) {
}

위와 같은 방식으로 쓸 수 있다.

그런데 보통 가장 위에 형태로 많이 쓰인다.

 

모바일에 작업의 중점을 둘것이냐

데스크탑에 작업의 중점을 둘것이냐에 따라

min-width, max-width 둘 중 하나만 사용하는게 일반적이다.

 

<-- 데스크탑 베이스 -->

// 랩탑 이상 (기본)
.content {
}

// 랩탑
@media (max-width: 1024px) {
  .content {
  }
}

// 태블릿
@meida (max-width: 768px) {
  .content {
  }
}

// 모바일
@media (max-width: 430px) {
  .content {
  }
}
<-- 모바일 베이스 -->

// 태블릿
@media (min-width: 431px) {
  .content {
  }
}

// 랩탑
@media (min-width: 769px) {
  .content {
  }
}

// 랩탑 이상
@media (min-width: 1025px) {
  .content {
  }
}

// 모바일 (기본)
.content {
}

 

차이점을 분명 알수있을것이다.

max-width: 화면 크기가 이것보다 작으면 적용하라

min-width: 화면 크기가 이것보다 크면 적용하라

 

이정도면 실무에 별 문제가 없지만

그래도 각 구성요소에 대해 알아본다.

 

* 미디어 유형

screen: 화면을 대상

all: 모든 디바이스를 대상

print: 인쇄 결과물, 인쇄 미리보기 문서를 대상

 

* 논리 연산자

and: 모든 쿼리가 참이면 적용

not: 모든 쿼리가 거짓이면 적용

,: 어느 한 쿼리라도 참이면 적용 (or)

only: 미디어 쿼리를 지원하는 대상만 적용

 

* 특성 (상태)
width: 너비

height: 높이

aspect-ratio: 가로/세로 비율

orientation: Viewport 방향

 

 

3. flex style

마지막으로,

최근 작업에서는 컴포넌트 배치 관련된 css는

항상 flex로 적용하고 있다. 그 만큼 편리하고 강력하다.

각 속성에 대해서 정확히 짚어놓고 가자.

display: flex;

 

display 속성중 하나인 flex.

flex를 적용하면 해당 태그는 방향에 대한 특성을 갖게 된다.

웹에서 flex의 기본 방향성은 가로축이다.

display: flex;
flex-direction: row; // 가로 배치에 대한 특성을 갖음
flex-direction: column; // 세로 배치에 대한 특성을 갖음

즉, 웹에서 flex의 기본 direction은 row라는 이야기이다.

 

 

그럼, 아래의 문제를 풀어보자.

1,2,3은 어떻게 배치될까?

<div>
  <ul style="display: flex;">
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
</div>

 

맞다

1 2 3

가로로 배치된다.

 

<div>
  <ul style="display: flex; flex-direction: column;">
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
</div>

이렇게 했다면

1
2
3

세로로 배치되었을 것이다.

 

 

여기까지 했으면

flex의 25%정도 이해했다고 보면된다.

지금까지 "방향성"이라는 특성에 대해 공부했다면

이번에는 내부 요소들을 "어떻게" 배치할 것인지에 대해 알아볼 차례이다.

 

내부 요소에 대한 배치 메인 특성으로는 2가지가 있다.

1. justify-content: flex-start / flex-end / center / space-between / space-evenly / space-around

2. align-items: flex-start / flex-end / center / stretch

 

justify-content부터 하나씩 알아보자.

먼저, 가로축 상태에서의 justify-content 참고

<div>
  <ul style="display: flex; justify-content: flex-start;">
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
</div>

* 예상 화면
[123       ]
<div>
  <ul style="display: flex; justify-content: flex-end;">
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
</div>

* 예상 화면
[       123]
<div>
  <ul style="display: flex; justify-content: center;">
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
</div>

* 예상 화면
[   123    ]
<div>
  <ul style="display: flex; justify-content: space-between;">
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
</div>

* 예상 화면
[1    2    3]
<div>
  <ul style="display: flex; justify-content: space-evenly;">
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
</div>

* 예상 화면 - 전체 여백이 균일하게
[  1  2  3  ]
<div>
  <ul style="display: flex; justify-content: space-around;">
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
</div>

* 예상 화면 - 요소간 여백이 균일하게
[ 1   2   3 ]

 

세로축 상태에서의 justify-content는

가로로 적용되던 속성이 세로로 적용된다고 보면 정확하다.

 

가로축 에서의 align-items도 알아보자

<div>
  <ul style="display: flex; justify-content: flex-start;">
    <li>1</li>
    <li style="height: 100px;">2</li>
    <li>3</li>
  </ul>
</div>

* 예상 화면 - 요소간 여백이 균일하게 (실제로는 2가 길게 세로 전체를 덮고 있다고 보면 되겠다)
|123       |
|          |
|          |
<div>
  <ul style="display: flex; justify-content: flex-end;">
    <li>1</li>
    <li style="height: 100px;">2</li>
    <li>3</li>
  </ul>
</div>

* 예상 화면 - 요소간 여백이 균일하게
|          |
|          |
|123       |
<div>
  <ul style="display: flex; justify-content: center;">
    <li>1</li>
    <li style="height: 100px;">2</li>
    <li>3</li>
  </ul>
</div>

* 예상 화면 - 요소간 여백이 균일하게
|          |
|123       |
|          |

 

세로축에서의 align-items는

가로축에서의 align-items에 적용되던 속성이 세로로 적용된다고 보면 정확하다.

728x90
반응형
728x90

React 개발을 하다보면

state, props로는 depth가 너무 깊어지는

props drilling문제가 발생하는 시점이 온다.

 

또한,

단계별 진행이나 페이지 변경 후에도 상태를 유지해야 하는 List뷰 등에서

어려움을 겪게된다.

 

이러한 문제들을 해결해주는 것이

global state관리를 도와주는 라이브러리들이다.

그 중에서 local global state라고 부르도록 하겠다.

 

주요 상태관리 라이브러리

1. Context API

2. Recoil

3. MobX

4. Redux

 

위 4가지 정도가 있는데,

1에서 4로 갈수록 러닝커브가 높다고 생각하는 바이다.

그럼에도 각 장,단점이 있으니 알아보도록 하자.

 

1. Context API

ContextAPI는 4가지 중에 유일하게
React 내장 상태관리 기능이다.

즉, 별도의 라이브러리 설치 없이 사용 가능하다는 말이다.

 

Docs를 보고 처음 사용 하는 사람도
쉽게 적용할 수 있는 수준이니

러닝커브 또한 낮다고 할 수 있다.

 

ContextAPI가 처음 나왔을때는

언어설정이나 색상테마 등

잘 변경되지 않는 상태를 관리할때 쓰였다.

 

그러나 지금은

전역상태 관리로 사용하던

지역상태 관리로 사용하던

개발자의 자유일뿐

상태 관리 기능으로써 충분한 지원을 하고있다.

 

참고

 

그럼에도 다른 라이브러리들을

추가 설치해 사용하는 이유가 있다.

 

 

2. MobX

언급할 내용은 MobX뿐 아니라

Redux, Recoil등 다른 라이브러리들을

사람들이 사용하는 이유이다.

 

4가지 모두 상태관리라는 컨셉을 가지고 있지만 그 안에서 나뉘는 개별 특징들이 있다.

그중에 내게 맞는 특징을 갖는 라이브러리를 택하면 되는것이다.

 

MobX는 전역상태관리 기능을 제공한다.

뿐만 아니라 상태 업데이트 로직을 View Component 밖에서(코드 분리) 할 수 있도록 도와준다.

Redux에 비해 적은 보일러 플레이트 코드, 직관적인 코드를 갖는다는 특징도 있다.

 

다만, MobX에서는 여러개의 Store를 둘 수 있는데

그로인해 예상치 못한 업데이트 등이 발생할 수 있다는 단점아닌 단점이 있다.

 

3. Redux

Redux도 MobX와 마찬가지로

전역상태관리 + 상태 업데이트 로직 분리를 돕는다.

 

하나의 Store를 갖는 특징으로

상태가 업데이트 될때 정확하게(직관적으로)

해당하는 상태를 갖는 컴포넌트들만 업데이트 된다는 장점이 있다. (유지보수의 편안함)

 

다만, Redux는 비동기 처리를 위해

thunk, saga 등 추가적으로 라이브러리들이 붙게되고

보일러플레이트 코드가 너무 많아진다는 단점을 가지고 있다.

 

4. Recoil

최근 각광받고 있는 Recoil은

react를 개발/운영하고 있는 Facebook(Meta)에서 개발한 만큼

가장 react 친화적이라는 장점을 가지고있다.

뿐만 아니라 매우 사용 방법이 매우 간단하고 직관적이다.

 

ContextAPI가 상태를 일일이 만들어야 하는 과정을 가진데 반해

Atom을 통해 매우 간결하게 상태관리를 할 수 있다.

캐싱을 통한 최적화 기능은 보너스이다.

 

 

 

최근,

이직 준비를 하며 많은 기업들에서 Recoil을 도입하고 있는것을 보게되었다.
사이드 프로젝트에 적용해 공부중인데 매우 합리적인 선택지라는 생각이 든다.

 

현직 개발자들은 대부분 현명하고, 최선의 선택을 하기위해 노력하는 만큼

Recoil이 사랑받는데는 분명히 이유가 있다.

 

 

 

(수정할 사항이 있다면 자유롭게 알려주세요. 저에게 큰 도움이 됩니다.)

728x90
반응형
728x90

MVC 패턴

구성

1. Model: 어플리케이션에서 사용되는 데이터와 그 데이터를 처리하는 로직을 담당

2. View: 사용자에게 보여지는 UI 담당

3. Controller: 사용자의 입력을 받고 처리하는 부분

 

동작 방식

View에서 사용자가 액션

-> Controller에 액션이 전달됨, Model이 처리해야될 일이면 Model로 액션을 전달

-> Model이 데이터를 처리

-> Model이 View로 업데이트된 데이터를 전달

 

특징

1. Controller는 여러개의 View를 선택할 수 있는 1:N 관계를 갖음

2. Controller는 View에 직접 데이터를 전달하지는 않음

 

장점

가장 단순하고 많이 쓰이는 보편적인 패턴

 

단점

View와 Model 사이의 의존도가 높음 -> 앱이 커지고 복잡해질수록 유지보수가 어려워짐

 

 

------------------------------------

 

 

MVP 패턴

구성

1. Model: 어플리케이션에서 사용되는 데이터와 데이터를 처리하는 로직을 담당

2. View: 사용자에게 보여지는 UI를 담당

3. Presenter: 사용자의 요청을 처리하고 View와 Model을 연결

 

동작 방식

View에서 사용자가 액션

-> Presenter에 액션이 전달됨, Model이 처리해야될 일이면 Model로 액션을 전달

-> Model이 데이터를 처리 후 Presenter로 응답

-> Presenter가 Model의 응답을 View로 전달

 

특징

1. MVC와 달리 Model과 View과 분리됨

2. 오직 Presenter를 통해서만 상태나 변화를 알려줄 수 있음

3. Prenseter와 View가 1:1 관계를 갖음

 

장점

View와 Model의 의존도를 없앰

 

단점

View와 Presenter의 의존도가 높아져, MVC 패턴의 문제를 그대로 가지고 있음

 

 

------------------------------------

 

 

MVVM 패턴

구성

1. Model: 어플리케이션에 사용되는 데이터와 데이터를 처리하는 로직을 담당

2. View: 사용자에게 보여지는 UI를 담당

3. View Model: View를 처리하기 위해 만든 View를 위한 Model, View를 나타내기 위한 데이터와 데이터를 처리하는 로직을 담당

 

동작 방식

Model을 가지고, Command Design Pattern을 통해 View를 위한 ViewModel을 생성

-> ViewModel 인스턴스를 View에 props로 넘겨줌

-> View와 Model이 Data-binding됨

-> View에서 사용자가 액션

-> View Model에 액션이 전달됨, Model이 처리해야될 일이면 Model로 액션을 전달

-> Model이 데이터를 처리 함

-> Presenter가 Model의 응답을 View로 전달

 

특징

1. Command Design Pattern과 Data-Binding, 두가지 패턴을 사용하여 구현됨

2. View와 View Model, View와 Model 간의 의존도 문제가 위 두가지 패턴으로 해소됨

 

장점

의존성이 사라져 각 부분을 모듈화하여 개발할 수 있음

 

단점

View Model을 잘 설계하는 것이 어려움

728x90
반응형