TIL
241120 TIL
GoJay
2024. 11. 21. 00:14
- Udemy <Git & Github 실무 활용 완벽 가이드>
- Git Hash를 사용할 때 앞에 7자리만 사용해도 된다.
git log --oneline
을 실행하면 축약된 로그를 볼 수 있고, 여기엔 7자리로 축약된 해시가 있다. - 일반적으로 Git에서
head
는branch
를 가리키고,branch
는 해당 브랜치의 가장 최신 커밋을 가리킨다. 즉,head
와branch
는 보통 일치된 상태이다. 하지만,git checkout <이전 커밋 해시>
를 통해 이전 커밋으로 이동한다면head
와commit
이 분리된 상태가 된다(detached 된 상태가 된다). 이런 상황에서 커밋이나 어떠한 동작을 하려고 하면 Git은 에러를 뱉어준다. - 해당 상황에서
head
를 다시 가장 최신 커밋이 있는branch
위치로 이동시키고 싶다면 그냥git switch <브랜치 이름>
을 해주면 된다. 상당히 간단하다. - 만약에 뒤로 돌아간 커밋 위치에서 새로운 브랜치를 만들고 싶다면
git branch <브랜치 이름>
으로 원래와 같이 브랜치를 새로 만들어주면 된다. 그러면 자연스럽게head
가 새롭게 생성된branch
와 일치되기 때문에head
와branch
가 분리된 상태가 해결된다. 해당 상황에서 다시 원래의 기존 브랜치 최신 커밋 위치로 가고 싶으면git switch <기존 브랜치 이름>
을 해주면 된다. 간단하다. - 마지막 commit을 한 상태에서 수정을 하다가 마음에 안 들어서 마지막 commit을 한 시점으로 되돌리고 싶으면
git checkout HEAD
를 해주면 된다. 만약에 모든 파일이 아니라 특정 파일을 바로 직전 커밋 상태로 되돌리고 싶다면git checkout HEAD <파일명>
을 해주면 된다. 되돌리고 싶은 파일이 전체는 아니지만 두 개 이상이라면 뒤에 파일명을 띄어쓰기로 구분해서 나열해 주자. - 동일한 동작을
git restore
로도 수행할 수 있다(switch
와 비슷하게 새로 나온 명령어이고, 목적에 맞는 기능만 제공해 혼란을 없앨 수 있으니, 가급적restore
를 사용하자). 마지막 커밋 이후 작업을 하다 스테이징을 안 한 상황에서 마지막 커밋 상태로 돌아가고 싶으면git restore .
를 해주면 된다. git restore
를 사용해서 원하는 시점의 커밋으로 복구하고 싶다면git restore --source <커밋 해시> <파일 이름(생략 가능)>
방식으로 하면 된다. 마지막의 '생략 가능' 부분을 생략하면 모든 파일이 복구되고, 파일 이름을 띄어쓰기로 구분해서 나열하면 전달한 파일들만 복구된다.git restore
로 복원하면head
와branch
가 분리되지 않는다.git restore --stage <파일 이름>
를 사용하면git add
로 스테이징 한 내용을 스테이징 취소할 수 있다. <파일 이름> 부분은 생략 가능하며, 생략하면 전체 파일의 스테이징이 취소된다.git reset <커밋 해시>
를 하면head
와branch
의 가장 최근 커밋 정보가 모두 다 커밋 해시 위치로 돌아간다. 롤백한 커밋 해시 위치 이후의 커밋을 날리는 거다.reset
을 소프트한 방식으로 하면 커밋만 취소되고 가장 마지막의 변경돼 있던 워킹 디렉토리의 파일은 이전 버전으로 변경되지 않는다. 이러한 방식은 변경 사항은 남기고 커밋을 날린 후 다른 브랜치로 쪼개서 관리하고 싶을 때 유용하다.gir reset --hard <커밋 해시>
를 하면 커밋 기록을 날리고 워킹 디렉토리의 작업 내역도 날려서 복원한 커밋 시점으로 되돌린다.git revert <커밋 해시>
는git reset
과 비슷하게 커밋 해시 위치로 프로젝트들 되돌린다. 하지만, 결정적인 차이가 있다.git revet
는 되돌리기를 한 커밋 기록을 남겨둔다. 즉, 원하는 시점의 코드로 되돌린다는 점에서git reset
과 유사하지만, 필요하다면 코드를 원하는 시점으로 되돌리기 전의 커밋 기록을 남겨놓기 때문에 문제가 생길 가능성이 적다.
- Git Hash를 사용할 때 앞에 7자리만 사용해도 된다.
- Udemy <한 입 크기로 잘라먹는 리액트>
- Vite로 빌드한 리액트 프로젝트의
public
과assets
둘 다 정적 파일을 저장하는 폴더이다. 하지만, 정적 파일 중 이미 파일은assets
에 저장해야 빌드 시 이미지 최적화가 된다. assets
에 저장된 이미지 폴더는 빌드 후 배포했을 때 이미지 데이터의 URI를 활용해 브라우저 메모리에 캐싱한다. 캐싱이 되면 한 번 받아온 이미지를 다시 request로 요청해야 할 때 브라우저 메모리에 캐싱된 이미지 URI를 가져와 사용한다.- 하지만, 항상
assets
폴더에 이미지를 넣는 게 맞진 않다. 정말 많은(또는 무거운) 이미지들이 사용되는 웹 애플리케이션인데 한 번 내려받은 이미지가 브라우저 메모리에 캐싱되면 브라우저의 메모리 사용량이 비대해질 것이다. 적은 양의 이미지라면 모르겠지만, 양이 많아지면 이건 브라우저의 원활한 동작에 문제를 발생시킬 수 있다. 이런 경우엔 정적 이미지 파일을public
폴더에 저장해서 이미지 최적화를 우회하는 게 필요할 수 있다. - CSS로
public
폴더에 저장한 폰트를 적용하려면 아래와 같이@font-face
를 사용해서 폰트 스타일을 지정한 다음,font-family
에 지정한 이름을 CSS 선택자 요소 내부에서 선언해 주면 된다.
@font-face { font-family: 'NanumPenScript'; src: url('/NanumPenScript-Regular.ttf'); } ... body { font-family: 'NanumPenScrtip'; }
- CSS에서
vh
는 'viewport height'를 의미한다. 사용자의 화면 세로 길이를 의미하며,100vh
라고 설정하면 높이가 뷰포트를 꽉 채우게 된다. - CSS에서
white-space: nowrap
으로 설정하면 뷰포트 사이즈가 줄어들어도 텍스트가 줄 바꿈 되지 않는다. useNavigate
로 생성한 Navigation 함수의 두 번째 인자로 객체를 전달해서 옵션을 설정할 수 있다.{ replace: true }
로 설정해 주면 라우팅을 하면서 뒤로 가기 적용에서 제외를 시켜준다(뒤로 가기를 해도 이전 페이지로 돌아가지 못하게 한다).- Navigation 함수에 인자로
-1
을 전달하면 바로 이전 페이지로 이동한다. 아마도 1을 입력하면 앞쪽의 페이지로 이동하게 될 것 같다(history
객체를 사용한 것 같다). - Navigation 함수는 페이지에 있는 컴포넌트들이 전부 마운트(렌더링) 된 다음에 사용할 수 있다. 순서에 문제가 있다면
useEffect
를 사용해서 마운트 완료 시(의존성 배열로[]
전달) 동작하도록 수정할 수 있다. - 감정 일기 애플리케이션을 강의를 보며 따라 만들면서 몇 가지 든 생각이 있다.
- Context API는 선언된 위치 하위에서 생성된 Context에 등록된
value
에 쉽게 접근해서 쓸 수 있기 때문에 Props Drilling을 방지하고, 상태를 편하게 관리할 수 있는 유용한 도구임에 틀림없다. 하지만, 언제나 모든 상태를 최상위 컴포넌트에서 정의할 순 없고, 컴포넌트의 계층과 상태를 사용하는 곳에 따라 여러 곳에서 여러 상태가 정의될 수 있다. 이런 경우를 Context API만 가지고 관리하려면 여러 컴포넌트 계층에서 별도로 Context를 새롭게 다 정의를 해줘야 하고, 하위 컴포넌들은 필요에 따라 여러 Context들을 구독해야 하는 상황이 생길 것 같다(실제로 해본 건 아니지만 그럴 것 같다). 그런 식으로 여러 Context가 생기고, 한 컴포넌트에서도 다양한 Context를 구독하는 상황이 생기면, 아무래도 어떤 상태가 어떤 Context에서 어떻게 내려오는 건지를 추적하기가 쉽지 않을 것으로 예상된다. 이런 배경에서 상태 관리를 더욱 쉽게 해주는 다양한 툴들이 등장한 게 아닌가 싶다. - 컴포넌트들은 자신이 가지고 있는 상태가 변하거나, 또는 상위 부모 컴포넌트가 리렌더링 돼야 하면 함께 리렌더링이 될 수밖에 없다. 즉, 컴포넌트들은 언제나 리렌더링이 될 가능성을 가지고 있다(
useMemo
나memo
를 사용하면 얘기가 다르긴 하다). 그리고, 컴포넌트가 리렌더링 된다는 것은 함수인 컴포넌트가 다시 실행된다는 것이고, 내부에 정의된 모든 코드들이 다시 실행된다는 것이다. 이것의 사이드 이펙트를 항상 잘 계산해야겠다. 예를 들어, 어떤 상태 변경과 컴포넌트 리렌더링 상황에서도 절대로 바뀌지 않는 함수가 존재할 수 있다(최초 컴포넌트 마운트 시 정의한 함수를 변경 없기 계속 쓰는 경우). 이런 함수는 컴포넌트 리렌더링에 의해 다시 정의될 때마다 예상치 못한 사이드 이펙트를 발생시킬 수 있다. 이런 경우엔useCallback
을 써주는 것도 방법이고, 아니면 컴포넌트의 외부에 함수를 정의해 주는 것도 방법이 될 수 있다. 아무래도, 컴포넌트 안에 너무 많은 함수가 정의되어 있으면 유지보수나 관리가 어려워질 수 있기 때문에, 적절하게 함수를 컴포넌트 밖으로 빼기 위해 고민을 많이 해야겠다. - 이외에도 상태를 어디에서 정의할지,
props
로 내려줄 때 어떤 데이터 형태로 내려줄지, 로직을 함수로 분리할 것과 분리하지 않은 것을 어떻게 정할지, 어떤 걸util
로 빼서 관리할지 등, 개발하면서 고민해야 할 부분이 정말 많은 것 같다. 결국, 안정적이고 확장성 있는 웹 애플리케이션을 만들기 위해 여러 경험과 고민이 수반되어야 한다. 갈 길이 멀다.
- Context API는 선언된 위치 하위에서 생성된 Context에 등록된
- Vite로 빌드한 리액트 프로젝트의