[리액트 로그인 처리]
const loginSlice = createSlice({
name: 'LoginSlice',
initialState : loadMemberCookie() || initState, // 쿠키가 없으면 초기값 사용
reducers: {
login: (state, action) =>{
console.log("login.....")
//소셜로그인 회원이 사용
const payload = action.payload
setCookie("member", JSON.stringify(payload), 1) // 1일
return payload
},
logout: (state, action) => {
console.log("logout.....")
removeCookie('member')
return {...initState}
}
},
extraReducers: (builder) => {
... 생략
}
})
export const {login,logout} = loginSlice.actions
export default loginSlice.reducer
- API 서버에서 받은 데이터는 기존의 로그인 데이터 구성과 동일하기 때문에 loginSlice의 login()을 사용해서 처리합니다.
const KakaoRedirectPage = () => {
const [searchParams] = useSearchParams()
const dispatch = useDispatch();
const authCode = searchParams.get("code")
useEffect(() => {
getAccessToken(authCode).then(accessToken => {
console.log(accessToken)
getMemberWithAccessToken(accessToken).then(memberInfo => {
console.log("-------------")
console.log(memberInfo)
dispatch(login(memberInfo))
})
})
}, [authCode])
return (
<div>
<div>Kakao Login Redirect</div>
<div>{authCode}</div>
</div>
)
}
- KakaoRedirectpage에서 API 서버로 전송받은 결과를 dispatch()를 이용해서 login()을 호출합니다.
- API 서버에서 전송된 결과로 member 쿠키가 생성되는 것을 확인할 수 있습니다.
[화면 이동 처리]
//소셜 회원이 아니라면
if(memberInfo && !memberInfo.social){
moveToPath("/")
} else {
moveToPath("/member/modify")
}
- KakaoRedirectPage.js의 dispatch 하위에 로그인 시 소셜 회원 여부에 대한 경로 이동 로직을 추가해줍니다.
import { useEffect, useState } from "react";
import { useSelector } from "react-redux/es/hooks/useSelector";
const initState = {
email: '',
pw:'',
nickname:''
}
const ModifyComponent = () => {
const [member, setMember] = useState(initState)
const loginInfo = useSelector(state => state.loginSlice)
useEffect(() => {
setMember({...loginInfo, pw:'ABCD'})
},[loginInfo])
const handleChange = (e) => {
member[e.target.name] = e.target.value
setMember({...member})
}
return (
<div className="mt-6">
<div className="flex justify-center">
<div className="relative mb-4 flex w-full flex-wrap items-stretch">
<div className="w-1/5 p-6 text-right font-bold">Email</div>
<input className="w-4/5 p-6 rounded-r border border-solid border-neutral-300 shadow-md"
name="email"
type={'type'}
value={member.email}
readOnly></input>
</div>
</div>
<div className="flex justify-center">
<div className="relative mb-4 flex w-full flex-wrap items-stretch">
<div className="w-1/5 p-6 text-right font-bold">Password</div>
<input className="w-4/5 p-6 rounded-r border border-solid border-neutral-300 shadow-md"
name="pw"
type={'password'}
value={member.pw}
onChange={handleChange}></input>
</div>
</div>
<div className="flex justify-center">
<div className="relative mb-4 flex w-full flex-wrap items-stretch">
<div className="w-1/5 p-6 text-right font-bold">Nickname</div>
<input className="w-4/5 p-6 rounded-r border border-solid border-neutral-300 shadow-md"
name="nickname"
type={'text'}
value={member.nickname}
onChange={handleChange}></input>
</div>
</div>
<div className="flex justify-center">
<div className="relative mb-4 flex w-full flex-wrap justify-end">
<button type="button" className="rounded p-4 m-2 text-xl w-32 text-white bg-blue-500">Modify</button>
</div>
</div>
</div>
)
}
export default ModifyComponent;
- modifyComponent를 생성합니다.
import ModifyComponent from "../../components/ModifyComponent";
import BasicLayout from "../../layouts/BasicLayout";
const ModifyPage = () => {
return (
<BasicLayout>
<div className="text-3xl">Member Modify Page</div>
<div className="bg-white w-full mt-4 p-2">
<ModifyComponent></ModifyComponent>
</div>
</BasicLayout>
)
}
export default ModifyPage;
- member 디렉토리 하위에 modifyPage를 생성하고 modifyComponent를 사용해줍니다.
{
path:"modify",
element: <Suspense fallback={Loading}><MemberModify/></Suspense>
}
- memberRouter에 modify 페이지를 추가하면 소셜로그인 시 modify 페이지가 정상적으로 뜨는 것을 확인할 수 있습니다.
[API 서버 회원정보 수정]
package org.zerock.mallapi.dto;
import lombok.Data;
@Data
public class MemberModifyDTO {
private String email;
private String pw;
private String nickname;
}
- dto 하위에 MemberModifyDTO를 생성해줍니다.
@Transactional
public interface MemberService {
MemberDTO getKakaoMember(String accessToken);
void modifyMember(MemberModifyDTO memberModifyDTO);
default MemberDTO entityToDTO(Member member){
MemberDTO dto = new MemberDTO(member.getEmail(), member.getPw(), member.getNickname(), member.isSocial(), member.getMemberRoleList().stream().map(memberRole -> memberRole.name()).collect(Collectors.toList()));
return dto;
}
}
@Override
public void modifyMember(MemberModifyDTO memberModifyDTO) {
Optional<Member> result = memberRepository.findById(memberModifyDTO.getEmail());
Member member = result.orElseThrow();
member.changePw(passwordEncoder.encode(memberModifyDTO.getPw()));
member.changeSocial(false);
member.changeNickname(memberModifyDTO.getNickname());
memberRepository.save(member);
}
- memberService, memberServiceImpl에 modify() 기능을 추가합니다.
- 변경이 가능한 패스워드와 닉네임을 수정하고 social 속성 값을 false로 변경합니다.
@PutMapping("/api/member/modify")
public Map<String, String> modify(@RequestBody MemberModifyDTO memberModifyDTO) {
log.info("member modify: " + memberModifyDTO);
memberService.modifyMember(memberModifyDTO);
return Map.of("result", "modified");
}
- socialController에 회원정보 수정 시 사용할 메서드를 추가합니다.
[리액트 API 연동]
export const modifyMember = async (member) => {
const res = await jwtAxios.put(`${host}/modify`, member)
return res.data
}
- memberApi.js에 /api/member/modify 경로를 호출하는 코드를 추가합니다.
- 회원정보 수정은 로그인이 될 수 있는 사용자만 가능하므로 jwtAxios를 이용합니다.
const handleClickModify = () => {
modifyMember(member)
}
- ModifyComponent.js에 수정을 위한 handleClickModify 함수를 추가합니다.
- modify 페이지에서 소셜로그인 사용자 계정을 저장하면 social에 false(bit(1) 형태로는 0)으로 잘 저장된 것을 확인할 수 있습니다.
[수정 후 다시 로그인]
const colseModal = () => {
setResult(null)
moveToLogin()
}
return (
<div className="mt-6">
{result? <ResultModal title={'회원정보'} content={'정보수정완료'} collbackFn={colseModal}></ResultModal>:<></>}
...생략
)
}
- 이전에 생성해놓은 modal 컴포넌트로 수정완료 처리를 해줍니다.
'React' 카테고리의 다른 글
[React] React Query 사용해보기(1) (0) | 2025.06.17 |
---|---|
[React] React Query 설정하기 (0) | 2025.06.17 |
[React] 소셜 로그인 (2) (0) | 2025.03.21 |
[React] 소셜 로그인 (1) (0) | 2025.03.19 |
[React] 쿠키(Cookie)를 이용한 애플리케이션 상태 저장 (0) | 2025.03.13 |