이제 프로젝트의 핵심 내용을 적어보려 했는데 이 부분을 알기전에 데이터 구조와 api에 대해 간략히 설명을 하고 가야 할 것 같다.
내 첫 프로젝트기도 하고 이것저것 구글에서 검색하면서 공부하고 또 같이한 동기와 머리를 맞대면서 짠 구조이기 때문에 효율적이진 않을 수 있지만 그래도 한번 서술해보겠다.
먼저 해당 웹 프로젝트에는 크게 2가지 데이터를 받아서 저장하게 사용했고, 이 과정에서 redux를 사용한 상태관리를 적용시켜 보았다. 첫번째는 유저정보이고 두번째는 달력정보인데 이 두개를 큰 길로 잡은데는 이유가 있다.
우선 유저는 유저마다 개인 정보가 있다. 회원정보나 가진 프로젝트의 id, 그 프로젝트의 관리자인지 알바생인지 등등의 정보가 있을것이다. 또한 프로젝트또한 그 정보가 있다. 날짜나 시간 , 특이사항 기록, 시간표등의 기록이 있을것이다. 그런데 이 프로젝트는 한 유저에 속해있는 개념이 아니다. 여러 사용자가 한 프로젝트에 속해있을수 있으면서 한 사용자는 여러개의 프로젝트를 사용할 수 있어야 하는 개념이기 때문에 구조를 크게 두개로 나누어 사용했다.
먼저 User 객체 구조를 보면
{
userId: "1",
userName: "정민규",
phone: "01022348115",
projects: [
{
projectId: "1",
joinId: "",
projectName: "서브웨이 연수점",
calendarId: "1",
userList: [
{ userName: "정민규", userId: "supersfel@naver.com", done: false },
{
userName: "박세연",
userId: "parkseyeon99@naver.com",
done: true,
},
],
},
{
projectId: "2",
projectName: "맘스터치 개봉점",
calendarId: "2",
userList: [
{ userName: "짭민규", userId: "supersfel@naver.com", done: true },
{
userName: "짭세연",
userId: "parkseyeon99@naver.com",
done: false,
},
],
},
],
}
우리는 위와 같은 구조로 객체를 만들어서 사용했다. 유저 아이디, 이름, 핸드폰번호, 가지고 있는 프로젝트들과 그안의 간단한 정보들까지 넣어놔서 쉽게 사용할 수 있게 해놨다.
프론트에서 해당 부분이 수정되거나 바뀔때 우선 redux를 이용하여 자체적으로 수정을하면서 가지고 있다가 저장 버튼을 누르거나 특정 행동을 하였을때 저장을 요청하는 api를 보내서 데이터베이스를 수정하는 방식을 택했다.
캘린더 구조는 아래와 같다.
{
calendarId: "6",
projectId: "13",
projectName: "맘스터치 오류점",
userList: [
{
userId: "parkseyeon99@naver.com",
name: "박세연",
fixedtimes: [
{
dayId: "MONDAY",
worktime: "000000000000000000011111111000000000000000000000",
},
{
dayId: "TUESDAY",
worktime: "000000000000000000000000000000001111111100000000",
},
{
dayId: "WEDNESDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "THURSDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "FRIDAY",
worktime: "000000001111111100000000000000000000000000000000",
},
{
dayId: "SATURDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "SUNDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
],
},
{
userId: "supersfel@naver.com",
name: "정민규",
fixedtimes: [
{
dayId: "MONDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "TUESDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "WEDNESDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "THURSDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "FRIDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "SATURDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "SUNDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
],
},
{
userId: "user8@naver.com",
name: "고민수",
fixedtimes: [
{
dayId: "MONDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "TUESDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "WEDNESDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "THURSDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "FRIDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "SATURDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
{
dayId: "SUNDAY",
worktime: "000000000000000000000000000000000000000000000000",
},
],
},
],
dates: [
{
date: "220212",
dateId: "155",
dayIssues: [
{
name: "박세연",
text: "안녕하세요",
time: "14:20",
userId: "parkseyeon99@naver.com",
},
{
name: "박세연",
text: "Hello",
time: "14:20",
userId: "parkseyeon99@naver.com",
},
{
name: "고철수",
text: "얍얍",
time: "14:21",
userId: "user3@naver.com",
},
],
dayId: "SATURDAY",
users: [],
},
{
date: "220213",
dateId: "156",
dayIssues: [],
dayId: "SUNDAY",
users: [],
},
{
date: "220214",
dateId: "157",
dayIssues: [],
dayId: "MONDAY",
users: [],
},
{
date: "220215",
dateId: "158",
dayIssues: [],
dayId: "TUESDAY",
users: [],
},
{
date: "220216",
dateId: "159",
dayIssues: [],
dayId: "WEDNESDAY",
users: [],
},
{
date: "220217",
dateId: "160",
dayIssues: [],
dayId: "THURSDAY",
users: [],
},
{
date: "220218",
dateId: "161",
dayIssues: [],
dayId: "FRIDAY",
users: [],
},
{
date: "220219",
dateId: "162",
dayIssues: [],
dayId: "SATURDAY",
users: [],
},
{
date: "220220",
dateId: "163",
dayIssues: [],
dayId: "SUNDAY",
users: [],
},
{
date: "220221",
dateId: "164",
dayIssues: [],
dayId: "MONDAY",
users: [],
},
{
date: "220222",
dateId: "165",
dayIssues: [],
dayId: "TUESDAY",
users: [],
},
{
date: "220223",
dateId: "166",
dayIssues: [],
dayId: "WEDNESDAY",
users: [],
},
{
date: "220224",
dateId: "167",
dayIssues: [],
dayId: "THURSDAY",
users: [],
},
{
date: "220225",
dateId: "168",
dayIssues: [],
dayId: "FRIDAY",
users: [],
},
{
date: "220226",
dateId: "169",
dayIssues: [],
dayId: "SATURDAY",
users: [],
},
{
date: "220227",
dateId: "170",
dayIssues: [],
dayId: "SUNDAY",
users: [],
},
{
date: "220228",
dateId: "171",
dayIssues: [],
dayId: "MONDAY",
users: [],
},
{
date: "220301",
dateId: "172",
dayIssues: [],
dayId: "TUESDAY",
users: [],
},
{
date: "220302",
dateId: "173",
dayIssues: [],
dayId: "WEDNESDAY",
users: [],
},
{
date: "220303",
dateId: "174",
dayIssues: [],
dayId: "THURSDAY",
users: [],
},
{
date: "220304",
dateId: "175",
dayIssues: [],
dayId: "FRIDAY",
users: [],
},
{
date: "220305",
dateId: "176",
dayIssues: [],
dayId: "SATURDAY",
users: [],
},
{
date: "220306",
dateId: "177",
dayIssues: [],
dayId: "SUNDAY",
users: [],
},
{
date: "220307",
dateId: "178",
dayIssues: [],
dayId: "MONDAY",
users: [],
},
{
date: "220308",
dateId: "179",
dayIssues: [],
dayId: "TUESDAY",
users: [],
},
{
date: "220309",
dateId: "180",
dayIssues: [],
dayId: "WEDNESDAY",
users: [],
},
{
date: "220310",
dateId: "181",
dayIssues: [],
dayId: "THURSDAY",
users: [],
},
{
date: "220311",
dateId: "182",
dayIssues: [],
dayId: "FRIDAY",
users: [],
},
{
date: "220312",
dateId: "183",
dayIssues: [],
dayId: "SATURDAY",
users: [],
},
{
date: "220313",
dateId: "184",
dayIssues: [],
dayId: "SUNDAY",
users: [],
},
],
}
훨씬 구조가 크긴 하지만, 구조는 더 간단하다. 이유는 단순하다 날짜마다 특이사항, 스케쥴표가 들어가야 하기 때문이다. 특히 우리는 스케줄을 자동으로 기록해주는것이 메인 기능인데, 이로인해 고정 스케줄표를 작성해주는 부분이 들어가 있다. 중간에 0000000000011111111111000000000000 이런식으로 되어있는 부분이 있을 것이다.
이는 하루 24시간을 30분 단위로잘라서 일하는 시간을 1로 설정한 것이다. 처음에는 이또한 객체로 만들어서
"00:30" : true 이런식의 형태를 취해보려고도 했으나 뭔가 저장공간 낭비도 심한거 같고 30분씩 잘라서 써도 될 것 같아서 방법을 채택했다.
그럼이제 api부분을 한번 보자.
import axios from "axios";
import { useHistory } from "react-router";
import { getCalendarinfo } from "../module/Calendar";
import { get_userinfo, Usertype } from "../module/User";
// export const api = "http://localhost:8080";
export const api = "http://54.180.70.202";
type UserApiprops = {
userId: string;
userPassword: string;
};
type RegistApiprops = {
userId: string;
userPassword: string;
userName: string;
userPhone: string;
};
type EmailRequestApiprops = {
id: string;
};
export async function getUserinfoApi(token: any, dispatch: any) {
if (token !== null) {
try {
await axios({
method: "get",
url: `${api}/api/oldproject`,
headers: {
'Accept': "application/json", //prettier-ignore
'Content-Type': "application/json", //prettier-ignore
Authorization: token,
},
}).then((response) => {
dispatch(get_userinfo(response.data));
});
} catch (e) {
console.log("get getUserinfoApi error!!");
return false;
}
} else {
return false;
}
}
export async function UserApi(params: UserApiprops) {
try {
await axios({
method: "post",
url: `${api}/api/login`,
headers: {
'Accept': "application/json", //prettier-ignore
'Content-Type': "application/json", //prettier-ignore
},
data: params,
}).then((response) => {
const { authorization } = response.headers;
localStorage.setItem("token", authorization);
console.log(response.data);
});
} catch (e) {
console.log("get UserApi error!!");
}
}
export async function RegistUserApi(params: RegistApiprops) {
try {
await axios({
method: "post",
url: `${api}/api/userRegist`,
headers: {
'Accept': "application/json", //prettier-ignore
'Content-Type': "application/json", //prettier-ignore
},
data: params,
}).then((response) => {
const { memberRefreshToken } = response.data;
console.log(memberRefreshToken);
localStorage.setItem("token", memberRefreshToken);
console.log(response.data);
});
} catch (e) {}
}
export async function findpasswordapi(params: any) {
try {
await axios({
method: "post",
url: `${api}/api/find/password`,
headers: {
'Accept': "application/json", //prettier-ignore
'Content-Type': "application/json", //prettier-ignore
},
data: params,
}).then((response) => {
console.log(response.data);
});
} catch (e) {
console.log("error in findpasswordapi");
}
}
export async function resetpasswordapi(body: any, id: string) {
try {
await axios({
method: "post",
url: `${api}/api/reset/password`,
headers: {
'Accept': "application/json", //prettier-ignore
'Content-Type': "application/json", //prettier-ignore
},
data: body,
params: {
id,
},
}).then((response) => {
console.log(response.data);
});
} catch (e) {
console.log("error in resetpasswordapi");
}
}
export async function findidapi(body: any) {
let response: never[] = [];
try {
response = await axios({
method: "post",
url: `${api}/api/find/userid`,
headers: {
'Accept': "application/json", //prettier-ignore
'Content-Type': "application/json", //prettier-ignore
},
data: body,
}).then((response) => {
return response.data;
});
} catch (e) {
console.log("error in resetpasswordapi");
}
return response;
}
export async function Emailrequestapi(params: EmailRequestApiprops) {
const history = useHistory();
try {
await axios({
method: "post",
url: `${api}/api/emailAuth`,
headers: {
'Accept': "application/json", //prettier-ignore
'Content-Type': "application/json", //prettier-ignore
},
data: params,
}).then((response) => {
if (response.data) {
history.push("/");
} else {
alert("올바르지 않은 인증입니다.");
}
});
} catch (e) {
alert("올바르지 않은 인증입니다.");
history.push("/");
}
}
export async function PostApi(url: string, token: string, params: any) {
try {
await axios({
method: "post",
url,
headers: {
'Accept': "application/json", //prettier-ignore
'Content-Type': "application/json", //prettier-ignore
Authorization: token,
},
data: params,
}).then((response) => {
console.log(response.data);
localStorage.setItem("response", response.data);
return response.data;
});
} catch (e) {
console.log("error in PostApi");
}
}
export async function getCalendarApi(
token: string,
params: any,
dispatch: any
) {
try {
await axios({
method: "post",
url: `${api}/api/load`,
headers: {
'Accept': "application/json", //prettier-ignore
'Content-Type': "application/json", //prettier-ignore
Authorization: token,
},
data: params,
}).then((response) => {
// console.log("calendar받아오기");
// console.log(response.data);
dispatch(getCalendarinfo(response.data));
});
} catch (e) {
console.log("error in getCalendarApi");
}
}
export async function sendfixedscheduleapi(token: string, params: any) {
try {
await axios({
method: "post",
url: `${api}/api/auto`,
headers: {
'Accept': "application/json", //prettier-ignore
'Content-Type': "application/json", //prettier-ignore
Authorization: token,
},
data: params,
}).then((response) => {
console.log(response.data);
});
} catch (e) {
console.log("error in sendfixedscheduleapi");
}
}
export async function calendarupdateapi(token: string, params: any) {
try {
await axios({
method: "post",
url: `${api}/api/update`,
headers: {
'Accept': "application/json", //prettier-ignore
'Content-Type': "application/json", //prettier-ignore
Authorization: token,
},
data: params,
}).then((response) => {
console.log(response.data);
});
} catch (e) {
console.log("error in calendarupdateapi");
}
}
api는 많긴 하지만 형태가 결국 똑같다. 백엔드 서버에 요청하고 백엔드에선 그에대한 작업을 해준다. 예를 들어 비밀번호를 찾는 api를 보내면, 여러 정보를 보내고 그게 백엔드에서 유효한지 판단하고 맞다면 비밀번호를 바꿀 수 있는 이메일을 보내주거나 하는 행동을 취해준다.
'프로젝트 > 알바일기(알바스케쥴러)' 카테고리의 다른 글
04_일기만들기,참여,내 일기 (0) | 2022.03.22 |
---|---|
03_Index 첫페이지 (0) | 2022.03.22 |
02_프로젝트 구조 (0) | 2022.02.02 |
01_프로젝트 소개 (0) | 2022.01.28 |