- 학습 목표 1 : 프론트엔드 JS 코드 - Fetch (로그인)
- 학습 목표 2 : 프론트엔드 JS 코드 - Fetch (회원 가입)
fetch('/api/users/login', {})
- 일반적인 웹사이트 URL과는 목적과 용도가 다름, 클라이언트가 서버에 요청을 보내기 위해 사용되는 API 엔드포인트 (데이터를 주고 받는 데 사용)
- api는 보통 서버에서 데이터를 제공하는 경로임을 표시해 API 요청과 일반 웹페이지를 구분하기 위해 붙이곤 함
- 의미가 분명하고 요청 목적을 명확히 드러내는 것이 좋으며, RESTful 규칙을 따르는 경우가 많음
fetch('/api/users/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email, password })
})
- method: 요청 동작 정의 (기본 값 GET, method 생략 가능)
- headers: 서버에 전달하는 추가 정보 (클-서 어떻게 소통할지 알려줌)
- Content-Type: 요청 데이터 형식 지정 (기본적으로 많이 사용)
- application/json: JSON 형식의 데이터를 전송할 때 사용
- Authorization: 인증 토큰 또는 인증 정보
- Accept: 클라이언트가 받을 수 있는 응답 데이터 형식
- User-Agent: 요청 보낸 클라이언트 정보
- body: 서버에 보낼 데이터 담음 (GET 요청에는 body 포함 안됨, 규칙상 허용 X)
- 일반적으로 JSON 형식 사용, 이를 JSON.stringfy로 JavaScript 객체를 JSON 문자열로 변환
.then(response => {
if (!response.ok) {
throw new Error(`서버 에러 발생: ${response.status}`);
}
return response.json();
})
.then(data => {
if (data.token) {
// 로그인 성공 시
localStorage.setItem('authToken', data.token);
window.location.href = '/posts';
} else {
// 로그인 실패 시
helperText.textContent = '*아이디 또는 비밀번호를 확인해주세요.';
helperText.style.display = 'block';
}
})
.catch(error => {
console.error('로그인 오류:', error);
})
- then(): Promise의 성공 결과를 처리 (체인 패턴: .then 여러번 연결해 단계별로 데이터 처리)
- response.ok: HTTP 상태 코드가 200~299 사이(정상적인 응답)인지 확인
- response.json(): 서버에서 반환된 데이터를 JSON 형식으로 파싱하여 다음 .then으로 넘김 (서버가 반환하는 JSON 응답은 텍스트로 인코딩된 상태)
- data.token: 서버로부터 받은 응답 데이터 중 token 값이 있는지 확인
- localStorage.setItem('authToken', data.token): 브라우저 localStorage에 authToken 키로 받은 토큰 값을 저장 (이후 API 호출 시 인증 정보로 사용 가능)
- catch: 앞 단계에서 발생한 모든 오류 처리
fetch(`/api/users/email/check?email=${encodeURIComponent(email)}`, {})
- ? 이후는 쿼리 문자열(Query String), 서버로 데이터 전달 시 사용
- encodeURIComponent(): URL에 포함될 데이터를 안전하게 인코딩 (이메일 주소 같은 값에는 특수문자가 포함될 수 있으므로 이를 URL에서 사용할 수 있도록 변환)
- GET 요청으로 읽기 작업을 했으므로, 이메일 정보를 쿼리 문자열로 제공함으로써 본문(body)을 포함하지 않고 서버는 클라이언트가 요청한 내용을 명확히 알 수 있음
fetch(`/api/users/email/check?email=${encodeURIComponent(email)}`, {
method: 'GET',
})
fetch('/api/users/signup', {
method: 'POST',
body: formData
})
- GET은 요청 본문을 포함하지 않아 Content-Type 헤더가 필요없음 (데이터 형식을 지정할 필요가 없음)
- POST는 formData를 전송할 때 Content-Type 헤더를 자동으로 추가함
<헤더를 명시적으로 추가해야하는 경우>
- JSON 데이터를 보낼 때
- 인증 정보를 포함해야할 때
- 성공 여부: success, status, result
- 메시지: message, error, description
- 데이터: data, items, result
- 기타 정보: token (인증 토큰), count (데이터 개수), exists (존재 여부)
// 회원가입 데이터를 서버로 전송
const formData = new FormData();
formData.append('profile_photo', profilePhotoInput.files[0]);
formData.append('email', emailInput.value.trim());
formData.append('password', passwordInput.value);
formData.append('nickname', nicknameInput.value.trim());
- HTML 폼 데이터를 키-값 쌍 형태로 쉽게 다룰 수 있는 JavaScript 객체 (주로 파일 업로드, 폼 데이터 전송에 사용)
<FormData 사용 이유>
- 파일 업로드: 일반적인 폼에서는 파일을 전송할 때 multipart/form-data 형식으로 데이터를 전송해야함, FormData 객체는 이 형식을 자동으로 처리
- 편리한 데이터 관리: 각 입력 필드의 데이터를 별도로 관리하지 않고, FormData에 추가하는 방식으로 데이터를 모아 서버로 전송 가능
- 도전 과제 1: TIL 작성
- 도전 과제 2: Fetch에 대해 이해하기
- 도전 과제 3: 프론트엔드 JS 코드 - Fetch (로그인)
- 도전 과제 4: 프론트엔드 JS 코드 - Fetch (회원 가입)
- 도전 과제 5: 프론트엔드 JS 코드 - Fetch (게시글 목록 조회)
- 도전 과제 6: HTTP REST API 수정
- Fetch는 패턴이 비슷해서 하나를 이해하고 나니 나머지 코드의 작성이 Event 보다도 수월한 것 같았다.