[React] 이미지 스타일링 및 프로필 변경 기능 구현하기
Styled-Components를 사용하여 이미지 기본 설정과 스타일링을 구현해보자.
1. 기본 이미지 설정하기
사용자가 프로필 이미지가 없는 경우, 기본 이미지를 설정하여 보여줄 수 있다.
- 프로젝트의 assets/images 폴더에 기본 이미지를 추가하기
- 해당 이미지를 컴포넌트에서 사용할 수 있도록 import하기.
import defaultUser from "assets/images/defaultUser.png";
2. Styled-Components로 이미지 스타일링하기
StLetterCardAvatorFigure라는 styled-component를 정의하여 이미지 컨테이너를 스타일링한다.
- figure 태그를 Styled-Components로 감싸 이미지의 크기와 스타일을 지정하기
overflow: hidden
을 사용하여 이미지가 컨테이너를 넘치지 않게 하고,border-radius
로 둥글게 만들기
import styled from "styled-components";
import defaultUser from "assets/images/defaultUser.png";
const LetterCard = () => (
<StLetterCardAvatorFigure>
<img src={user.avatar || defaultUser} alt="아바타 이미지" />
</StLetterCardAvatorFigure>
);
const StLetterCardAvatorFigure = styled.figure`
width: 50px;
height: 50px;
border-radius: 50%;
overflow: hidden;
& img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 50%;
}
`;
3. 프로필 변경 기능 구현하기
이제 사용자가 프로필 사진과 닉네임을 변경할 수 있는 기능을 구현해보자
이미지와 텍스트 데이터를 FormData로 서버에 전송하는 방식이며, 서버에 프로필 변경 요청을 보낸 후 응답을 받아 상태를 업데이트한다.
- 프로필 수정 시 서버로 nickname과 avatar 이미지를 보내기 위해 FormData 객체를 사용한다.
- 이미지 파일과 텍스트 데이터를 서버로 전송할 수 있도록
multipart/form-data
형식으로 요청한다.
//src/api/auth.js
export const editProfile = async (data) => {
const formData = new FormData();
formData.append("avatar", data.avatar);
formData.append("nickname", data.nickname);
return await authAxios.patch("/profile", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
};
// src/pages/protected/Mypage.jsx
import { editProfile } from "api/auth";
import { useAuth } from "context/AuthContext";
import { useState, useEffect } from "react";
import styled from "styled-components";
import defaultUser from "assets/images/defaultUser.png";
const MyPage = () => {
const { user, setUser } = useAuth();
const [isEditMode, setIsEditMode] = useState(false);
const [editNickname, setEditNickname] = useState(user.nickname || ""); // 편집할 닉네임 상태
const [imgFile, setImgFile] = useState(null); // 선택한 이미지 파일
const [previewUrl, setPreviewUrl] = useState(""); // 이미지 미리보기 URL
// 편집 모드가 아닐 때 원래 닉네임과 이미지를 설정
useEffect(() => {
setEditNickname(user.nickname || "");
setPreviewUrl(user.avatar ? user.avatar : defaultUser);
}, [user]);
// 파일 선택 시 호출되는 함수
const handleFileChange = (e) => {
const file = e.target.files[0];
// if (imgFile.size > 1024 * 1024) {
// return alert('최대 1MB까지 업로드 가능합니다.');
// }
setImgFile(file); // 선택한 파일 저장
// 미리보기 URL 생성(File -> Url 형식으로 변환)
const imgUrl = URL.createObjectURL(file);
setPreviewUrl(imgUrl);
};
// 프로필 변경 처리 함수
const handleProfileChange = async () => {
try {
const response = await editProfile({
nickname: editNickname,
avatar: imgFile,
});
setUser(response.data);
alert("변경 완료!");
setIsEditMode(false);
} catch (error) {
console.error("프로필 변경 중 오류 발생:", error);
}
};
return (
<div>
<h2>프로필 관리</h2>
{isEditMode ? (
<>
<StMyPageFigure>
<img src={previewUrl} alt="아바타 이미지" />
</StMyPageFigure>
<input type="file" onChange={handleFileChange} />
<input
value={editNickname}
onChange={(e) => setEditNickname(e.target.value)}
placeholder="변경할 닉네임"
/>
<button onClick={handleProfileChange}>변경완료</button>
<button onClick={() => setIsEditMode(false)}>취소</button>
</>
) : (
<>
<StMyPageFigure>
<img src={user.avatar || defaultUser} alt="아바타 이미지" />
</StMyPageFigure>
<div>{user.nickname}</div>
<button onClick={() => setIsEditMode(true)}>
닉네임 및 이미지 변경
</button>
</>
)}
</div>
);
};
export default MyPage;
const StMyPageFigure = styled.figure`
width: 50px;
height: 50px;
border-radius: 50%;
overflow: hidden;
& img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 50%;
}
`;
댓글남기기