📍 HTTP 메소드에서의 멱등성
🍀 한 줄 요약: 요청(Request)을 한 번을 호출하든 여러 번을 호출하든 그 결과가 같음을 의미,
🍀 여러 번 동일한 요청을 보냈을 때, 서버에 미치는 의도된 영향이 동일한 경우
- 동일한 요청을 한번 보내는 것과 여러번 연속으로 보내는 것이 같은 효과를 가지고, 서버의 상태도 동일하게 남을 때 해당 HTTP 메서드가 멱등성을 가진다고 말할 수 있다. (응답 상태 코드가 아닌 서버의 상태와 관련이 된다!)
HTTP 스펙에 따르면, GET, PUT, DELETE 메소드는 멱등성을 보장해야한다고 나와있다고 한다. 한 번 하나씩 살펴보도록 하자.
1️⃣ GET 메소드
: 서버에 존재하는 리소스를 단순히 읽어오기만 하는 메소드이기 때문에 당연히 여러번 수행되어도 결과값은 변하지 않는다.
2️⃣ PUT 메소드
: 서버에 존재하는 리소스를 요청에 담긴 내용대로 통째로 대체해버리므로 올바르게 구현하였다면 여러번 수행되어도 결과 값은 변하지 않을 것 이다.
3️⃣ DELETE 메소드
: DELETE를 처음 요청 하면, 서버에서 해당 리소스는 삭제가 된다. 이후 DELETE를 여러번 요청하더라도 해당 리소스는 삭제된 상태 그대로 일 것이니 서버의 상태는 변하지 않는다.
4️⃣ PATCH 메소드
: 리소스의 일부분을 수정하는 경우 사용된다. 특이하게 경우에 따라 멱등성을 보장할 수도, 보장하지 않을 수도 있다.
✔️ 멱등성을 보장하는 경우
: 리소스의 일부분을 대체하는(갈아끼우는) 경우, 멱등성을 보장한다.
✔️ 멱등성을 보장하지 않는 경우
: 리소스에 특정 연산이 들어가는 경우 (값을 증가시키거나 등등)
예를 들어 아래처럼, 나이를 10씩 "증가"하는 요청을 보내게 되면, 요청을 보낼때마다 나이값은 달라지므로, 결과값도 달라지게 된다.
{ "operation": "add", "age": 10"}
아래처럼 매 요청마다 새로운 데이터를 추가해서 보내는 것도, 멱등성에 어긋나는 행위가 된다.
- PATCH → name: [”MangKyu”]
- PATCH → name: [”MangKyu”, ”MangKyu”]
- PATCH → name: [”MangKyu”, ”MangKyu”, ”MangKyu”]
5️⃣ POST 메소드
: 이 경우 당연히 데이터베이스에 리소스가 추가되는 행위이므로, 요청시마다 데이터가 추가되어 서버의 상태도 매번 바뀌게 된다.
👉 정리: 스스로 머리속으로 정리한결과, 멱등성을 보장하지 않는 경우는 해당 요청을 잘못해서 중복으로 계속 요청하게 되는 경우!!일 가능성이 높다고 생각된다.
예를들어, 결제시스템에서 결제POST를 여러번 요청하거나 하는 행위 !! 매우 주의하는 경우들은 멱등성을 보장하지 않을 가능성이 높다는 생각이 들었다-!
[참고참고참고용... RFC 공식문서(RFC7230, RFC7231)에 자세히 나와있는 듯하다... 영어를 잘 못해서 일단은 패쑤..)
https://www.rfc-editor.org/search/rfc_search_detail.php
RFC Search Detail
From Month January February March April May June July August September October November December Year 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998
www.rfc-editor.org
📍Spring Boot 구동 원리
우선 구동원리를 살펴보기 전에! 몇가지 핵심원리들을 먼저 살펴보고자 한다.
🤔 Servlet 이란?
🍀 Spring Servlet은 웹 애플리케이션에서 클라이언트의 요청을 처리(요청을 받고, 응답을 반환)하는 작업을 한다.
일반적으로 이 Servlet을 Spring MVC 패턴에서 DispatcherServlet이라고 불린다.
(Servlet은 일반적인 개념과 인터페이스를 나타내고, DispatcherServlet은 Spring의 특정 구현을 나타낸다.)
- Servlet Container에 의해 동작하는 Servlet은 javax.servlet 패키지안에 정의된 인터페이스이며 HTTP 요청, 응답을 처리하며 웹페이지를 동적으로 생성하는 역할을 한다.
- 기본적으로 init, service, destroy 메소드가 정의되어 있다.
- 대표적으로 DispatcherServlet, HttpServlet등의 구현체가 있으며 서블릿들은 일반적으로 HttpServlet을 상속받는다.
🤔 Servlet Container란?
🍀 Servlet들을 관리하는 저장소
servlet의 생성부터 소멸까지의 일련의 과정(Life Cycle)을 관리한다.
대표적으로 톰캣은 WAS로 Web Server + Web Container(Sevlet Container)의 역할을 담당한다.톰캣을 WAS라 하는 곳도 있고 웹 컨테이너라고 하는 곳도 있고... 애매모호하게 느껴진다.(더 공부해봐야할듯..!)
1️⃣ Servlet 생명주기 관리
Servlet Container는 Servlet의 생명주기를 관리(init(), service(), destory() 메서드)하는데 클라이언트의 요청이 오면 init()메서드를 호출해 Servlet을 load한다. 이후 클라이언트의 요청에 따라 service()메서드를 실행해 처리한 다음 destroy() 메서드를 이용해 servlet을 제거(unload)한다.
2️⃣ 요청 및 응답 처리
URL의 정보를 분석하여 요청을 처리할 web.xml에 등록된 서블릿을 찾는다.
Container는 서블릿에 대한 Thread를 생성하고, HttpServletRequest, HttpServletResponse 객체를 생성한 뒤이를 servlet의 service() 메서드에 전달을 한다. servlet은 이 객체를 사용해 클라이언트의 요청을 분석해서 응답을 만든다.
스프링부트를 사용한다면 내장 서블릿 컨테이너를 포함하고있기때문에 web.xml 파일이 없어도 @EnableAutoConfiguration, @ComponentScan, @Configuration 등의 어노테이션으로 필요한 서블릿을 자동으로 설정된다.
3️⃣ URL Mapping
Servlet Container는 클라이언트가 요청한 URL을 기반으로 호출할 servlet을 결정(mapping)한다. 즉, URL을 servlet과 연결하는 작업을 한다.
servlet을 특정한 URL에 매핑하는것뿐만 아니라 패턴을 이용해 servlet을 여러 URL에 매핑할수도 있다. 무슨말이냐면 servlet을 "/products/*" 에 매핑을하면 이 servlet은 "/products/" 로 시작하는 URL에 대한 모든 요청을 처리한다.
4️⃣ 멀티 스레딩 지원
클라이언트 요청에 대해서 Servlet Container는 새로운 Java 스레드를 생성하여 요청을 처리한다. 이러한 기능 덕분에 웹 애플리케이션은 여러 요청을 동시에 처리할 수 있다.
🤔 Dispatcher Servlet
🍀 HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해주는 프론트 컨트롤러(Front Controller)
작동 방식을 먼저 쉽게 정리해보면,
- 클라이언트로부터 요청이 오면 Tomcat과 같은 서블릿 컨테이너가 요청을 받는다.
- 그리고 이 모든 요청을 프론트 컨트롤러인 디스패처 서블릿이 가장 먼저 받게 된다.
- 그러면 디스패처 서블릿은 공통적인 작업을 먼저 처리한 후에 해당 요청을 처리해야 하는 컨트롤러를 찾아서 작업을 위임한다.
우리는 컨트롤러를 구현해두기만 하면 디스패처 서블릿가 알아서 적합한 컨트롤러로 위임을 해주는 구조가 된 것 !!
✔️ Dispatcher Servlet 의 동작 방식
(🔗출처: https://mangkyu.tistory.com/18)
1️⃣ 클라이언트의 요청을 디스패처 서블릿이 받음
2️⃣ 요청 정보를 통해 요청을 위임할 컨트롤러를 찾음
@Controller에 @RequestMapping 관련 어노테이션을 사용해 컨트롤러를 작성하는 것 !!
오늘날 흔한 @Controller 방식은 RequestMappingHandlerMapping가 처리한다. 이 친구는 @Controller로 작성된 모든 컨트롤러를 찾고 파싱하여 HashMap으로 <요청 정보, 처리할 대상> 관리한다.
3️⃣ 요청을 컨트롤러로 위임할 핸들러 어댑터를 찾아서 전달함
디스패처 서블릿은 컨트롤러로 요청을 직접 위임하는 것이 아니라 HandlerAdapter를 통해 위임한다.
> 다양하게 작성되는 컨트롤러에 대응하기 위해 스프링은 HandlerAdapter라는 어댑터 인터페이스를 통해 어댑터 패턴을 적용함으로써 컨트롤러의 구현 방식에 상관없이 요청을 위임할 수 있도록 하였음
4️⃣ 핸들러 어댑터가 컨트롤러로 요청을 위임함
5️⃣ 비지니스 로직을 처리함
컨트롤러는 서비스를 호출하고 우리가 작성한 비지니스 로직들이 실행된다.
6️⃣ 컨트롤러가 반환값을 반환함
7️⃣ 핸들러 어댑터가 반환값을 처리함
8️⃣ 서버의 응답을 클라이언트로 반환함
응답이 데이터라면 그대로 반환되지만, 응답이 화면이라면 View의 이름에 맞는 View를 찾아서 반환해주는 ViewResolver가 적절한 화면을 내려준다.
📍 EnumType.ORDINAL (의 단점)
속성 | 기능 | 기본값 |
value | EnumType.ORDINAL : enum 순서를 데이터베이스에 저장 EnumType.STRING : enum 이름을 데이터베이스에 저장 |
EnumType.ORDINAL |
위의 예시에서 enum에 정의된 순서대로, SERVER는 0, WEB은 1값이..등등 데이터베이스에 저장된다.
- 장정 : 데이터베이스에 저장되는 데이터 크기가 작습니다.
- 단점 : 이미 저장된 enum의 순서를 변경할 수 없습니다.
추후 SERVER가 1, WEB을 0으로 변경하게 되었을때 .. 가 문제가 된다. 왜냐! SERVER가 1로 변경된지 모르고 가져올 수 있으니
📍 스프링 빈의 생명주기
빈(Bean)은 스프링 컨테이너에 의해 관리되는 재사용 가능한 소프트웨어 컴포넌트이다. 즉, 스프링 컨테이너가 관리하는 자바 객체를 뜻하며 스프링 컨테이너에 등록된 객체를 스프링 빈이라고 한다.
스프링에서 Bean의 생명주기는 크게 세 가지 단계로 나눌 수 있다.
3️⃣ 첫째, Bean의 인스턴스 생성 단계
- Bean은 스프링 컨테이너에서 빈으로 등록되면, 해당 빈의 클래스의 인스턴스를 생성한다. 이 때, 스프링 컨테이너는 Bean의 클래스를 찾아서 인스턴스를 생성한다.
2️⃣ 둘째, Bean의 의존성 주입(Dependency Injection) 단계
- Bean의 생성이 완료되면, 해당 Bean이 의존하는 다른 Bean들이 주입된다. 이 때, 스프링은 설정 파일에서 빈 간의 의존 관계를 확인하고, 해당 빈이 의존하는 다른 빈을 찾아서 주입한다.
3️⃣ 셋째, Bean의 초기화(Initialization)와 소멸(Destruction) 단계.
- Bean의 인스턴스 생성과 의존성 주입이 완료된 후에는, 스프링 컨테이너는 빈을 초기화하고, 필요에 따라 소멸한다. 이 때, 빈의 초기화 작업은 InitializingBean 인터페이스의 afterPropertiesSet() 메서드나, @PostConstruct 어노테이션을 이용하여 구현할 수 있다. 또한, 빈의 소멸 작업은 DisposableBean 인터페이스의 destroy() 메서드나, @PreDestroy 어노테이션을 이용하여 구현할 수 있다.
[🙇♀️ 출처 모음 🙇♀️]
https://inpa.tistory.com/entry/WEB-🌐-HTTP의-멱등성-·-안정성-·-캐시성-💯-완벽-이해하기
[Inpa Dev 👨💻:티스토리]
https://hudi.blog/http-method-idempotent/
[hudi.blog]
https://mangkyu.tistory.com/251
[MangKyu's Diary:티스토리]
https://ttl-blog.tistory.com/115
[Shin._.Mallang:티스토리]
https://www.inflearn.com/blogs/3313https://seungjjun.tistory.com/297
'연합동아리 > SOPT' 카테고리의 다른 글
엔티티의 생명주기와 Java의 Checked Exception과 Unchecked Exception (0) | 2024.05.01 |
---|---|
[NOW SOPT] SERVER - 1차 세미나 정리 (0) | 2024.04.10 |