졸업작품 5일차

임선구·2025년 4월 26일

졸업작품

목록 보기
5/29
post-thumbnail


오늘의 잔디



오늘은 카페를 가서 무려 5시간 넘게 개발을 했다.

gpt 선생님과 함께


spring boot도 써보고 서버도 만들어보고


postman으로 테스트도 해보고

프론트랑 서버랑 연동도 했다.


delete 버튼도 만들었다.
UI도 개선해서 삭제를 하면 일정이 오른쪽으로 흐려지면서 사라진다.


이랬던 일정 추가 팝업창이

이렇게 변했다!!!!!!

마찬가지로 구린 팝업창에서 위에 사진처럼 UI도 바꿨다.

이제 x버튼을 누르면 어떤 일정을 삭제하는지 다시 한번 묻는 팝업창도 이쁘게 만들었다.
취소하면 삭제가 되지 않는다.
확인을 하면 일정이 오른쪽으로 사라지면서 없어진다.

그리고 ui도 더 다듬고 기능도 추가했다.


📅 2025년 4월 26일 개발일지

1. 일정 삭제 모달 개선

  • 기존 삭제 확인창(alert 기반)을 직접 디자인한 모달 창으로 변경

  • 삭제 모달에 삭제할 일정 이름 표시 ("study 일정을 삭제하시겠습니까?")

  • "확인" / "취소" 버튼 적용

  • 삭제 시 부드러운 애니메이션(fade-out) 추가

  • 성공적으로 서버 삭제 요청(DELETE) 및 프론트에서 이벤트 제거 처리

2. 일정 추가 모달 개선

  • 기존 prompt() 방식 제거

  • "일정을 추가하세요" 제목이 있는 예쁜 모달 창으로 교체

  • 입력창(placeholder: 제목을 입력하세요) 추가

  • 일정 타입 선택 버튼 (Work, Sports, Friend, Other) 추가

  • "추가" / "취소" 버튼 구현

  • 일정 추가시 서버 POST 요청 및 프론트 렌더링 갱신

3. index.js 코드 정리

  • 중복 함수 제거 (특히 showAddModal 중복 제거)

  • 함수 구조를 일관성 있게 정리

  • 캘린더 렌더링, 모달 관련 함수 별도 구분

  • 코드 가독성 및 유지보수성 향상

4. CSS(style.css) 복구 및 유지

  • 레이아웃 문제 발생 후, 기존 정상 동작하던 CSS로 되돌림

  • 기존 달력 스타일, 이벤트 스타일, 모달 스타일 정상 적용

  • 레이아웃 깨짐 현상 해결 완료

5. UI 개선 작업

  • 모달 제목(일정을 추가하세요)을 위로 조금 더 올려 레이아웃 정리

  • 버튼, 입력창 간 여백 조정

  • 전체 디자인 통일성 유지

✨ 오늘 결과

  • 일정 추가/삭제 기능 모두 "모달 기반" UX로 업그레이드 완료

  • index.js 파일 가독성/구조 개선 완료

  • CSS 레이아웃 깨짐 복구 완료

  • 전체 시스템이 훨씬 사용자 친화적이고 깔끔한 형태로 발전함

📌 느낀점

모달 디자인/UX 개선은 확실히 사용성에 큰 차이를 준다.
코드를 조금씩 다듬어가는 과정에서 "완성도"가 점점 올라가는 걸 느꼈다.
앞으로도 변경사항은 항상 "백업 → 테스트 → 적용" 흐름을 지키면 좋을 것 같다.

📚 오늘 배운 것 (2025.04.26)

1. 모달(modal) 직접 만들기

  • div 요소로 모달 배경 만들고, 중앙에 박스(box) 띄우기

  • z-index, position: fixed 사용해서 화면 맨 위에 고정

  • 버튼 클릭 시 모달을 생성해서 붙이고, 닫을 때 remove() 로 제거

2. 모달 안에 동적으로 텍스트 삽입하기

  • 삭제 모달에서 삭제할 일정 이름을 가져와서 ${변수} 문법으로 모달 내용에 반영
`<p><strong>「${eventName}」</strong><br>일정을 삭제하시겠습니까?</p>`
  • 이렇게 모달을 만들면 다양한 내용(동적 내용)을 쉽게 보여줄 수 있다.

3. 모달 버튼 이벤트 연결 방법

  • 생성한 버튼에 addEventListener로 이벤트를 연결

  • "확인" 버튼 → 서버에 요청 보내고 삭제

  • "취소" 버튼 → 그냥 모달 닫기

  • 특히 모달은 한번 띄운 후 DOM에 추가된 버튼을 대상으로 이벤트 연결해야 한다.

4. 코드 중복 제거 및 함수화

  • 같은 동작(모달 띄우기, 모달 닫기 등)을 하는 코드들은 함수로 빼서 재사용

  • showConfirmModal(), hideConfirmModal(), showAddModal() 등 함수로 정리

  • 이렇게 하면 유지보수나 코드 수정할 때 훨씬 편하다.

5. CSS 정리하는 방법

  • CSS를 무조건 "깔끔한 흐름"으로 정리해야 레이아웃이 깨지지 않음

  • 새로운 기능을 추가할 때는 기존 CSS를 함부로 바꾸지 말고 필요한 부분만 추가하는 게 안전함

  • (오늘 실제로 한번 레이아웃 깨졌다가 되돌림!)

6. 애니메이션 적용 방법

  • 삭제할 때 fade-out 클래스를 추가해서 부드럽게 사라지게 만들기

  • @keyframes를 이용해서 opacity, transform을 자연스럽게 변하게 설정

  • 삭제 완료되면 서버에 삭제 요청 보내는 흐름

7. 서버와 통신하는 방법 (fetch) 복습

  • fetch(주소, { method, headers, body }) 형태로 서버랑 통신

  • 추가할 때는 POST, 삭제할 때는 DELETE

  • fetch 요청 성공/실패에 따라 .then(), .catch()로 처리

✨ 오늘 총 정리 요약

  • 모달 생성/제거 기본기 숙달

  • 동적 콘텐츠 삽입 방법 학습

  • 깔끔한 코드 정리 습관 체득

  • 삭제/추가 UX 향상시키는 방법 익힘

  • 서버 통신 흐름 복습 완료

📦 오늘 주요 코드 스니펫 정리

  1. 삭제 확인 모달 띄우기
function showConfirmModal({ eventName, onConfirm, onCancel }) {
  const existingModal = document.querySelector('.confirm-modal');
  if (existingModal) existingModal.remove();

  const modal = document.createElement('div');
  modal.className = 'confirm-modal';
  modal.innerHTML = `
    <div class="confirm-box">
      <p><strong>「${eventName}」</strong><br>일정을 삭제하시겠습니까?</p>
      <div class="modal-buttons">
        <button class="btn-yes">확인</button>
        <button class="btn-no">취소</button>
      </div>
    </div>
  `;

  // 버튼 이벤트 연결
  modal.querySelector('.btn-yes').addEventListener('click', () => {
    onConfirm();
    modal.remove();
  });
  modal.querySelector('.btn-no').addEventListener('click', () => {
    onCancel();
    modal.remove();
  });

  document.body.appendChild(modal);
}

👉 포인트

  • 일정 이름(eventName)을 동적으로 보여줌

  • 버튼 클릭 시 confirm 또는 cancel 흐름으로 진행

  • 기존에 열려있는 모달 있으면 삭제하고 새로 띄움

  1. 삭제 요청 보내기(fetch + 애니메이션)
deleteBtn.addEventListener('click', function () {
  showConfirmModal({
    eventName: ev.eventName,
    onConfirm: () => {
      div.classList.add('fade-out');
      div.addEventListener('animationend', () => {
        fetch(`http://localhost:8080/api/events?title=${encodeURIComponent(ev.eventName)}&type=${encodeURIComponent(ev.calendar)}&date=${ev.date.format('YYYY-MM-DD')}`, {
          method: 'DELETE'
        })
        .then(response => {
          if (response.ok) {
            // 프론트 메모리에서도 삭제
            const index = calendar.events.indexOf(ev);
            if (index > -1) {
              calendar.events.splice(index, 1);
            }
            calendar.renderEvents(calendar.events.filter(e => e.date.isSame(ev.date, 'day')), ele);
          } else {
            throw new Error('삭제 실패');
          }
        })
        .catch(error => {
          console.error('삭제 중 오류:', error);
          alert('삭제 실패');
        });
      }, { once: true });
    },
    onCancel: () => {
      hideConfirmModal();
    }
  });
});

👉 포인트

  • fade-out 애니메이션 먼저 적용하고

  • animationend 이벤트 끝나고 서버에 DELETE 요청

  • 삭제 실패시 alert 띄워서 사용자 알림

  1. 일정 추가 모달 띄우기
function showAddModal({ onSubmit, onCancel }) {
  const existing = document.querySelector('.add-modal');
  if (existing) existing.remove();

  const modal = document.createElement('div');
  modal.className = 'add-modal';
  modal.innerHTML = `
    <div class="add-box">
      <h3>일정을 추가하세요</h3>
      <input type="text" placeholder="일정을 입력하세요" class="add-title"/>
      <div class="type-buttons">
        <button data-type="Work">Work</button>
        <button data-type="Sports">Sports</button>
        <button data-type="Friend">Friend</button>
        <button data-type="Other">Other</button>
      </div>
      <div class="modal-buttons">
        <button class="btn-no">취소</button>
        <button class="btn-yes">추가</button>
      </div>
    </div>
  `;

  document.body.appendChild(modal);

  let selectedType = null;
  modal.querySelectorAll('.type-buttons button').forEach(btn => {
    btn.addEventListener('click', () => {
      selectedType = btn.dataset.type;
      modal.querySelectorAll('.type-buttons button').forEach(b => b.classList.remove('selected'));
      btn.classList.add('selected');
    });
  });

  modal.querySelector('.btn-yes').addEventListener('click', () => {
    const title = modal.querySelector('.add-title').value.trim();
    if (title && selectedType) {
      onSubmit(title, selectedType);
      modal.remove();
    } else {
      alert('제목과 유형을 선택하세요!');
    }
  });

  modal.querySelector('.btn-no').addEventListener('click', () => {
    onCancel();
    modal.remove();
  });
}

👉 포인트

  • 추가 버튼 누르면 제목, 카테고리 선택

  • "추가" 버튼 눌렀을 때만 서버에 POST 요청

  • 취소 버튼 누르면 모달만 닫음

✨ 총 요약

기능/주요 개념

  • 삭제 확인 모달 | showConfirmModal(), 삭제 애니메이션(fade-out), 서버 DELETE

  • 일정 추가 모달 | showAddModal(), 제목 입력 + 유형 선택, 서버 POST

  • CSS | 모달 레이아웃, 버튼 스타일링, 애니메이션 (fade, move)

  • fetch 사용법 | .then(), .catch(), 요청 성공/실패 구분

profile
끝까지 가면 내가 다 이겨

1개의 댓글

comment-user-thumbnail
2025년 4월 26일

아니 얘 봐라??....... 제가 알던 사람 맞나요...?

답글 달기