스프링을 이용해서 개발을 하던 중, 검색이나 정렬등 여러 기능을 사용해서 웹페이지의 내용들을 표시할때,
왜 ? UriComponents와 같은 라이브러리를 사용해서 uri를 만들고
왜 ? 그 조합되어 웹페이지의 주소창에 표시되는 uri에 따라 표시되는 내용이 달라지는지
왜 ? 브라우저 주소창의 URI에 임의로 값을 넣으면 서버단의 결과값을 바꿀 수 있는지 궁금해졌다.
bgno(게시판카테고리구분), page(현재페이지), perPageNum(페이지에 표시 할 게시글 개수), searchType(검색타입) ,
keyword(검색어), sort(최신순,댓글순 등 정렬) 이다.
게시글 목록을 출력로직인 /board/list라는 컨트롤러 매핑 주소값에 대응되는 쿼리(게시글목록)의 where문에 들어가는 내용들이다.
(게시판목록 html페이지는 board폴더의 list.jsp파일이다. 주소창의 /board/list)
첫번째 사진 주소창은 커뮤니티 카테고리에 들어가서 아무것도 조작하지 않았을 때의 상태이다.
http://localhost:8080/board/list?bgno=1&page=1&perPageNum=10&searchType=&keyword=&sort=
두번째 사진 주소창은 조회순 정렬 버튼을 눌렀을때 이고
http://localhost:8080/board/list?bgno=1&page=1&perPageNum=10&searchType=&keyword=&sort=viewCount
세번째 사진 주소창은 조회순정렬, 전체타입으로 f 검색어를 검색하고 20개씩 보기를 한 후 2페이지로 갔을때이다.
http://localhost:8080/board/list?bgno=1&page=2&perPageNum=20&searchType=tcw&keyword=f&sort=viewCount
스프링으로 개발을 하면서,
당연히 World Wide Web(http프로토콜) 을 사용하고,
http프로토콜이 뭔지 이론상으로는 훑어봤고,
개발을 하면서도 계속 작성한 코드와 , 주소창의 uri를 보면서 페이지이동시 요청값이 잘 넘어오는지
지켜보면서 개발을 했지만 그 연관관계에 대해서 생각해본 적이 없었다.
포트폴리오를 만들면서 모티브로 정한 웹페이지들의 기능들을 눌러보고, uri의 변화에 따라서 어떤식으로 구현할지
대략 머리속에 생각나고 관련 정보를 찾아 만드는 과정도 있었지만 왜 uri의 변화에 따라 결과가 바뀌는건지 생각해본적이 없었다. uri가 어떻게 작용하길래 결과값이 나오게 되는걸까...
일단 먼저 http프로토콜에 대한 이해가 필요할 것 같아서, 관련 내용을 찾아보았다.
HTTP는 HTML문서와 같은 리소스들을 가져올 수 있도록 해주는 프토토콜이다.
웹에서 이루어지는 모든 데이터 교환의 기초이고, 클라이언트 - 서버 프로토콜이다.
클라이언트에 의해 전송되는 메시지를 요청(Request) 서버에서 응답으로 전송되는 메시지는 응답(Response)라고 한다.
Http프로토콜에 대해 모르더라도, 웹개발을 공부하면서 서블릿을 접하게되면 들을 수 밖에 없는 두 단어이다.
서블릿이란?
자바로 구현된 클라이언트의 요청에 동적으로 작동하는 웹어플리케이션 컴포넌트 ,
HTML을 사용하여 Response,
MVC패턴에서 Controller,
HttpServlet라이브러리 클래스를 상속,
jsp파일이 WAS(톰캣)에 의해 서블릿 클래스로 변환되어 사용되어 진다.(jsp로 작성->servlet파일로 변환->HTML로 변환)
이러한 과정 때문에,
스프링에서 환경설정 시
web.xml에 Bean을 지정할 xml파일 경로를 선언하고
xml파일에서(root-context.xml 등) 스프링이 jsp파일을 스캔할 수 있도록
InternalResourceViewResolver 에 jsp파일의 경로등을 설정하는 것이다.
//root-context.xml
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
서블릿 클래스는 서블릿 컨테이너(web.xml)에 의해 관리되서 소멸되고 생성된다.
결국 서블릿을 사용하는 java파일은 html로 변환되어서, 프로토콜을 통해 클라이언트와 서버가 통신한다는 것이다.
!!HTML문서만이 HTTP 통신을 위한 유일한 정보 문서는 아니다, JSON과 XML과 같은 형태도 가능하다.
클라이언트가 서버로 요청을 했을때 , 보내는 데이터를 HTTP패킷이라고 표현한다.
f12를 눌러 개발자도구의 네트워크탭을 보면 볼 수 있다.
패킷의 구조는 크게 헤더와 바디로 나뉘어진다.
헤더는 메서드방식,클라이언트의 정보,브라우저 정보, 접속할URL등 과 같은 클라이언트 정보를 담고
바디엔 서버에 요청을 보낼 수 있는 특정 데이터를 담는다.
HTTP에는 7가지 메서드 방식이 있는데, 주로 사용하는 GET과 POST에 대해서만 알아보겠다.
두 방식 모두 서버에 요청을 하는 메서드이다.
GET방식은 URL에 데이터를 담아서 보내고 , key-value 형식으로 데이터를 넣는다. (위의 예시의 /board/list?bgno=1 )
URL에 붙이므로, HTTP패킷의 헤더에 포함되어 서버에 요청하고, BODY는 비어진 상태로 보내진다.
그러므로 헤더의 내용중 BODY 데이터를 설명하는 CONTENT-TYPE과 같은 헤더필드는 들어가지 않는다.
URL형태로 표현되므로 특정페이지를 다른 사람에게 접속하게 할 수 있고,
간단한 데이터를 넣도록 설계되어, 데이터를 보내는양에 한계가 있다.
URL형태로 데이터를 붙이므로 주로 페이지 조회등에 사용된다.
그래서 로그인과 같은 처리를 GET방식으로 하면 URL에 정보가 표시되고 보안상 취약하므로 POST방식으로 사용하는 것이다.
POST방식은 URL이 아닌 HTTP프로토콜의 BODY에 데이터를 넣어서 보내고, Content-Type 등으로 값을 받을 수 있지만, 자세한 설명은 생략하겠다.
보안상 취약해서 POST방식을 사용한다고 했지만 사실 GET과 POST방식 둘다 적절한 보안기능은 필수이다..
내가 궁금했던 부분은
GET방식의 HTTP메서드를 사용하고, 서버에 요청하는 데이터를 URL에 담아서 보내는 것이였다.
만약 예시의 첫번째인
http://localhost:8080/board/list?bgno=1&perPageNum=10&searchType=&keyword=&sort=
에서 조회수 정렬 버튼을 눌러서 (onclick="location.href=' * ' ")
http://localhost:8080/board/list?bgno=1&perPageNum=10&searchType=&keyword=&sort=viewCount
라는 URL에 접속한다고 생각해보자.
HTTP의 통신방식은 클라이언트 -> 서버로 요청 -> 서버 -> 클라이언트로 응답 이다.
스프링MVC와 비교하면 뷰(클라이언트) <-> 컨트롤러(요청,응답) <-> 모델(서버) 이렇게 표현 할 수 있겠다.
뷰에서 URL에 접속하면 클라이언트에서 /board/list라는 페이지정보와 ?뒤의 데이터를 보낸 것 이다.(요청)
board폴더의 list라는 jsp파일과 뒤의 정보를 WAS가 html 형식으로 변환시켜주고,
HTTP 프로토콜의 GET메서드를 이용해서 서버로 데이터를 보냈다.
컨트롤러에서 해당 데이터를 받아서 /board/list라는 매핑주소에 맞는 컨트롤러에 데이터를 넘겨주고,
해당 컨트롤러는 매개변수로 값을 받는다.
VO나 DTO로 값을 받을 수도 있을 것이고, @RequestParam,@ModelAttribute같은 어노테이션으로 받을수도 있을것이고, 라이브러리 인터페이스를 사용하는 등 여러가지 방법으로 값을 받는다.
그렇게 위의 URL에서 BoardVO라는 VO로
bgno=1(게시판 카테고리)와 sort=viewCount(조회순 정렬)라는 값을 받았다.
(나머진 페이징에 관련된 URI라 설명 생략)
그 다음, service나 Mapper 등의 로직을 거쳐 모델(DB)의 쿼리에서 받은 값을 대입해서, 결과( 게시글목록)을 얻었다.
(DB에 저장되어 있는 게시판테이블에서 bgno가 1인 커뮤니티카테고리의 게시글들을 조회순으로 정렬해서 가져옴)
이제 컨트롤러에서 다시 클라이언트로 결과를 반환한다. (응답)
org.springframework.ui.Model 과 같은 Model객체 등, 모델에서 뷰로 보낼 수 있는 방식들을 사용해서 뷰(클라이언트)로 결과를 보내고,
클라이언트에선 board폴더의 list 라는 jsp파일에 서버에서 받은 결과를 적용한 페이지를 볼 수 있게 된다.
간단하게, 이런 흐름으로 HTTP프로토콜을 이용해서 클라이언트에서 URL로 데이터를 서버로 전달할 수 있는 것이다.
form태그를 이용해 POST,GET방식등으로 데이터를 보내는 것 또한 같은 맥락이다.(input등..)
HTTP프로토콜,서브릿에 대한 자세한 설명들은(무상태, 요청헤더,응답헤더들의 데이터 포멧 등..)
구글검색을 통해 많은 정보를 볼 수 있으니 생략했고,
내가 궁금했던 내용에서 필요한 부분만 간략하게 추려서 이번 글에 작성했다.
HTTP프로토콜의 통신방식과 서블릿과 WAS의 역할등의 공부를 통해 어떻게 URL로 데이터를 받는지에 대해 알아보았다.
스프링에서 환경설정,코드작성을 하고 서버를 구동시켜서 브라우저에 URL을 입력하면
간단히 HTTP통신을 이용한 Hello world 를 출력 할 수 있겠지만..
그 안의 과정이 얼마나 많고, 복잡한지에 대해선 생각조차 할 수가 없을 것 같다...
위의 과정 설명은 겉핥기 수준에 불과하다는 걸 알고 있다.
차근차근 웹 기능의 구현에 대한 로직을 공부하면서,
이런 웹기능이 동작하는 기초적인 원리에 대한 이해를 절실히 느낀다.
그냥 이걸 이렇게 하면 된다가 아니라 왜 이렇게 되는지...를 항상 생각하며 웹개발을 공부해보고 싶다.
'SPRING > Spring' 카테고리의 다른 글
스프링에서 ajax 사용의 유형들 (0) | 2021.10.30 |
---|---|
[스프링] Session과 Cookie , HttpSession (2) | 2021.09.14 |
DataAccessException 란? -Spring 예외처리 (0) | 2021.08.12 |
HttpserveltRequest와 HttpSession,세션과 로그인 로그아웃 (0) | 2021.08.03 |
UriComponents과 URLEncoding (0) | 2021.07.31 |