📁 public
public/
에 저장하고 있는 이미지의 경우, 프로젝트 개발 서버 및 빌드 프로세스에 의해 공개적으로 제공된다. 따라서, 이 파일들은 브라우저 내에서 직접 방문이 가능하고, 파일에 의해 요청될 수 있음.
localhost:5173/image1.jpg
이렇게 불러오면 이미지를 볼 수 있음 (public/image1.jpg
이라면)
📁 src/assets
public과 asset으로 나눠보았지만, 사실상 public
과 src/assets
둘의 차이점에 주목해야 한다.
(꼭 이름이 assets일 필요는 없다. 다만,src/
안에 위치해야 한다.)
아무튼, src/
에 저장된 파일은 공개적으로 제공되지 않는다. 즉, 웹 방문자가 접근할 수 없다.
그대신, src/
하위에 위치한 이미지들은 빌드 프로세스에 의해 인식되고 ➡️ public/
에 삽입되어 웹단에 보여지게 된다. (이때, 참조한 위치에서 자동으로 링크가 생성됨)
그래서 언제 어떤 폴더를 사용하라고요? 🧐
1️⃣ 빌드 프로세스에 의해 처리되지 않는 이미지 ➡️
public/
ex. index.html 파일이나 파비콘에 사용되는 이미지)
2️⃣ 컴포넌트 내에서 사용되는 이미지 ➡️src/(assets)
물론, 빌드 프로세스를 거치는 경우에도, public 폴더를 사용할 수 있으나, src/ 를 사용할 경우, 코드와 관련된 파일을 한곳으로 모아 유지 보수가 용이하다.
일반적으로는 public 폴더를 사용하고, 만일 컴포넌트에 사용될 경우 src/ 에 넣자
토글이나, edit -> save 으로 버튼의 이름이 전환되는 경우가 여기에 해당하는데
이때 새로운 상태는, 이전의 상태값에 의존하게 된다 (on이면 => off로, edit -> save으로 동전의 양면과 같이 양자택일의 상황이기 떄문에 이전의 반대값을 취하게 됨)
이렇게 코드 짜기 ❌
setIsEditing(!isEditing)
-> 이경우 상태 변경은 즉각적으로 수행되지 않음
리액트가 미래에 수행하고자 하는 상태 변경 스케줄을 조율할 뿐
(몇 ms 겠지만, 즉각적이지 않다는 말 )
따라서, 경우에 따라 예상치 못한 결과를 얻을 수 있음
예시1
function handleEdit() { //현재 isEditing가 false일 경우
setIsEditing(!isEditing); // => isEditing를 true로 변경할 것을 스케쥴링
setIsEditing(!isEditing); // => isEditing를 true로 변경할 것을 스케쥴링
}
대신 아래와 같이 함수를 전달해주기. 이때 함수는 이전의 상태값을 전달해준다.
이말은 즉슨 함수식을 전달함으로써, 리액트가 바로 이전의 상태값을 매개변수로 전달해줄 것을 보장받는다!
setIsEditing(wasEditing => !wadEditing)
예시2
function handleEdit() { //현재 isEditing가 false일 경우
setIsEditing(!isEditing); // => isEditing를 true로 변경할 것을 스케쥴링
setIsEditing(!isEditing); // => isEditing를 false로 변경할 것을 스케쥴링
}
🥸 왜 그렇게 하는데요?
배열이나 객체는 자바스크립트 내의 참조 값. (메모리 주소를 참조)
그러나 객체의 일부분을 직접 덮어써서 저장한다면, 이는 메모리 속의 기존값을 바로 변경하게 되는데
이 때문에, side effect가 생길 수 있음
(상태 업데이트가 여러개 예정되어 있을때 -> 원본 참조를 공유하는 모든 값이 영향을 받아, 알 수 없는 버그나 부작용이 생길 수 있음)
특정 상태가 객체나 배열에 영향을 받는다면 불변한 방식으로 변경되어야 함
❌ 배열에 직접적으로 접근하여 수정한 잘못된 경우 ❌
function handleSelectSquare(rowIndex, colIndex, playerSymbol) {
setGameBoard((prevGameBoard) => {
prevGameBoard[rowIndex][colIndex] = 'X';
return prevGameBoard;
});
}
따라서, 객체나 배열 (둘다 객체이긴 함)일때는, 이를 복제한 후, 원본을 참조하지 않는 복제된 값의 상태를 변화시켜주어야 한다. 상태를 변경 불가능한 방식으로 업데이트
⭕️ 불변한 방식으로 객체의 상태를 관리 ⭕️
function handleSelectSquare(rowIndex, colIndex, playerSymbol) {
setGameBoard((prevGameBoard) => {
const updatedBoard = [...prevGameBoard.map((innerArray) => [...innerArray])];
updatedBoard[rowIndex][colIndex] = 'X';
return updatedBoard;
});
}
컴포넌트1과 컴포넌트2에서 같은 상태값을 다루어야 할때, 우리는 그 둘의 가장 가까운 부모 컴포넌트에서 해당 상태를 관리한다