

VSCode로 자바랑 스프링 부트 확장 프로그램을 설치하고 스프링 서버를 띄웠다.
여기서 데이터 보내는 걸로 React에서 처리할 예정이다.

사용자가 로그인을 하면 토큰이 응답으로 온다
다음 요청할때 헤더에 넣어서 토큰을 보내준다


베어러 토큰이란 무엇인가요?
이제 베어러 토큰으로 넘어가겠습니다. 베어러 토큰은 콘서트에서 VIP 패스와 같습니다. 이 패스를 가지고 있다면, 제한된 구역에 들어갈 때마다 신분증을 보여줄 필요가 없습니다. 토큰 자체가 접근 권한을 증명합니다.

베어러 토큰은 어떻게 작동하나요?
- 토큰 발급: 사용자가 성공적으로 로그인하면 서버가 토큰을 생성합니다. 일반적으로 JSON 웹 토큰(JWT)입니다.
- 토큰 저장: 이 토큰은 클라이언트 측에 저장되며, 로컬 저장소, 쿠키 또는 다른 곳에 저장될 수 있습니다.
- 인증 헤더: 이후 API 요청 시 클라이언트는 이 토큰을 인증 헤더에 포함합니다.
- 서버 검증: 서버는 토큰의 유효성을 확인하고, 토큰이 유효하고 만료되지 않았다면 접근을 허용합니다.
여기 베어러 토큰으로 사용된 인증 헤더의 예가 있습니다:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
이 경우, 토큰은 일반적으로 사용자 ID와 만료 시간을 포함한 인코딩된 정보를 담고 있는 긴 문자열입니다.
베어러 토큰 사용의 장점
- 강화된 보안: 토큰은 일반적으로 시간 제한이 있으며 암호화될 수 있어 기본 Auth보다 보안이 뛰어납니다.
- 무상태성: 서버가 세션 데이터를 저장할 필요가 없습니다. 대신 각 요청 시 토큰을 검증합니다.
- 유연성: 베어러 토큰은 다양한 범위나 권한을 포함하여 복잡한 API에 적합하게 사용자 정의할 수 있습니다.
베어러 토큰 사용의 단점
- 구현 복잡성: 베어러 토큰 인증을 설정하는 것은 기본 Auth에 비해 더 복잡합니다. 토큰 생성, 저장 및 검증이 필요합니다.
- 토큰 관리: 토큰은 안전하게 저장되어야 하며 만료 시 새로 고쳐야 하므로 클라이언트 측 관리가 복잡해질 수 있습니다.
- 부가적 부담: 소규모 API나 내부 도구의 경우, 토큰으로 제공되는 추가 보안이 과도할 수 있으며 불필요한 부하를 초래할 수 있습니다.
기본 Auth와 Bearer Token의 나란히 비교
이제 각 방법에 대해 자세히 논의했으니, 기본 Auth와 Bearer Token을 나란히 비교해 보겠습니다:
특징기본 Auth베어러 토큰
| 보안 | 낮음 (자격 증명이 매 요청에 전송됨) | 높음 (토큰은 암호화 가능하고 시간 제한이 있음) |
| 구현 용이성 | 매우 쉬움 | 중간에서 복잡함 |
| 세션 관리 | 없음 | 무상태 |
| 성능 | 매 요청에 자격 증명이 전송되어 느릴 수 있음 | 토큰 기반 접근으로 일반적으로 더 빠름 |
| 확장성 | 제한적 | 고도로 확장 가능 |
출처 : https://apidog.com/kr/blog/basic-auth-vs-bearer-token-2/
기본 인증과 베어러 토큰의 차이: API에 어떤 것을 사용해야 할까요?
Basic Auth와 Bearer Token의 차이를 알아보고, 어떤 방식이 API에 가장 적합한지 배워보세요. 이 상세 가이드는 보안, 구현 및 실제 사용 사례를 다루고 있습니다. Apidog로 API 관리를 최적화하세요.
apidog.com
Promise 비동기 작업 처리

직접 이용은 해본적 없고...
aysnc / await 만 사용함 나는...
await는 기다려.. 라는 뜻...
await를 가진 애는 무조건 aysnc 함수여야한다.

app 바깥에 apis폴더를 만들어서 axiosConfig.js를 만들어준다.
import axios from "axios";
//기본 경로 설정
axios.defaults.baseURL = "http://localhost";
//AccessToken을 받고나서 다음 요청시 전달할 수 있도록 요청 헤더에 추가
//로그인 성공했을 때 호출됨
function addAuthHeader(accessToken) {
//common 객체에 동적 속성으로 Authorization을 추가S
axios.defaults.headers.common["Authorization"] = "Bearer " + accessToken;
console.log(axios.defaults.headers.common);
}
//공통 요청 헤더에서 Authorization 헤더 삭제
//로그아웃시 호출됨
function removeAuthHeader() {
//common 객체의 Authorization 속성을 삭제
delete axios.defaults.headers.common["Authorization"];
console.log(axios.defaults.headers.common);
}
//외부에서 사용할 수 있도록 내보내기
const obj = {
addAuthHeader,
removeAuthHeader
};
export default obj;
로그인을 성공 하면 자동으로 Authorization 이름으로 헤더에 토큰을 넣어준다.
로그아웃할때 빼준다.

AuthContext.js에 보면 로그아웃 할때 헤더를 제거해줌
import axios from "axios";
//회원 가입
function join(member) {
/*
member = {
mid: "user1",
mname: "사용자1",
mpassword: "Ab123",
memail:"user1@naver.com"
}
*/
//POST: raw/json 방식으로 전달
return axios.post("/database/member/join", member);
}
//로그인
function login(member) {
/*
member = {
mid: "user",
mpassword: "12345"
}
*/
//POST: raw/json 방식으로 전달
return axios.post("/database/member/login", member);
}
const obj = {
join,
login
};
export default obj;
axios.post 로 요청 보냄
member정보 json방식으로 그대로 보냄
BaseUrl + /database/member.login이런식으로 요청이 들어간다
객체로 감싸서 export해주고 있다.
await 뒤에있는 부분이 promise이다.
보통 자바스크립트에서는 form에 submit버튼을 누르면 서버에 갔다가 html을 받아온다
그러나 React에서는 방식이 다르다. axios통해서 비동기 통신으로 갔다온다.
기본적인 form태그의 서버 갔다오는 기능을 막으려면
기본 기능을 막는 코드이다.
joinForm.js
"use client"
import { useState } from "react";
import memberApi from "@/apis/memberApi";
function JoinForm() {
const [member, setMember] = useState({
mid: "",
mname: "",
mpassword: "",
memail: ""
});
const handleChange = (event) => {
setMember({
...member, [event.target.name]: event.target.value
});
};
const handleJoin = async (event) => {
try {
//
event.preventDefault();
const response = await memberApi.join(member);
console.log(response);
} catch(error) {
console.log(error);
}
};
return (
<div className="card">
<div className="card-header">JoinForm</div>
<div className="card-body">
<form>
<div className="mb-2">
<label htmlFor="mid" className="form-label">Member ID</label>
<input type="text" className="form-control" name="mid" value={member.mid} onChange={handleChange}/>
</div>
<div className="mb-2">
<label htmlFor="mname" className="form-label">Member Name</label>
<input type="text" className="form-control" name="mname" value={member.mname} onChange={handleChange}/>
</div>
<div className="mb-2">
<label htmlFor="mpassword" className="form-label">Member Password</label>
<input type="password" className="form-control" name="mpassword" value={member.mpassword} onChange={handleChange}/>
</div>
<div className="mb-3">
<label htmlFor="memail" className="form-label">Member Email</label>
<input type="email" className="form-control" name="memail" value={member.memail} onChange={handleChange}/>
</div>
<div className="d-flex justify-content-center mb-2">
<button className="btn btn-primary btn-sm mr-2" onClick={handleJoin}>제출</button>
</div>
</form>
</div>
</div>
);
}
export default JoinForm;
joinForm에서 클릭으로 form에 있는 데이터를 memberApi로 보낸다.
import axios from "axios";
//회원 가입
function join(member) {
/*
member = {
mid: "user1",
mname: "사용자1",
mpassword: "Ab123",
memail:"user1@naver.com"
}
*/
//POST: raw/json 방식으로 전달
return axios.post("/database/member/join", member);
}
//로그인
function login(member) {
/*
member = {
mid: "user",
mpassword: "12345"
}
*/
//POST: raw/json 방식으로 전달
return axios.post("/database/member/login", member);
}
const obj = {
join,
login
};
export default obj;
멤버api에서 axios로 비동기로 요청을 보낸다
로그인이 성공하면

axiosConfig.addAuthHeader로 헤더에 accessToken을 넣어준다.
'React' 카테고리의 다른 글
| KOSA React 프론트기반 개발 과정(재직자) - 강추! 회사에서 보내주면 가세요 (2) | 2026.02.05 |
|---|---|
| [26.02.04] React 재직자 교육 5 - 배포방법, 도커 Docker 컨테이너 빌드 (0) | 2026.02.04 |
| [26.02.04] React 재직자 교육 3 - Login (1) | 2026.02.04 |
| [26.02.04] React 재직자 교육 1 - useMemo, React.memo (0) | 2026.02.04 |
| [26.02.03] React 재직자 교육 7 - Routing 라우팅 (0) | 2026.02.03 |
댓글