dailylife

nearworld·2022년 7월 12일
0

개발 일지

목록 보기
2/7
post-thumbnail

문제#1: CORS

발생 날짜: 2022/7/12
해결 날짜: 2022/7/12
키워드: CORS

배경 설명

프론트단에서 FetchAxios api를 사용하여 로그인을 위한 POST 요청을 보냈다.

문제

Access to XMLHttpRequest at 'http://146.56.39.196:8080/api/users/login' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

POST 요청을 보냈더니 브라우저 콘솔에 에러 메세지가 뜨면서 서버로부터 정상적인 응답이 오질 않았다.

원인

CORS 정책 위반

CORS(Cross Origin Resource Sharing) 정책은 서로 다른 도메인이 네트워크 통신을 할때 브라우저에서 서버가 허용하는 Origin만 서버와 통신할 수 있도록 제한을 둔 보안 정책이다.

fetch api를 사용하여 서버에 요청을 보내게 되면,

클라이언트는 위와 같이 예비 요청본 요청 2가지 요청을 서버에 보내게 되는데 예비 요청에는 HTTP methodsOPTIONS를 사용하여 요청을 보내게 된다. 이때 서버는 예비 요청을 받아 클라이언트의 도메인인 Origin이 서버에서 CORS 허용을 해주고 있는 도메인인지 아닌지 확인한다. 만약 해당되지 않는다면,

preflight request doesn't pass access control check

라는 에러를 발생시킨다. preflight request예비 요청을 의미하고 있다. 즉, 이러한 에러가 떴다면 그것은 서버에서 예비 요청을 받은 후 서버에서 허용하고 있는 도메인이 아니기 때문에 접근을 차단하겠다는 의미가 된다.

해결

서버 측에서 응답 헤더에다가 Access-Control-Allow-Origin: *를 설정해주면 모든 Origin이 요청을 보낼 수 있도록 허용하는 것인데 이렇게 되면 CSRF attack의 표적이 될 수 있다고 한다. 그러므로 허용할 Origin은 엄격히 설정해주는게 보안상 안전하다고 생각한다.

참고자료

https://evan-moon.github.io/2020/05/21/about-cors/


문제#2: Label태그

발생 날짜: 2022/7/17
해결 날짜: 2022/7/17
키워드: Label 태그

배경 설명

label태그의 파일 찾기 텍스트를 웹페이지에서 클릭하면 input type='file'이 작동하도록 만들려고 했다.

1차 문제

<label for='file'>파일 찾기</label>
<input type='file' />

브라우저 콘솔창에 for 대신 htmlFor를 사용하라는 경고가 뜨면서 코드가 의도했던대로 작동하지 않는다.

원인

React 에서는 label 요소의 for attribue 대신 htmlFor를 사용하도록 되어있다.

해결

<label htmlFor='file'>파일 찾기</label>
<input type='file' />

for 대신 htmlFor attribute 사용

2차 문제

<label htmlFor='file'>파일 찾기</label>
<input type='file' />
htmlFor로 프로퍼티를 변경해줬음에도 여전히 label을 눌렀을때 input file이 트리거되지 않는다.

원인

label 태그가 htmlFor의 값을 통하여 input을 작동시키려면 inputid값을 사용해야하는데 id가 없었다.

해결

<label htmlFor='file'>파일 찾기</label>
<input type='file' id='file' />

id='file'을 추가해줬더니 input file이 트리거 된다.


문제#3: input value

발생 날짜: 2022/7/17
해결 날짜: 2022/8/3
키워드: input value

문제


파일 찾기 버튼을 눌렀을 때 첨부파일 부분이 서버에 업로드할 파일명으로 바뀌어야하는데 바뀌지 않는다.

원인

<input id='post-upload-name' value='첨부파일' placeholder='첨부파일' readOnly />

value'첨부파일' 문자열로 고정된 상태.

document.querySelector('#post-upload-name').value = e.target.files[0]

value'첨부파일' 문자열로 고정된 상태이기 때문에 querySelector메서드를 사용하여 value를 바꾸는게 불가능한 것이었다.

해결

const [file, setFile] = useState('');

상태 file을 생성.

<input type='file' multiple onChange={(e) => {
    for (let i = 0; i < e.target.files.length; i++)
      setFile(file + " " + e.target.files[i].name);
  }} />

onChange 이벤트 리스너함수를 이용하여 setFilefile 상태 변경.

<input id='post-upload-name' value={file} placeholder='첨부파일' readOnly />

value='첨부파일'이 아닌 value={file}value가 상태 file이 되었으므로 file이 업데이트되면 input value도 업데이트 됨.


문제#4: image files

발생 날짜: 2022/7/17
해결 날짜: 2022/8/3
키워드: multipart/form-data, input file, FormData

1차 문제

서버로 이미지 파일들을 전송해야하는데 서버에서 이미지 파일들을 받지 못함.

원인

formData를 사용하지 않았기 때문.

해결

formData 사용

2차 문제

const [imageName, setImageName] = useState([]);

function handleSubmit(e) {
  e.preventDefault();
  const formData = new FormData();
  formData.append('imageName', imageName);
  // codes...

formData를 사용했지만 이미지 파일을 2개 이상 담은 배열을 보내면 서버측에서 에러 발생

원인

formData를 이용하여 이미지 파일들을 다수 보내는 방법이 잘못됨.

해결

imageName.forEach(file => {
  formData.append('imageName', file);
});

forEach문을 사용하여 상태 변수 imageName에 담긴 배열 요소들을 각각 따로 formData에 추가해줌.

console.log([...formData]);

위 코드를 사용하여 formData 내부에 입력된 데이터들을 확인 가능.
formData 내부를 살펴보는데 참고한 자료
https://stackoverflow.com/a/45673708/15060678

추가 학습

FormData는 폼 태그를 AJAX 통신을 사용하여 전송할때 사용할 수 있는 API.

// form이 폼 태그라고 가정하면 `FormData`에 전달하여 AJAX통신때 form태그를 보낼 수 있게 한다.
// 폼 태그는 submit 즉시 새로고침되어 ajax통신과 연동될 수 없으므로
// e.preventDefault(); 메서드를 사용하여 새로고침을 방지한 후 FormData에 
// form태그를 전달하는 방식으로 전송 가능하다.
const formData = new FormData(form);

FormData 오브젝트를 AJAX 통신에 사용할 경우

axios.post(url, formData, {
  headers: { 'Conetent-Type': 'multipart/form-data' }
}

Content-Typeheaders에 명시적으로 지정해줄 필요가 없다. 그 이유는 request body에 추가된 formData로 인해 자동으로 content-typemultipart/form-data로 변경되기 때문이다.
그러므로, formDatarequest body에 올릴 경우에는

axios.post(url, formData);

처럼 headerscontent-type을 지정하지 않아도 된다.


문제#5: 새 카드 레이아웃

발생 날짜: 2022/8/6
해결 날짜: 2022/8/7
키워드: nth-of-type


협업 스터디에 새로 오신 디자이너 팀원 분이 기존의 같은 크기의 카드들로만 있었던 카드 레이아웃을 위 이미지에 나오는 레이아웃 구현이 가능한지 여쭤보셨다.

문제

display: grid 를 써야함을 알았지만 카드들의 크기가 다 같은 것이 아닌 특정 순번의 카드는 크기가 다른 카드의 크기보다 4배 크기였다. 그리고 이 패턴이 반복되게 해야했다.

해결

.cards__item:nth-of-type(9n + 2),
.cards__item:nth-of-type(9n + 7) {
  grid-column: span 2;
  grid-row: span 2;
  border: 1px red solid;
  height: 100%;
}

nth-of-type 속성을 써서 특정 카드에만 CSS를 적용하는 것을 생각해냈다.
grid-columngrid-row 속성에 span 2 값을 줘서 그리드 레이아웃에서 행렬 각 2칸씩 차지하는 카드가 되도록 했다. 디자이너 팀원 분이 의도하신 대로 특정 순번에만 큰 이미지가 오도록 순번을 연산해줄 수 있는 수식이 필요했다. 다음 큰 카드가 언제 오는지 알아본 다음 항상 같은 패턴의 큰 카드들의 사이에는 8개의 카드가 있음을 알아냈다. nth-of-typen0 부터 시작하므로 1번째 패턴과 2번째 패턴 카드에 각각 +2+7 을 설정하여 첫번째 큰 카드들의 위치를 정해줬다. 그 뒤부터는 항상 9 번째마다 큰 카드들이 위치하게 된다.

profile
깃허브: https://github.com/nearworld

0개의 댓글