4주 차에서 다룰 내용은 다음과 같다.
1. Network
- 대칭키/공개키
- HTTP / HTTPS
- 로드 밸런싱
- Blocking, Non-blocking / Synchronous, Asynchronous
- Blocking / Non-Blocking I/O
2. Spring
- Bean Scope
- MVC Framework
- Spring Boot, SpringApplication
Network
대칭키&공개키
대칭키란(Symmetric Key)?
암호화와 복호화에 같은 암호키를 사용하는 알고리즘
동일한 키를 주고받기 때문에, 매우 빠르다. 하지만 전달 과정에서 해킹 위험에 노출된다.
공개키(Public Key)/비대칭키(Asymmetric Key)란?
대칭키의 키 분배 문제를 해결하기 위해 고안됨.(대칭키일 때는 송수신자 간만 키를 알아야 하기 때문에
분배가 복잡하고 어렵지만 공개키와 비밀키로 분리할 경우, 남들이 알아도 되는 공개키만 공개하면 되므로)
자신이 가지고 있는 고유한 암호키(비밀키)로만 복호화할 수 있는 암호키(공개키)를 대중에 공개함
대칭키와 공개키를 적절하게 사용한 예시
1. A가 B의 공개키로 암호화 통신에 사용할 대칭키를 암호화하고 B에게 보냄
2. B는 암호문을 받고, 자신의 비밀키로 복호화함
3. B는 A로부터 얻은 대칭키로 A에게 보낼 평문을 암호화하여 A에게 보냄
4. A는 자신의 대칭키로 암호문을 복호화함
5. 앞으로 이 대칭키로 암호화를 통신함
HTTP & HTTPS
HTTP(HyperText Transfer Protocol)란?
인터넷상에서 클라이언트와 서버가 자원을 주고받을 때 쓰는 통신 규약
HTTP는 텍스트 교환 -> 해킹 시 내용 노출되는 보안 이슈가 존재
HTTPS(HyperText Transfer Protocol Secure)란?
인터넷상에서 정보를 암호화하는 SSL 프로토콜을 사용해 클라이언트와 서버가 자원을 주고받을 때 쓰는 통신 규약
HTTPS는 텍스트를 암호화한다. (공개키 암호화 방식으로)
HTTPS 통신 흐름
1. 애플리케이션 서버(A)를 만드는 기업은 HTTPS를 적용하기 위해 공개키와 개인키를 만든다.
2. 신뢰할 수 있는 CA 기업을 선택하고, 그 기업에게 내 공개키 관리를 부탁하며 계약을 한다.
CA란? : Certificate Authority로, 공개키를 저장해주는 신뢰성이 검증된 민간기업
3. 계약 완료된 CA 기업은 해당 기업의 이름, A서버 공개키, 공개키 암호화 방법을 담은 인증서를 만들고, 해당 인증서를 CA 기업의 개인키로 암호화해서 A서버에게 제공한다.
4. A서버는 암호화된 인증서를 갖게 되었다. 이제 A서버는 A서버의 공개키로 암호화된 HTTPS 요청이 아닌 요청이 오면, 이 암호화된 인증서를 클라이언트에게 건네준다.
5. 클라이언트가 main.html 파일을 달라고 A서버에 요청했다고 가정하자. HTTPS 요청이 아니기 때문에 CA기업이 A서버의 정보를 CA 기업의 개인키로 암호화한 인증서를 받게 된다.
6. 브라우저는 해독한 뒤 A서버의 공개키를 얻게 되었다. 이제 A서버와 통신할 대는 얻은 A서버의 공개키로 암호화해서 요청을 날리게 된다.
로드 밸런싱(Load Balancing)
사람들이 급격하게 늘어나는 트래픽을 감당하기에는 1대의 서버로는 부족하다.
대응 방안으로는 하드웨어의 성능을 올리거나 여러 대의 서버가 나눠서 일을 하도록 만드는 것이다.
서버가 여러 대면 무중단 서비스를 제공하는 환경 구성이 용이하므로 Scale-out이 효과적이다.
이때 여러 서버에게 균등하게 트래픽을 분산시켜주는 것이 로드 밸런싱이다.
로드 밸런서가 서버를 선택하는 방식
- 라운드 로빈(Round Robin) : CPU 스케줄링의 라운드 로빈 방식 활용
- Least Connections : 연결 개수가 가장 적은 서버 선택 (트래픽으로 인해 세션이 길어지는 경우 권장)
- Source : 사용자 IP를 해싱하여 분배 (특정 사용자가 항상 같은 서버로 연결되는 것 보장)
Blocking/Non-blocking & Synchronous/Asynchronous
Blcking과 Synchronous, Non-blocking, Asysnchronous를 서로 같은 개념이라고 착각하기 쉽다.
각 차이점에 대해 알아보자.
Blocking/Non-blocking
블록/논 블록은 간단히 말해서 호출된 함수가 호출한 함수에게 제어권을 건네주는 유무의 차이라고 볼 수 있다.
함수 A, B가 있고, A 안에서 B를 호출했다고 가정해보자. 이때 호출한 함수는 A고, 호출된 함수는 B가 된다. 현재 B가 호출되면서 B는 자신의 일을 진행해야 한다. (제어권이 B에게 주어진 상황)
- Blocking : 함수 B는 내 할 일을 다 마칠 때까지 제어권을 가지고 있는다. A는 B가 다 마칠 때까지 기다려야 한다.
- Non-blocking : 함수 B는 할 일을 마치지 않았어도 A에게 제어권을 바로 넘겨준다. A는 B를 기다리면서도 다른 일을 진행할 수 있다.
즉, 호출된 함수에서 일을 시작할 때 바로 제어권을 리턴해주느냐, 할 일을 마치고 리턴해주느냐에 따라 블록과 논 블록으로 나누어진다고 볼 수 있다.
Synchronous/Asynchronous
동기/비동기는 일을 수행 중인 동시성에 주목하자
아까처럼 함수 A와 B라고 똑같이 생각했을 때, B의 수행 결과나 종료 상태를 A가 신경 쓰고 있는 유무의 차이라고 생각하면 된다.
- Synchronous : 함수 A는 함수 B가 일을 하는 중에 기다리면서, 현재 상태가 어떤지 계속 체크한다.
- Asynchronous : 함수 B의 수행 상태를 B 혼자 직접 신경 쓰면서 처리한다. (Callback)
즉, 호출된 함수(B)를 호출한 함수(A)가 신경 쓰는지, 호출된 함수(B) 스스로 신경 쓰는지를 동기/비동기라고 생각하면 된다.
비동기는 호출 시 Callback을 전달하여 작업의 완료 여부를 호출한 함수에게 답하게 된다. (Callback이 오기 전까지 호출한 함수는 신경 쓰지 않고 다른 일을 할 수 있음)
Blocking I/O & Non-Blocking I/O
1. Blcking I/O
I/O Blocking 형태의 작업은
(1) Process(Thread)가 Kernel에게 I/O를 요청하는 함수를 호출
(2) Kernel이 작업을 완료하면 작업 결과를 반환 받음.
- 특징
- I/O 작업이 진행되는 동안 user Process(Thread)는 자신의 작업을 중단한 채 대기
- Resource 낭비가 심함
(I/O 작업이 CPU 자원을 거의 쓰지 않으므로)
여러 Client 가 접속하는 서버를 Blocking 방식으로 구현하는 경우 -> I/O 작업을 진행하는 작업을 중지 -> 다른 Client가 진행 중인 작업을 중지하면 안 되므로, client 별로 별도의 Thread를 생성해야 함 -> 접속자 수가 매우 많아짐
이로 인해, 많아진 Threads로 스위칭 횟수가 증가함 비효율적인 동작 방식
2. Non-Blocking I/O
I/O 작업이 진행되는 동안 User Process의 작업을 중단하지 않음.
- 진행 순서
- User Process가 recvfrom 함수 호출 (커널에게 해당 Socket으로부터 data를 받고 싶다고 요청함)
- Kernel은 이 요청에 대해서, 곧바로 recvBuffer를 채워서 보내지 못하므로, "EWOULDBLOCK"을 return 함.
- Blocking 방식과 달리, User Process는 다른 작업을 진행할 수 있음.
- recvBuffer에 user가 받을 수 있는 데이터가 있는 경우, Buffer로부터 데이터를 복사하여 받아옴.
- 이때, recvBuffer는 Kernel이 가지고 있는 메모리에 적재되어 있으므로, Memory 간 복사로 인해, I/O보다 훨씬 빠른 속도로 data를 받아올 수 있음.
- recvfrom 함수는 빠른 속도로 data를 복사한 후, 복사한 data의 길이와 함께 반환함.
Spring
Bean Scope
Bean은 스프링에서 사용하는 POJO기반 객체이다.
상황과 필요에 따라 Bean을 사용할 때 하나만 만들어야 할 수도 있고, 여러 개가 필요할 때도 있고, 어떤 한 시점에서만 사용해야 할 때가 있을 수 있다.
이를 위해 Scope를 설정해서 Bean의 사용 범위를 개발자가 설정할 수 있다.
우선 따로 설정을 해주지 않으면, Spring에서 Bean은 Singleton으로 생성된다. 싱글톤 패턴처럼 특정 타입의 Bean을 딱 하나만 만들고 모두 공유해서 사용하기 위함이다. 보통은 Bean을 이렇게 하나만 만들어 사용하는 경우가 대부분이지만, 요구사항이나 구현에 따라 아닐 수도 있을 것이다.
Scope 종류
- singleton - 해당 Bean에 대해 IoC 컨테이너에서 단 하나의 객체로만 존재한다.
- prototype - 해당 Bean에 대해 다수의 객체가 존재할 수 있다.
- request - 해당 Bean에 대해 하나의 HTTP Request의 라이프사이클에서 단 하나의 객체로만 존재한다.
- session - 해당 Bean에 대해 하나의 HTTP Session의 라이프사이클에서 단 하나의 객체로만 존재한다.
- global session - 해당 Bean에 대해 하나의 Global HTTP Session의 라이프사이클에서 단 하나의 객체로만 존재한다.
MVC Framework
클라이언트가 서버에게 url을 통해 요청할 때 일어나는 스프링 프레임워크의 동작을 그림으로 표현한 것이다.
MVC 진행 과정
- 클라이언트가 url을 요청하면, 웹 브라우저에서 스프링으로 request가 보내진다.
- Dispatcher Servlet이 request를 받으면, Handler Mapping을 통해 해당 url을 담당하는 Controller를 탐색 후 찾아낸다.
- 찾아낸 Controller로 request를 보내주고, 보내주기 위해 필요한 Model을 구성한다.
- Model에서는 페이지 처리에 필요한 정보들을 Database에 접근하여 쿼리문을 통해 가져온다.
- 데이터를 통해 얻은 Model 정보를 Controller에게 response 해주면, Controller는 이를 받아 Model을 완성시켜 Dispatcher Servlet에게 전달해준다.
- Dispatcher Servlet은 View Resolver를 통해 request에 해당하는 view 파일을 탐색 후 받아낸다.
- 받아낸 View 페이지 파일에 Model을 보낸 후 클라이언트에게 보낼 페이지를 완성시켜 받아낸다.
- 완성된 View 파일을 클라이언트에 response 하여 화면에 출력한다.
구성 요소
Dispatcher Servlet
모든 request를 처리하는 중심 컨트롤러라고 생각하면 된다. 서블릿 컨테이너에서 http 프로토콜을 통해 들어오는 모든 request에 대해 제일 앞단에서 중앙집중식으로 처리해주는 핵심적인 역할을 한다.
기존에는 web.xml에 모두 등록해줘야 했지만, 디스패처 서블릿이 모든 request를 핸들링하면서 작업을 편리하게 할 수 있다.
Handler Mapping
클라이언트의 request url을 어떤 컨트롤러가 처리해야 할지 찾아서 Dispatcher Servlet에게 전달해주는 역할을 담당한다.
컨트롤러 상에서 url을 매핑시키기 위해 @RequestMapping을 사용하는데, 핸들러가 이를 찾아주는 역할을 한다.
Controller
실질적인 요청을 처리하는 곳이다. Dispatcher Servlet이 프런트 컨트롤러라면, 이곳은 백엔드 컨트롤러라고 볼 수 있다.
모델의 처리 결과를 담아 Dispatcher Servlet에게 반환해준다.
View Resolver
컨트롤러의 처리 결과를 만들 view를 결정해주는 역할을 담당한다. 다양한 종류가 있기 때문에 상황에 맞게 활용하면 된다.
SpringApplication
스프링 부트로 프로젝트를 실행할 때 Application 클래스를 만든다.
클래스명은 개발자가 프로젝트에 맞게 설정할 수 있지만, 큰 틀은 아래와 같다.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication 어노테이션을 통해 스프링 Bean을 읽어와 자동으로 생성해준다.
이 어노테이션이 있는 파일 위치부터 설정들을 읽어가므로, 반드시 프로젝트의 최상단에 만들어야 한다.
SpringApplication.run()으로 해당 클래스를 run 하면, 내장 WAS를 실행한다. 내장 WAS의 장점으로는 개발자가 따로 톰캣과 같은 외부 WAS를 설치 후 설정해두지 않아도 애플리케이션을 실행할 수 있다.
또한, 외장 WAS를 사용할 시 이 프로젝트를 실행시키기 위한 서버에서 모두 외장 WAS의 종류와 버전, 설정을 일치시켜야만 한다. 따라서 내장 WAS를 사용하면 이런 신경은 쓰지 않아도 되기 때문에 매우 편리하다.
'CS' 카테고리의 다른 글
HTTP 상태 코드 (2) | 2023.01.04 |
---|---|
5주차 CS 스터디 Operating System&Spring (1) | 2022.11.08 |
3주차CS스터디Network&Java (0) | 2022.10.14 |
2주차CS스터디Computer Architecture&Java (2) | 2022.09.28 |
1주차 CS스터디 Computer Architecture & Java (8) | 2022.09.21 |