[React] Westagram Live Review
Westagram Live Review
지금까지 진행한 Westagram작업을 라이브 리뷰를 받으며 수정할 사항을 체크하고 다른 동기님들의 코드를 함께 보며 나에게 필요한 부분을 정리하고자 기록한다.
JSX 리팩토링 목록
✅ localhost:3000 삭제
Mock Data를 만드는 과정에서 fetch에 'http://localhost:3000/data/commentData.json'
로 로컬호스트 주소를 입력했었다.
이 localhost:3000
는 바뀔 수 있는 값이다.
실제로3001
, 3002
으로 바뀔 때마다 다시 fetch
함수에 수정했었고 이 과정이 번거롭게 느껴졌다.
그런데 이것을 '/data/commentData.json'
로 적어도 자동으로 local host가 들어간다는 사실을 배웠다!!
✅ method: 'GET' 삭제
GET
이 fetch
함수의 method
의 기본 값이지만, 나는 GET
이라고 끝까지 적는 게 아직 초보 단계에서 익숙해지기 쉽고 또 메소드를 파악하기 빠른 것 같아 표시했었다.
하지만 삭제하는 것이 좋다고 한다. 😢
✅ 정말 기본이자 중요한 네이밍!
로직을 보고 네이밍을 해석하는 것이 아니라 네이밍만 보고 로직을 이해할 수 있도록 해야한다.
-
mock data에서
id
,value
라고 적었지만 실제로는value
에는 여러 값이 들어있기 때문에values
라고 수정해야한다. -
로그인 유효성 검사를 위해 정규 표현식을 사용했는데 이때 변수명을
regExp
라고 지었다.
무엇을 위한 정규표현식인지 변수명을 지어줘야한다.
emailValidationPattern
로 변경하면 좋을 것 같다. -
한 번 더 생각하는 과정이 필요한
btns
와 같은 줄여쓰는 네이밍 작성을 지양해야 한다.
buttons
로 변경하는 것이 좋다.
✅ config.js 생성
현재 westagram 프로젝트에서는 fetch
를 쓴 곳이 적지만 실제 프로젝트에서는 많은 fetch
함수를 사용해야하는데 만약 백엔드 주소가 바뀌면 어떻게 될까?
하나 하나 변경해야하는 대참사가 일어난다.
실제로 처음에 페어 백엔드분의 API만 사용하면 되지만 나중에 merge하고 배포하면 API를 바꿔야 한다.
때문에 초기 세팅때부터 이런 API를 관리하는 파일을 만들어야 한다.
config.js
를 생성해 상수로 API 주소 값을 관리하는 것이 좋다.
//config.js
const BASE_URL = 'http://10.58.3.11:8000';
export const API = {
SIGN_IN: `${BASE_URL}/users/signin`,
SIGN_UP: `${BASE_URL}/users/signup`,
};
// login.js
import { API } from '../../../config';
fetch(API.SIGN_IN, {
// ...
});
✅ ID 삭제
id
는 'root'
와 같은 명확한 이유로 꼭 필요한 상황에만 사용하고 스타일링이 목적이라면 className
을 사용해야한다.
section id="main"
은 className="main"
으로 변경해야하며,
순수 JS에서 DOM을 조자하기 위해 사용했던 button id="loginSubmitBtn"
이런 방식도 전부 className
으로 변경해야한다.
✅ useRef를 사용하는 2가지 용도
- DOM 요소를 잡기 위해 사용
- 컨테이너처럼 사용
함수 실행이 끝난다는 것은 함수 안에 변수들도 가비지컬렉션의 대상이 된다는 것을 의미한다.
하지만useRef
를 사용하면 함수가 종료되도 살아있고, 언마운트 시에도 남을 수 있다.
이것이 바로 클로저 기술이다!!
✅ setState는 비동기다.
state
를 업데이트하는 것은 바로 그 즉시 일어나지 않는다.
// 동기님 코드
const handleUserInput = e => {
const {name, value} = e.target;
setUserInfo({
...userInfo,
[name]: value,
});
// 이 시점에는 state가 아직 업데이트 되지 않았다.
inputValid(); // 업데이트가 되지 않은 state값으로 함수를 실행한다.
}
setState
는 여러 개, 즉 여러 번 일어날 수 있다.
그때마다 리엑트가 동기적으로 렌더링시키면 정말 많은 렌더링이 발생한다.
그래서 리엑트는 Batch 업데이트로 모았다가 한 번에 처리해 한 번만 UI를 그리도록 한다.
때문에 setState
는 한 템포 느리다.
이를 맞추기 위해 useEffect
를 쓸 수 있다.
setUserInfo
로useInfo
데이터를 업데이트시킨다.useInfo
데이터가 업데이트됨을 감지하고inputValid()
를 실행한다.
이때 업데이트된 상태로 실행할 수 있다.
// 동기님 코드
const handleUserInput = e => {
const {name, value} = e.target;
setUserInfo({
...userInfo,
[name]: value,
});
};
useEffect(()=>{
inputValid();
}, [userInfo]);
✅ state값에 어떤 특정한 값을 넣는 것을 지양하자
로그인 유효성 검사가 통과되지 못할 시 버튼을 비활성화 시키기 위해 아래처럼 useState
초기값으로 disabled
라는 string
값을 넣었었다.
// login.js
const [abel, setAbel] = useState('disabled');
const onInput = () => {
const isInputValid = handleValidInput();
isInputValid ? setAbel(null) : setAbel('disabled');
};
// 버튼 JSX
<button type="submit" id="loginSubmitBtn" disabled={abel}>
로그인
</button>
만약 이처럼 어떤 문자열을 사용하고 싶다면 이것을 상수로 만들고 사용해야한다.
왜냐하면 string
값은 오타 나기 쉽기 때문이다.
상수로 작성을 해두면 자동완성 기능으로 에러 가능성을 줄여준다.
const DISABLED = 'disabled';
function Login(){
//...로그인 컴포넌트 로직
const [abel, setAbel] = useState(DISABLED);
}
하지만 아래처럼 불리언 값으로 설정하면 더 범용성이 생기기 때문에 좋다.
string
과 null
이면 다른 구성을 생각하기 어려워진다.
function Login(){
//...로그인 컴포넌트 로직
const [isDisable, setIsDisable] = useState(true);
const onInput = () => {
const isInputValid = handleValidInput();
isInputValid ? setIsDisable(false) : setIsDisable(true);
};
// 버튼 JSX
<button type="submit" id="loginSubmitBtn" disabled={isDisable}>
로그인
</button>
}
토글 같은 상황에서는 불리언 값을 할당해서 string
을 선택하는 방향으로 바꾸자!
✅ useCallback을 남발하지 말자
useCallback
을 사용한다는 것은 결국엔 변했는지 안변했는지 검사 과정이 추가되는 것이기 때문에 어차피 변해도 되는 함수라면 그대로 나두는 것이 좋다.
✅ 에러 메세지만 따로 관리하자
로그인 페이지에서 fetch
함수 내에 에러 메세지를 아래처럼 삼항연산자로 하나의 경우만 처리했었다.
// Login.jsx
res.MESSAGE === 'UNAUTHORIZED'
? alert('비밀번호 틀렸습니다.')
: navigate('/main-soyoung');
};
이 에러 메세지는 '이메일이 올바르지 않을 때', '비밀번호가 올바르지 않을 때' 등 경우의 수도 다양하고 결국 고정값으로 상수 데이터이므로 errorMessages
파일을 따로 만들어 백엔드님이 설정하신 메세지 값을 받아 객체 형태로 보관하면 유지보수도 좋고 훨씬 더 간결해진다.
// errorMessages.js
export const ERRORS = {
UNAUTHORIZED: '존재하지 않는 아이디입니다.',
INVAILDPASSWORD: '비밀번호 틀렸습니다.',
ALRREADY_EXIST: '이미 존재하는 아이디입니다.',
};
// Login.jsx
.then(res => {
console.log(res);
ERRORS[res.MESSAGE]
? alert(ERRORS[res.MESSAGE])
: navigate('/main-soyoung');
});
프로젝트 세팅 때 백엔드동기님과 꼭 메세지를 같이 맞추고 시작하자!
✅ fetch 함수 실행 전 return
프론트에서 만든 로그인 버튼 비활성화을 위한 유효성 검사 로직을 fetch에 활용할 수 있다!
fetch로 서버에 통신하기 전 프론트에서 미리 올바르지 않은 값을 인식하고 return 시키면 된다!!
const goToMain = e => {
e.preventDefault();
const isInputValid = handleValidInput();
if (isInputValid) return; // 유효하지 않을 경우 return 탈출!
fetch(API.SIGN_IN, {
// doing...
})
};
scss 리팩토링 목록
✅ 태그 셀렉터는 왠만해서는 지양하자
태그 셀럭터는 정말 중복되는 가능성이 높으면 사용하고 왠만하면 지양하자.
✅ & 연산자 활용하기
sass는 중첩 안에서 상위(부모) 선택자를 참조하여 치환할 수 있는 &
키워드를 제공한다!
sass... 너.. 만난지 얼마되지 않았지만 정말 굉장하구나!
.lineOr {
// 코드
.txt {
// 코드
}
}
.lineOr::after,
.lineOr::before {
// 코드
}
위처럼 따로 분리할 필요없이 중첩으로 넣어 &
키워드로 처리할 수 있다.
.lineOr {
// 코드
&::after,
&::before {
// 코드
}
.txt {
// 코드
}
}
✅ 스타일링이 필요가 없다면 className을 제거 + scss 파일 제거
class
는 해당 요소를 다른 요소와 구분짓고, css
에서 선택자로 사용하여 스타일링을 부여하기 위해 존재한다.
때문에 스타일링이 필요 없다면 굳이 className
을 사용할 필요가 없다. 또한 scss
도 필요가 없다.
✅ 네스팅 미디어쿼리
네스팅에서는 미디어쿼리로 따로 작성할 필요가 없이 해당 태그 바로 밑에 넣으면 된다.
절대 경로
@import '../../../../../styles/variables.scss';
✅ alt에는 이미지라고 적지 않아도 된다.
img
태그에 alt
작성 시 '하트 버튼 이미지', '즐겨찾기 버튼 이미지' 이런 식으로 '이미지'라는 단어를 함께 붙였는데 이미 이미지 태그라는 것을 알기 때문에 필요 없다고 한다.
✅ event를 받아 함수를 호출할 때는 단축가능
// before
onClick = { e => handleClick(e)}
// after
onClick = {handleClick}
기타
- 업데이트는 기존 값을 지키고 새 값을 생성해야한다.
원본은 불변성을 유지해야하기 때문에 항상 copy를 뜨고 변화를 구현하는 것을 잊지말자! - 최대한
state
를 줄여 렌더링을 줄이는 것이 중요하다. - 하나의 컴포넌트에는 하나의 관심사만 다뤄야한다. 관심사 분리를 할 때는 반드시 scss도 함께 분리해줘야한다.
div
는 이미block
속성인데width: 100%
를 줄 필요가 없다.
하지만 부모 요소가display: flex;
면 자식은 자동으로inline-block
속성으로 변경되기 때문에 이때는 필요하다면width:100%
를 사용해도 된다.- 관심사끼리 코드를 묶어주거나 hook끼리 묶어두는 등 다양한 방식으로 코드를 묶어줄 수 있지만 중요한 것은 방식을 한 가지로 통일해야한다.
Author And Source
이 문제에 관하여([React] Westagram Live Review), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sozero/React-Westagram-Live-Review저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)