개발 리포트는 프로젝트가 끝난 후 전체적인 과정을 되돌아보고, 성과와 문제 해결 과정을 정리하여 팀과 공유하는 문서입니다. 프로젝트의 전반적인 진행 상황, 맡은 역할, 해결한 문제 등을 구체적으로 기술하여 향후 프로젝트에 대한 참고자료로 활용할 수 있습니다.
습관 조회
오늘의 습관 화면에 들어가면, 해당 스터디의 종료되지 않은 습관을 불러 옵니다. 습관 목록 수정을 통해 습관이 수정될 경우, 변경된 습관을 다시 조회하여 화면에 렌더링합니다.
habit의 GET을 활용하여 해당 스터디의 습관을 불러옵니다. 이때 isDone이 true라면 이미 종료된 습관이므로 isDone이 false인 습관만 불러옵니다.habitdone의 GET을 활용하여 처음 습관이 렌더링될 때 오늘 날짜의 특정 습관이 habitDone에 존재하면 초록색, 없으면 회색으로 습관이 보입니다.습관 체크
오늘의 습관 화면에서 각 습관을 클릭 시, 특정 습관을 오늘 진행했는지 체크할 수 있습니다. 기본적으로 회색이며, 한번 클릭 시 초록색으로 변하고 오늘 습관을 진행했다는 의미를 가지고, 다시 클릭하면 회색으로 변하고 습관 체크를 취소하는 토글 형식으로 구현하였습니다.
habitdone의 put 메서드를 활용하여 습관 클릭 시 오늘 날짜의 특정 습관이 habitDone에 존재하면 삭제하고, 존재하지 않으면 생성하였습니다.습관 스키마
model Habit {
id Int @id @default(autoincrement())
title String
createAt DateTime @default(now())
updatedAt DateTime @updatedAt
study Study @relation("StudyHabits", fields: [studyId], references: [id], onDelete: Cascade)
studyId Int //습관이 속한 스터디 참조
isDone Boolean @default(false) //습관 생성 시 기본값 false, 습관 종료 시 true로 변경
HabitDone HabitDone[]
}
model HabitDone { //습관을 실행한 경우 해당일 레코드 추가, 취소한 경우 삭제
id Int @id @default(autoincrement())
habitId Int //실행한 습관 참조
createdAt DateTime @default(now()) @db.Date //실행한 날짜.
habit Habit @relation(fields: [habitId], references: [id], onDelete: Cascade)
}
습관을 수정 시 변경된 습관을 바로 반영할 수 있도록 습관 목록 모달이 닫히면 오늘의 습관을 다시 불러오는 기능을 추가하였습니다.
useEffect(() => {
if(!isModalOpen){ //isModalOpen = false 인 경우(모달이 닫힌 경우) 오늘의 습관을 재조회함
handleLoad();
}
}, [isModalOpen]); //모달이 닫힐때 isModalOpen은 true->false로 변하므로 오늘의 습관을 다시 불러옴

습관 목록 수정을 통해 스트레칭 하기 습관 추가

추가된 습관이 오늘의 습관 목록에서 바로 반영되지 않음
원인: 습관 수정 시 변경된 데이터가 DB에 반영되기 전에 데이터를 가져오기 때문에 바뀐 데이터가 오늘의 습관에 반영되지 않았습니다.
모달이 닫히자마자 습관을 재조회 하는데, 이때 아직 DB는 모달에서 바뀐 습관이 적용되지 않음

변경 전
생각한 해결 방법: 모달이 닫히고 일정 시간 이후에 다시 데이터를 가져오는 방법을 생각하였으나 환경에 따라 DB에 반영되는 시간이 다를 것이기 때문에 제대로 적용이 되지 않을 것이라고 생각하였습니다.
결론: 모달에 Loading 상태를 추가하여 변경된 데이터가 DB에 반영되었는지 확인하고 로딩이 끝난 후 DB에서 데이터를 가져오도록 변경하였습니다.
const handleConfirmRevision = async () => {
try {
setIsModalLoading(true);
await putHabits(studyId, habits); //모달에서 변경된 습관이 DB에 반영
onClose();
} catch (error) {
} finally {
setIsModalLoading(false); //DB에 반영 이후 isModalLoading을 false로 바꿈
}
};
useEffect(() => {
if (!isModalLoading) {
handleLoad();
}
}, [isModalLoading]); //isModalLoading이 변경된 후 (로딩이 끝남) 다시 습관을 조회함

변경 후
습관을 종료할 경우 종료된 습관은 스터디 상세의 습관 기록표에 뜨지 않는 문제가 있었습니다.
Cascade로 인해 해당 습관에 대한 기록도 삭제되었습니다.Cascade를 set null로 바꾸는 방법을 생각해보았으나 여전히 habitId를 참조하고 있기 때문에 습관의 이름을 불러오지 못할 것으로 예상되었습니다.habit title을 habitDone 에 추가해주는 방법을 생각하였으나 습관 수정 시 이름을 모두 바꿔야 하기 때문에 불필요한 연산이 발생할 수 있을 것이라고 생각하였습니다.habit을 삭제하는 대신 habit에 isDone을 추가하여 습관 종료 시 isDone을 true로 변경하여 습관 참조에 문제가 없도록 변경하였습니다.주어진 요구사항이 복잡하여 모두 만족할 수 있는 DB 구조 구상에 어려움을 겪었고, 습관 관련 스키마를 계속 수정하였습니다.
첫번째 시도
ex) 월요일에 운동하기 습관을 체크한 경우, 운동하기 habit의 monday가 true로 변경
habit
| title | monday | tuesday | wednesday | … |
|---|---|---|---|---|
| 운동하기 | true | false | false | … |
문제점: 일주일 전의 습관 기록과 오늘의 습관 기록을 구분하기 어려움.
model Habit {
id Int @id @default(autoincrement())
title String
monday Boolean @default(false)
tuesday Boolean @default(false)
wednesday Boolean @default(false)
thursday Boolean @default(false)
friday Boolean @default(false)
saturday Boolean @default(false)
sunday Boolean @default(false)
createAt DateTime @default(now())
updatedAt DateTime @updatedAt
study Study @relation("StudyHabits", fields: [studyId], references: [id])
studyId Int
}
두번째 시도
ex) 월요일에 운동하기 습관을 체크한 경우, 운동하기 습관을 참조하는 월요일의 habitdone의 isDone이 true로 변경
habitdone
| habit | dayOfWeek | isDone | … |
|---|---|---|---|
| 운동하기 | Monday | true | … |
| habit | dayOfWeek | isDone | … |
|---|---|---|---|
| 운동하기 | Tuesday | false | … |
문제점: 모든 습관의 모든 요일에 대해 habitDone이 존재해야 하므로 주가 바뀔 때마다 초기화를 진행해줘야 하므로 불필요한 과정이 추가됨
HabitDone {
id Int @id @default(autoincrement())
habitId Int //참조하는 습관
dayOfWeek DAY_OF_WEEK //습관이 체크된 요일
isDone Boolean //습관 체크 여부
createdAt DateTime @default(now())
habit Habit @relation(fields: [habitId], references: [id], onDelete: Cascade)
}
enum DAY_OF_WEEK {
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
}
세번째 시도
체크한 습관만 habitDone에 추가됨
habitdone
| habit | createdAt | … |
|---|---|---|
| 운동하기 | 2025.04.07 | … |
model HabitDone {
id Int @id @default(autoincrement())
habitId Int //참조하는 습관
createdAt DateTime @default(now()) @db.Date //습관이 체크된 날짜
habit Habit @relation(fields: [habitId], references: [id], onDelete: Cascade)
}