오늘의 학습은 단순한 기능 구현을 넘어, 브라우저가 서버와 소통하는 근본적인 방식(HTTP)과 백엔드 서비스의 아키텍처를 견고하게 다지는 과정이었다.
서버로 데이터를 보내기 전, 브라우저에서 1차적으로 데이터의 유효성을 검사한다.
이유: 서버 부하를 줄이고 사용자에게 즉각적인 피드백을 주기 위함이다.
핵심: form 태그의 onsubmit 이벤트를 사용하여 빈 값이나 잘못된 입력을 차단한다. trim()을 통해 공백만 입력되는 상황도 방지한다.
JavaScript
function ArticleWrite__submit(form) {
form.title.value = form.title.value.trim();
if (form.title.value.length == 0) {
alert('제목을 입력해주세요.');
return;
}
form.submit();
}
우리가 URL을 입력할 때 내부적으로 일어나는 과정은 다음과 같다.
1. DNS 조회: 도메인을 IP 주소로 변환하여 서버를 찾는다.
2. HTTP 요청 변환: 브라우저는 URL 정보를 바탕으로 HTTP 패킷을 생성한다.
3. HTTP 메서드 활용:
GET: 자원의 조회 (게시글 리스트 요청)
POST: 자원의 생성 (게시글 등록 데이터 전송)
PUT/PATCH: 자원의 수정
DELETE: 자원의 삭제
Controller가 모든 일을 전담하던 방식에서, 유지보수를 위해 역할을 명확히 나눴다.
- DispatcherServlet: 모든 요청의 입구(Front Controller). 요청을 분석해 적절한 컨트롤러로 배분한다.
- Controller (점원): 고객(사용자)의 요청을 받고 응답(JSP)을 결정한다.
- Service (요리사): 핵심 비즈니스 로직(검증, 데이터 가공)을 수행한다.
- Repository (창고지기): 데이터 저장소(DB/파일/리스트)와 직접 소통한다.
하나의 기능(게시물 작성)이라도 목적에 따라 메서드를 분리해야 한다.
- GET /usr/article/write: 작성 화면(Form)을 보여준다.
- POST /usr/article/write: 입력받은 데이터를 실제로 저장한다.
- getActionPath 도입: URL에서 명령어를 더 정확하게 추출하여 라우팅 효율을 높였다.
데이터 식별을 더 세련되게 처리하고 보안(Validation)을 강화했다.
✅ 상세 페이지 벨리데이션
존재하지 않는 게시물 ID로 접근할 경우, 서버 측에서 유효성을 체크하여 "존재하지 않는 게시물입니다"라는 메시지와 함께 리스트로 리다이렉트하는 방어적 프로그래밍을 적용했다.
✅ Path Variable 도입
기존: /usr/article/detail?id=1 (쿼리 스트링)
변경: /usr/article/detail/1 (경로 변수)
getLongPathValueByIndex 구현: URL 경로의 특정 인덱스에서 ID 값을 추출하는 로직을 만들어 훨씬 깔끔하고 RESTful한 URL 구조를 완성했다.
"URL은 자원을 식별하고, HTTP 메서드는 행위를 결정하며, 서버는 계층별 책임을 다한다."
오늘 구현한 DispatcherServlet의 switch-case 라우팅 로직과 Service-Repository 구조의 분리는 현대적인 프레임워크인 Spring MVC의 동작 원리를 이해하는 데 가장 중요한 밑거름이 될 것이다.