신촌 연합 동아리 CEOS의 프론트엔드 스터디 과제로 react js를 활용한 메신저 프로젝트를 진행했다.
(10월에 마무리했었는데, 이제서야 관련 글을 쓴다,,,)
폴더구조는 다음과 같다.
src
|-components
|-chattingListPage
|-chattingPage
|-homePage
|-profilePage
|-settingPage
|-elements (공유 컴포넌트)
|-data
|-chatData.json
|-userData.json
|-image
|-emoji (icon 이라고 이름 지었어야 했는데..)
|-CameraIcon.tsx
|-...
|-state
|-styles
|-App
<Route path="/" element={<HomePage />}>
<Route path="" element={<ProfilePage />} />
<Route path="chattingList" element={<ChattingListPage />} />
<Route path="setting" element={<SettingPage />} />
</Route>
가장 주된 기능들만 정리했다.
const updateChatList = () => {
if (typeof content === 'string' && content.trim().length === 0) {
window.alert('문자를 입력해주세요.');
} else {
let time = `${new Date().getHours()} : ${new Date().getMinutes()}`;
setChatList(() => {
let tempList = chatList[targetUserId];
tempList = [
...tempList,
{
username: username,
messageTime: time,
content: content,
},
];
return { ...chatList, [targetUserId]: tempList };
});
}
setContent('');
setIsButtonActive(false);
};
마지막 return {…chatList, [targetUserId]: tempList} 에서 어떻게 하면 chatData의 key 부분을 변수로 할 수 있을지에 관해 많이 고민해
return{…chatList,${targetUserId}
: tempList} 등 많은 시도를 해보았는데, 객체에서는 저런 방식으로 변수를 key값에 할당한다는 사실을 알게 되었다.
<div>
<input
type="file"
id="img-upload"
style={{ display: 'none' }}
onChange={(e) => encodeFileToBase64(e.target.files)}
accept="image/x-png,image/gif,image/jpeg"
/>
<label htmlFor="img-upload">
<CameraIcon className="camera-icon" />
</label>
</div>
<input type=“file” />
으로 설정하면 다음과 같이 ‘파일 선택’란이 나온다. const encodeFileToBase64 = (files: any) => {
const file = files[0];
let fileReader = new FileReader();
const time = `${new Date().getHours()} : ${new Date().getMinutes()}`;
fileReader.onload = () => {
let img = new Image();
img.onload = () => {
setImageHeight((img.height / img.width) * 200);
};
if (typeof fileReader.result === 'string') {
img.src = fileReader.result;
}
setChatList(() => {
let tempList = chatList[targetUserId];
tempList = [
...tempList,
{
username: username,
messageTime: time,
content: fileReader.result,
},
];
return { ...chatList, [targetUserId]: tempList };
});
};
fileReader.readAsDataURL(file);
};
파일을 선택해서 ‘열기’ 버튼을 눌러 그것을 console.log(file.result) 해보면 엄청 긴 문자열이 나온다.
이건 코드의 맨 마지막 줄에 있는 fileReader.readAsDataURL(file);
때문인데, readAsDataURL 함수를 쓰면 바이너리 파일을 base64로 인코딩된 문자열을 반환한다.
이걸 일반 텍스트와 같이 content에 저장하고, 불러올 때는 <img src=`문자열` />
하면 사진이 나온다.
이렇게 react-messanger 프로젝트를 진행하며 typescript와 recoil을 이용한 객체 상태 관리를 경험해보고, base64로 사진을 인코딩하여 사진을 첨부하는 기능도 사용해보았다.