728x90

1. string

문자열 타입

 

2. number

숫자

 

3. booelan

true/false

 

4. undefined

데이터 타입이 있는지 없는지 알수없는 경우에 주로 쓰이며

단독으로 쓰이기 보다는

string | undefined와 같이 쓰인다.

(| 는 유니온 타입으로 A타입 또는 B타입 처럼, 타입을 또는 이라는 키워드로 묶어준다.)

 

5. null

undefined과 유사하지만

값이 있는지 없는지에 대한것

주로, string | null 형태로 쓰인다

 

6. unknown 💩

any와 마찬가지로 어떤 type이든 올수있다.

무엇이 올지 알수없을때 사용되는데,

사실 typescript에서는 사용되지는 않고

javascript와 혼합해서 코드를 작성할때

무엇이 return되는지 알수없거나 할 때 사용한다.

 

7. any 💩

무엇이든, 어떤것이든 할당할 수 있는 타입이다.

정말 불가피한 경우에 도피처로 사용된다.

 

8. void

함수가 동작은 하지만

return이 없는 함수인 경우 혹은 return; 인 경우

void type에 해당한다.

 

9. never

함수에서 while: true, throw error와 같이

앱이 죽을 정도로 절대로 리턴이 발생할 수 없는 경우의

타입에 해당한다.

 

10. object 💩

어떤 타입의 object(객체)라도 받을 수 있는 타입이다.

심지어 배열도 가능하다.

 

11. Promise

함수에서 promise를 return하는 경우 사용되며

주로 Promise<number>와 같이

리턴되는 데이터를 제네릭으로 갖는다.

 

12. array

string[] 또는 Array<string>으로 정의할 수 있다.

readonly를 부여해서 수정 불가능하게 만들수도 있다.

const numbers: readonly number[] = [1,2,3];

function sum(numbers: readonly number[]) {
...
}

 

13. Tuple 💩

배열과 비슷하지만 각 자리에 오는 값의 타입을 정할 수 있다.

const items: [string, number] = ['pen', 100];

 

14. type alias

타입을 직접 정의하는것

type device = {
  laptop: string;
  phone: 'iphone' | 'galaxy';
};

 

15. String Literal

위에 alias타입에서 슬쩍 나온 부분이다.

type OS = 'ios';
const myPhone: OS = 'galaxy'; // error
const myPhone: OS = 'ios'; // ok

지정된 문자열 값만 허용하는 타입이나

 

16. union

위에서도 몇번 나왔지만

union타입이란 

A 또는 B 또는 C ... 와 같이

몇개의 타입중에 하나에 해당하는 것이라고 정의할 때 쓰인다.

type OS = 'linux' | 'macos' | 'window';

 

17. Discriminated union

alias와 union타입을 적절하게 이용하면,

보다 나은 개발을 할 수 있다.

type SUCCESS_RESPONSE = {
  result: 'success';
  body: {
    code: string;
    data: string;
  };
};

type FAILED_RESPONSE = {
  result: 'failed';
  reason: string;
};

type API_REPSONSE = SUCCESS_RESPONSE | FAILED_RESPONSE;

// res.result 자동완성 가능
function requestSomething(res: API_RESPONSE) {
  if (res.result === 'success') {
  } else {
  }
}

 

18. intersection

union이 or과 같다면

intersection은 and와 같다.

A타입 이면서 B타입인 경우에 사용한다.

type desk = {
  material: string;
  size: number;
};

type table = {
  color: string;
  height: number;
};

const multiDesk: desk & table = {
  material: '',
  size: 1200,
  color: 'white',
  height: 600,
};

 

19. Enum 💩

여러가지 관련된 상수를 정의할때 사용한다.

// js
const DAYS = Object.freeze({
  "MONDAY": 1,
  "TUESDAY": 2,
});

//ts - enum에 값을 지정하지 않으면 맨 위부터 0으로 초기화됨
enum DAYS {
  Monday,
  Tuesday
};

enum REST {
  POST = 'POST',
  GET = 'GET',
};

enum으로 타입을 설정했더라도

다른 값으로 값을 초기화 할수 있다는 이슈가 있다.

즉 타입이 보장되지 않는다.

const yesterday: DAYS = 1; // ok
const today: DAYS = 10; // ok..?

위와 같은 경우에는

유니온 타입으로 타입을 정의하는게 더 바람직하다.

 

20. type assertion 💩

타입에 대해 완전히 확신할때 타입을 강제로 캐스팅하여

타입의 메소드를 사용할 수 있다.

 

typescript에서는 거의 쓰이지 않지만

js코드와 병행해서 작업할때 종종 쓰일 수 있다.

function sum(a: number, b, number): number {
  return a + b;
}

const result = sum(1, 5);
(result as string).length; // undefined
(result as Array<number>).length // app crahsed
result!.length; // app crahsed, 완전히 타입에 대해 확신할때 !를 사용하여 warning을 제거할 수 있다

 

728x90
반응형
728x90

git stash

(working directory에) 작업중인 사항이 있는데

긴급히 다른 브랜치의 코드를 가져와 확인해야 한다면,

stash를 이용!

 

미완성 코드를 commit 하지 않고

stash stack에 임시로 보관했다가

다른 작업을 충분히 수행한 후,

내 코드를 다시 가져와 작업을 이어갈 수 있다.

 

혹은 버그를 잡기위한 시도를 하던중

잘 안됐더라도 의미 있는 작업을 했을때

임시 보관을 위해 stash에 저장해둘수도 있다.

# stash에 작업중인 사항 보관하기 - 1
git stash

# stash에 작업중인 사항 보관하기 - 2
git stash push

# msg와 함꼐 stash
git stash -m "<메세지>"

# 작업내역을 유지한채 stash에도 추가 (stash에 현재 작업내용 카피 떠두는 개념)
git stash -m "<메시지>" --keep-index

# untracking 파일포함 보관하기
git stash -u

# stash 목록 보기
git stash list

# stash 이력별 수정내용 보기
git stash show <stashId> -p

# stash 목록에서 최신 stash 다시 가져오기 (stash는 유지됨)
git stash apply

# stash 목록에서 선택해 stash 다시 가져오기
git stash apply <stashId>

# stash 목록에서 최신 stash 다시 가져오기 (stash는 제거됨)
git stash pop

# stash 제거
git stash drop <stashId>

# stash 전체 삭제
git stash clear

# 최신 stash를 가져오면서 새 브랜치에 적용
git stash branch <브랜치명>

 

git restore

working directory에 있는 작업중인 사항을 초기화

# working directory내 전체 초기화
git restore .

# 새로 추가된 파일은 restore로 제거되지 않음, 이때 사용하는 force directory
git clean -fd

# working directory내 특정 파일 초기화
git restore <파일명>

# add되어 staging area에 있는 파일을 working directory로 다시 가져옴
git restore --staged <파일명>

# add되어 staging area에 있는 모든 파일을 working directory로 다시 가져옴
git restore --staged .

# commit history로 초기화
git restore --source=<해시코드> <초기화할파일>

 

git commit --amend

commit 메시지를 잘못 적은 경우,

commit한 파일을 수정해야되는 경우,

직전에 수정한 commit을 수정할 수 있다

# 직전 커밋 메시지 수정하기
git commit --amend -m "<메시지>"

# 커밋한 파일의 내용을 수정해야할때, 추가 커밋없이 파일 수정
커밋했던 파일 현재 working directory에서 수정
git commit --amend

 

git reset

특정한 커밋으로 모든것을 초기화(지움) 할수있다.

원하는 버전의 해시코드로 reset하면 그 사이의 커밋은 제거된다.

 

--mixed

커밋 히스토리를 삭제하면서 해당 내용을

working directory로 작업 내역이 옮겨짐

 

--soft

커밋 히스토리를 삭제하면서 해당 내용을

staging area로 작업 내역이 옮겨짐

 

--hard

커밋 히스토리를 삭제하면서 해당 내용도 완전히 삭제

# 현재 ~ 해당 해시코드 사이의 commit 제거 + 내용은 working directory로 이동 - 1
git reset <해시코드>

# 현재 ~ 해당 해시코드 사이의 commit 제거 + 내용은 working directory로 이동 - 2
git reset --mixed <해시코드>

# 현재 ~ 해당 해시코드 사이의 commit 제거 + 내용은 staging area로 이동
git reset --soft <해시코드>

# 현재 ~ 해당 해시코드 사이의 commit 제거 + 내용은 삭제
git reset --hard <해시코드>

**주의사항

현재 working directory에 수정사항이 있는 상태에서

reset을 진행했다면 (특히, --hard)

작업중이 사항을 전부 잃을 가능성이 매우 높다

 

reset을 하기전에 working directory에 있는 파일들은

가능한 commit/stash 해두도록 하자.

 

git reflog

이전에 HEAD가 가리키고 있던 내역들을 전부 확인할 수 있다.

(내가 여태까지 실행했던 명령과 HEAD가 가리켰던 포인터들을 전부 확인 가능)

# 명령 이력 조회
git reflog

# 특정 해시코드로 돌아가기
git reset --hard <해시코드>

 

git revert

해당하는 커밋의 변경 사항을 완전히 취소할 수 있다.

명령후 revert 된 커밋이 새로 추가된다.

 

특히, 이미 서버 마스터 브랜치에 커밋인 경우

rebase, reset보다는 revert를 사용하는것이 맞다.

 

--no-commit을 쓸때, revert 커밋에서는 다른 파일을

수정, 삭제 등을 진행하는일은 절대로 없도록 한다.

# 특정 커밋 완전히 제거 + 취소사항 커밋
git revert <해시코드>

# 특정 커밋 완전히 제거 + 취소사항 staging area로 이동
git revert --no-commit <해시코드>

 

git rebase -i (interactive)

이전에 커밋된 사항을 수정할 수 있다.

이미 서버에 업로드된 사항은 다루지 말자.

 

오래된 순으로

5,4,3,2,1 이라는 커밋이 있을때

4라는 커밋을 수정하고 싶다면

4가 가리키는 이전 커밋인 5를 기준으로 해야한다.

 

rebase하게되면 기준 이후의 커밋들이

전부 수정되는 개념이기 때문이다.

(실제로, rebase 범주내 커밋들은 rebase후 해시코드가 변경됨)

# interactive rebase
git rebase -i <해시코드>

interactive 옵션

pick(p): 이거 써

reward(r): ok, 메시지는 변경

edit(e): ok, 변경사항 변경

squash(s): 여러가지 커밋 묶기 + 새 커밋 메시지

fixup(f): 여러가지 커밋 묶기

drop(d): 해당하는 커밋을 제거

 

 

git rebase & reset으로 커밋 분할

하나의 커밋에는 하나의 작업단위만 수행하는게 일반적이다.

예를들면, 버그수정 / 기능추가 / 라이브러리 추가 등.

그래야만 문제가 발생했을때 빠르게 revert해서 대응한다거나

문제의 커밋으로 되돌아가서 수정하는것이 수월하기 때문이다.

 

근데 나를 포함한 많은 개발자들이 실수하는게 여러개의

작업을 하나의 커밋에 추가하는 것이다.

 

실수를해야 사람이다.

실수로 여러 작업을 한 커밋을 다시 분할하는 방법에 대해 알아본다.

# A라는 비대한 커밋을 쪼개보자
# 1. A직전 커밋 해시코드 확인
git status

# 2. rebase interactive
git rebase -i <A직전 커밋 해시코드>

# 3. interactive - edit (커밋 수정하기 옵션)
pick -> e

# 4. reset으로 커밋을 working directory로 가져오기
git reset <가져올 해시코드>

# 5. 가져온 커밋에서 작업단위로 쪼개서 commit 하기
git add <특정 작업파일들>
git commit -m "<작업메시지>"
git add <특정 작업파일들>
git commit -m "<작업메시지>"

#6. continue
git rebase --continue

 

그런가 하면 commit들을 하나의 commit으로 묶는것도 가능하다.

# 1. 작업 범주 해시코드 확인
git status

# 2. rebase interactive
git rebase -i <squash할 범위 +1의 해시코드>

# 3. squash
squash(커밋 묶기)를 진행할때는 가장 최근 commit은 pick으로 유지한채
그외의 묶을 것들의 옵션을 s(squash)로 변경한다.

# 4. 커밋 메시지 작성하기
필요없는 내용은 지우고 커밋 메시지 작성

 

 

단, 혼자 작업하는게 아니라면

서버에 업로드된 작업에대해 절대로 rebase를 사용하지 말자

728x90
반응형

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

순수함수 (pure function)  (0) 2022.11.06
객체지향 프로그래밍 핵심 개념  (0) 2022.10.27
git 기본기_백과사전 (1)  (0) 2022.10.24
git 협업하기 - 실무편  (0) 2022.10.23
Webpack 구성 이해하기  (0) 2022.10.04
728x90

git workflow 구성

1. working directory: 작업중인 로컬 환경, untracked/tracked으로 구분됨
2. staging area: git add를 통해 작업 내역이 올라가는 장소
3. git directory: git commit하면 작업 내역이 git directory에 위치됨
4. server(github/gitlab): git push하여 서버에 업로드, git pull하여 내려받음

commit 뜻

1. 스냅샷된 정보를 담음
2. ID로 고유한 hash코드가 부여됨
3. 누가 작성했는지, 언제 했는지가 기록됨

git add

# 1개 파일 add
git add <file>

# 2개 파일 add
git add <file1> <file2>

# 전체 수정 파일 add
git add .

# 전체 수정 파일 add
git add -A

# 디렉토리 내 전체 파일 add
git add *

working directory의 수정된 사항들을
staging area로 옮기는 행위

git rm --cached <file> 명령어로
staging area의 파일을 working directory로 다시 옮기는것도 가능

.gitignore

git에 포함하고 싶지 않은 파일들을 지정
지정된 파일들은 track되지 않아 git 명령의 대상이 아니게됨

git status

git의 상태를 보여줌

# 짧게보기
git status -s

# 풀버전 (기본)
git status
git status --long

 

git diff

이전 버전과 현재의 수정사항을 비교하여 보여줌
-는 이전 버전을 의미
+는 현재 버전, 수정된 사항을 의미

# 이전 버전과 현재버전을 비교
git diff

# staging area만 확인
git diff --staged

 

git commit

staging area의 변경 사항들은 git repository로 이동시킴

# 메시지와 함께 commit
git commit -m "some message"

# 전체 수정사항을 add 후, commit
git add .
git commit -m "some message"

# 전체 수정사항 add와 commit을 동시에
git commit -am "some message"

commit이야 말로 개발의 history가 됨
기능별, 의미있는 수정/기능 단위로 commit을 진행
커밋의 메시지는 현재형, 동사로 작성하는게 일반적 (init/add/fix)

git log

간단하게 commit 히스토리를 볼 수 있음
위에 있을수록 최신 commit

# 커밋 히스토리 보기
git log

# 간단하게 보기 (해시번호 + 커밋 메시지)
git log --oneline

# 수정사항 함께보기
git log -p

# 텍스트 GUI로 브랜치 함께 보기
git log --oneline --graph all

 

git alias

나만의 명령어를 만들 수 있음

git config --global alias.<이름> "<수행할 액션>"

 

HEAD

각 커밋은 이전 커밋을 가리킨다.
HEAD는 내가 현재 위치한 버전을 가리킨다.
즉, 현재 내가 보고있는 커밋을 가리킨다.

HEAD~1은 직전 버전
HEAD~2은 이전이전 버전
HEAD~3은 이전이전이전 버전
을 의미한다.

git tag

특정한 커밋을 북마크해두고 싶을때 쓰는것
제품을 릴리즈할떄 제품의 버전명을 tag해두는게 일반적

# 버전관리 - semantic versioning
major.minor.fix

# 예시
1.0.1

# 태그 추가
git tag <태그명>

# 특정 커밋 해시코드에 태그 추가
git tag <태그명> <해시코드>

# 특정 커밋 해시코드에 태그를 메시지와 함께 추가
git tag <태그명> <해시코드> -am "메시지"

# 태그 내용 조회
git show <해시코드>

# 태그 찾기, 와일드 카드 사용가능
git tag -l "v1.*" 

# 태그 삭제
git tag -d <태그명>

 

git branch

기능개발 / 버그픽스 등 업무를 진행함에 있어
개발자들 간에 병렬적으로 개발하기 위해
각자의 작업 공간을 나누어 개발을 진행한다.

이때 필요한게 나만의 작업공간 "branch"
특정 기능을 위한 작업공간 "branch"


특정 브랜치에서 git commit을 해나가다가
개발이 완료되면 기준 브랜치 혹은 마스터 브랜치로 병합을 하게되는데,(merge)

이때 그냥 병합하게 되면 브랜치가 지저분해져서
커밋 내역을 합쳐서 새로운 하나의 커밋을 만든 다음 병합하는 경우가 많다. (rebase & merge)

# 로컬의 브랜치 확인
git branch

# 로컬 & 서버 브랜치 확인
git branch --all

# 브랜치 이동 방법, 2가지
git switch <브랜치 이름>
git checkout <브랜치 이름>

# 브랜치 생성 & 이동 방법, 2가지
git switch -C <브랜치 이름>
git checkout -b <브랜치 이름>

# 해시코드를 이용해 브랜치 이동
git checkout <해시코드>

# 현재 브랜치에 merge된 브랜치 확인
git branch --merged

# 현재 브랜치에 merge얀된 브랜치 확인
git branch --no-merged

# 브랜치 삭제
git branch -d <브랜치 이름>

# 브랜치 삭제 & 원격저장소에 브랜치 삭제 반영
git branch -d <브랜치 이름>
git push origin --delete <브랜치 이름>

# 브랜치 이름 변경
git branch --move <이전 브랜치 이름> <새 브랜치 이름>

# 브랜치 이름 변경 & 원격 저장소에 변경된 브랜치 반영
git branch --move <이전 브랜치 이름> <새 브랜치 이름>
git push --set-upstream origin <새 브랜치명>

 

fast forward

흔히 말하는 fast forward란 무엇일까?

과거의 히스토리인 A커밋과

현재의 히스토리인 B커밋이 있을때,

B커밋이 A커밋의 모든 이력을 가지고 있다면

두 커밋이 "fast forward" 관계에 있다고 한다.

(이미지 출처 > 링크)

 

git merge

fast forward merge?
기준 브랜치에서 새로운 브랜치가 생성된 이후에
새 브랜치에서 작업하는 동안
기준 브랜치에 변동사항이 없다면,

기준 브랜치가 가리키고 있는 포인터를
새 브랜치로 변경해준 뒤
새 브랜치를 삭제해주는 방식으로 머지하는 것을 의미한다.

merge하면서도 깔끔하게 브랜치를 관리할수 있다는 장점이 있다.

다르게 생각하면 history에 merge되었다는
이력이 남지않는다는 단점이 존재한다고 볼수도 있다.

merge했을때 기준 브랜치에 변동사항이 없다면
자동으로 fast forward merge가 진행된다.

# feature/a를 master에 merge
git switch master
git merge feature/a
git branch -d feature/a

# fast forward merge 방지
git merge --no-ff <브랜치명>


three way merge?
내가 새 브랜치에서 작업하는동안에
기준 브랜치에 수정사항이 커밋됐다면,
fast forward merge가 불가능하게 된다.

이때는 기준 브랜치와 새 브랜치의 변동 사항을 모두 합쳐서
새로운 merge commit을 만든 후
기준 브랜치에 커밋해야한다.


merge할때 두 브랜치에서 동일한 파일을 수정했을때
"conflict"가 발생한다.
이러한 경우에는 개발자가 직접 conflict를 해결해야한다.

conflict이 발생하면 관련 내용에
자동으로
<<< HEAD
충돌 BRANCH >>>
텍스트가 생성된다.

# merge를 취소하려면
git merge --abort

# merge conflict를 해결 후, 해결 했음을 알리려면
git add <충돌 해결 파일명>
git merge --continue

# merge 후 orig 파일 생성되는것 방지
git config --global mergetool.keepBackup false
git clean -fd


커밋된 사항을 묶어 새로운 하나의 커밋을 만들어
머지하는 방법도 있다.
feature 브랜치의 커밋 히스토리를 합쳐서 깔끔하게
만들기위해 사용된다.

# squash merge
git switch master
git merge --squash <머지할 브랜치>
git commit -m "<메시지>"


git rebase

기준점을 재설정 함으로써
fast forward merge가 가능한 상황을 만들어
브랜치를 깔끔하게 관리하기 위한 수단.

마치 하나의 브랜치에서 작업한듯한 히스토리를
만들 수 있다.

** 로컬레포지토리에서는
자유롭게 rebase를 이용해도 된다.

다만, remote 레포지토리에 반영된 사항에
rebase를 하다가 merge conflict이 발생할 수 있다.

# feature/b를 master에 rebase
git switch feature/b
git rebase master

git switch master
git merge feature/b

# feature/view, feature/view/logic
# logic을 먼저 올려줄것을 요청하는 다른 개발자가 있어서
# feature/view/logic을 master에 merge 해보기
git switch master
git rebase --onto master feature/view feature/view/logic
git merge feature/view/logic


rebase의 또 다른 활용법이 있다.
하나의 feature를 구현함에 있어서도
분명 세부적인 기능들이 나눠진다.

따라서, 로컬에서 개발을 진행할 때
n번에 나눠서 commit을 진행하게 되는데
이때 그냥 push하면 모든 commit기록이
remote 서버로 넘어가기 때문에 브랜치가 지저분해진다.

내 로컬 작업을 간단히 정리해서 push하기위해
아래와 같은 사전작업을 할 수 있다.

# git log로 커밋 이력 확인하기
git log

# 최근 3개의 커밋에 대해 정리하기
git rebase -i @~3

# push하기
git push origin <브랜치명>

위 rebase 작업에서는 2번의 텍스트 에디터 화면을 보게된다.
1. commit 선별하기
p (pick, 사용하기)
| r (reward, 사용하되 커밋 메시지 수정하기)
| s (squash, 사용하되 이전의 커밋에 녹이기)
등의 옵션을 이용할 수 있다.
2. commit 메시지 정리하기
dd명령어를 이용해 원하는 라인을 제외하고 모두 지우거나
새 커밋 메시지를 작성하여
커밋 메시지를 깔끔하게 할 수 있다.
(해당 내용은 다음 포스팅에서 더 상세히 다룸)

cherry pick

다른 브랜치에 작업중인 특정 커밋만,
내 브랜치에 머지하고자할때 사용

# 특정 커밋 가져오기
git cherry-pick <해시코드>
728x90
반응형

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

객체지향 프로그래밍 핵심 개념  (0) 2022.10.27
git 기본기_백과사전(2)  (0) 2022.10.26
git 협업하기 - 실무편  (0) 2022.10.23
Webpack 구성 이해하기  (0) 2022.10.04
Rest API 정리  (0) 2022.09.29
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

5년 / 15년 / 25년 / 35년 / 45년

35년부터는 혼합금리 (일정 기간 고정금리 적용 후 변동금리)

  • 고정금리 기간 처음 5년
  • 연 3.729%~4.228% <5년 고정금리기간>
  • 연 2.826%~3.641% <고정금리기간 종료 후>

 

대상주택 - 수도권 (서울/경기/인천) 소재 KB시세가 있는 아파트

(단, 투기지역/투기과열지구 15억초과 아파트는 주택구입 목적 및 생활안정자금 임차반환 목적으로 대출취급 불가)

 

 

천만원 초과 대출 신청 시 인지세가 발생 (고객은 50%만 부담)

  • 대출금액 5천만원 초과 시 7만원
  • 대출금액 1억원 초과 시 15만원

 

중도상환해약금은 부과되지 않습니다 (22.09.18 기준)

- 변경될 경우 홈페이지 고지됨

 

 

상환방법 - 원리금균등상환

 

 

필요 문서

  • 잔금일이 표시된 매매계약서
  • 추가 요청될 수 있음

 

대출실행 절차

  • 대출금은 실행일 오전에 법무사로 전달됨
  • 잔금일에 배정된 현장 담당자가 부동산에 방문해 잔금을 처리하고 소유권 이전 등기 업무를 도와줌
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
반응형