JSP + Spring FE 트러블슈팅 정리
요즘 취직하고 이래저래 할 것이 많아서 제대로 된 글을 작성하지 못했습니다.
회사에서 내어준 과제를 진행하며 겪은 문제를 정리했습니다.
트러블 슈팅
1. Overlay 문제
- 문제 : 요소가 다른 요소의 Overlay 순서가 꼬이는 문제
- 원인 :
z-index값이 잘못 들어가있음 - 해결 :
z-index의 값을 요소 별로 적절히 배분
2. 메인 화면 슬라이드 전환간 Button의 “선택 상태”
- 문제
- radio처럼 기본적으로 한 개가 선택되어 있어야 함
- 화면 전환 시 그에 맞는 버튼으로 자동으로 선택되어야 함
- 버튼을 클릭하면 그에 맞는 화면으로 전환되어야 함
- 원인
is-active가 아닌active옵션 사용 및 EventListener 미활용
- 해결
is-active옵션 추가<button type="button" class="home-toggle-btn is-active" id="alarmONButton"> 알림<br>ON </button> <button type="button" class="home-toggle-btn" id="searchONButton"> 검색<br>ON </button>for-each문을 활용해 버튼을 순회하며 상태 관리buttons.forEach(btn => { btn.addEventListener('click', () => { buttons.forEach(b => b.classList.remove('is-active')); btn.classList.add('is-active'); }); });- JS를 활용해 화면 전환 구현(기존 코드 재활용)
alarmONButton.addEventListener('click', () => { window.moveToSlide(0); }); searchONButton.addEventListener('click', () => { window.moveToSlide(1); }); - 추가로 궁금한 점
- 왜 radio를 사용하지 않고 button을 사용할까?
- radio라는 편한 기능이 있는데, for-each 등을 활용해 button으로 구현하는 이유가 궁금해 찾아보았다.
- 디자인 제약
- 브라우저마다 모양이 다르고, 크기·색상·애니메이션 적용이 거의 불가능
border-radius와 같은 CSS 직접 적용 불가
- 상호작용 제어가 제한적 : 클릭 영역이 작고, “눌렀다”는 피드백을 주기 어려움
- 아이콘 + 텍스트, 설명 문구, 카드 형태의 선택 UI 등 복잡한 상태 표현이 힘듦
- window가 무엇인가?
- 브라우저 전체를 대표하는 최상위 객체로 탭 하나, 그 안의 페이지, 화면, 스크롤, 위치, 전역 변수 등 모든 것을 감쌈
- 버튼을 클릭하면 window 객체에서 moveToSlide 함수를 호출하여 인자를 전달
JS에서 전역으로 선언한 함수는 자동으로 window의 속성이 됨- 단순히
moveToSlide로 작성해도 되지만 아래 이유로 window를 명시- 전역 함수라는 것을 명확히 하기 위해
- 이름 충돌 방지 및 의도 표현
- 추후 구조 변경이 용이
- 어떻게 바로 실행되는가?
(() => { // 코드 })();- 마지막
()를 통해 JS 파일이 로드될 때 바로 호출
- 마지막
- 왜 radio를 사용하지 않고 button을 사용할까?
기타 궁금한 점 등
FE의 동작 조건
- HTML이 요소(노드)를 생성 : DOM 생성
- 브라우저가 HTML을 읽으면
<div>같은 요소들이 DOM(Documented Object Model) 트리로 만들어짐 - JS는 DOM을 통해 요소를 제어할 수 있음
- 브라우저가 HTML을 읽으면
- CSS가 어떻게 보여줄지 정의
- 레이아웃, 스타일, 애니메이션 등 결정
- JS가 이벤트를 결정
- 이벤트가 발생했을 때 DOM/CSS 값을 바꿔서 화면 상태를 갱신
- JS 실행 타이밍 조건
- JS가 DOM 요소를 잡으려면, 그 요소가 DOM에 이미 존재해야 함
- 스크립트가 너무 위에서 실행되거나, 요소 이름이 바뀌거나, 페이지마다 구조가 다르면 동작하지 않음
- JS는 어떻게 이벤트를 받아 처리하고 화면을 구성할까?
- JS는 이벤트를 만드는 주체가 아닌, 이벤트를 기다리다 발생하면 처리하는 역할
- 이벤트 발생 -> 이벤트 객체 생성 -> 리스너 실행 -> 상태 변경 -> DOM/CSS 갱신 -> 브라우저가 다시 그림
이벤트
- 이벤트란?
- 브라우저에서 발생하는 신호·사건
- 사용자 입력, 마우스, 화면·브라우저, 로딩 등
- 이벤트가 발생하면 브라우저는 Event 객체를 생성해 핸들러에게 전달
- 이벤트 핸들러란?
- 특정 이벤트가 발생했을 때 실행할 함수를 등록해두는 장치
- 구조
btnRight.addEventListener("click", () => { ... });- bntRight : 이벤트를 받을 대상
- click : 이벤트 종류
() => { ... }: 이벤트 발생 시 실행할 콜백 함수
- 리스너만 있으면 이벤트를 다 받을 수 있을까?
- 아니다. 어디에 붙였는지와 전파에 따라 다름
- 이벤트는 타겟 요소에서 발생
- click은 실제 클릭한 요소에서 발생
- 그 요소에 리스너를 붙이면 확실히 받음
- 이벤트는 전파될 수 있음
- 대부분의 DOM 이벤트는 부모 방향으로 전파(Bubbling)되므로 자식에서 발생한 이벤트는 부모에서 받을 수도 있음
- 안받아지는 경우
- DOM 요소가 존재하기 전에 리스너를 단 경우
display: none인 요소에 이벤트를 기대하는 경우- 이벤트가 bubbling되지 않는 타입인 경우
focus, blur, mouseenter, mouseleave등
- stopPropagation()으로 중간에 끊긴 경우
- 다른 요소가 위에서 덮은 경우
- CustomEvent를 Dispatch하지 않은 경우
- 리스너는 다중 구조를 가질 수 있음
- 이벤트 전파(Event Propagation)
- 이벤트는 DOM 트리를 타고 이동하는데 순서가 있음
- Capturing : 위(문서) -> 아래(타겟)로 내려감
- Target : 실제 이벤트가 발생한 요소에서 처리
- Bubbling : 아래(타겟) -> 위(문서)로 올라감
- 기본적으로 addEventListener는 Bubbling 단계에서 동작
- 이벤트 위임(Event Delegation)
- 자식이 많을 때 자식마다 리스너를 다는 것이 아니라, 부모 하나만 달아서 처리하는 패턴
- 자식에서 click 이벤트 발생 -> 이벤트가 부모로 Bubbling -> 부모 리스너가
e.target을 보고 어떤 자식이 눌렀는지 판별
- 이벤트 전파(Event Propagation)
Dispatch
- Listener는 듣고만 있고 dispatchEvent()는 이벤트가 발생했다고 브라우저에 알리는 행위
- addEventListener는 마이크를 켜둔 것이고, dispatchEvent는 실제로 말을 하는 것
index.jsp에서 슬라이드가 동작하는 과정
- 초기화 후 즉시 실행
- state 만들기
let index = 0; const maxIndex = slides.length - 1; - render()를 통해 화면 그리기
const render = () => { track.style.transform = `translateX(-${index * 50}%)`; btnLeft.classList.toggle("is-disabled", index === 0); btnRight.classList.toggle("is-disabled", index === maxIndex); };- 트랙 위치 갱신(transform)
- 버튼 UI 상태 갱신
- 버튼 클릭 시 상태를 바꾸고 render()
btnRight.addEventListener("click", () => { index = Math.min(maxIndex, index + 1); render(); }); - 외부에서도 슬라이드를 이동할 수 있도록 공개