DAY 3

2024. 3. 2. 14:59

Network

OSI 7계층

1. 물리 계층(Physical)

  • 전기적 신호가 나가는 물리적인 장비
  • 단지 데이터를 전달할 뿐, 전송하려는(또는 받으려는) 데이터가 무엇인지, 어떤 에러가 있는지 등에 대해서는 신경쓰지 않는다.
  • 단지 데이터를 전기적인 신호로 변환해서 주고받는 기능만 있다.
  • 전송 단위 : 비트(Bit)
  • 장비 : 케이블, 허브

2. 데이터 링크 계층 **** 추가 학습 필요. 이더넷이란? 브릿지란? 어떻게 서로 연결? 허브란? 스위치와 라우터의 차이 등

  • 물리계층을 통해 송수신되는 정보의 오류와 흐름을 관리하여 안전한 정보의 전달을 수행할 수 있도록 도와주는 역할. 따라서 통신에서의 오류도 찾아주고 재전송도 하는 기능을 가지고 있다.
  • 맥(MAC) 주소를 가지고 통신한다.
  • 포인트 투 포인트(Point to Point)간 신뢰성 있는 전송을 보장하기 위한 계층으로 CRC 기반의 오류 제어와 흐름 제어가 필요하다.
  • 흐름 제어 : 송신 측과 수신 측의 속도 차이를 조정
  • 오류 제어 : 오류 검출과 회복
  • 순서 제어 : 프레임의 순서적 전송
  • 프레임 동기화 : 프레임의 시작과 끝을 구별하기 위한 동기화
  • 단위 : Frame
  • 장비 : 브릿지, 스위치, 이더넷

3. 네트워크 계층

  • 경로(Route)와 주소(IP)를 정하고 패킷을 전달해주는 역할
  • 목적지까지 가장 안전하고 빠르게 데이터를 보내는 기능. 최적의 경로를 설정해야 한다.
  • 즉, 이런 라우팅 기능을 맡고 있는 계층이 네트워크 계층이다.
  • 전송 단위 : 패킷

4. 전송 계층

  • 양 끝단의 사용자들 간의 신뢰성있는 데이터를 주고 받게 해주는 역할
  • 송신자와 수신자 간의 신뢰성있고 효율적인 데이터를 전송하기 위하여 오류 검출 및 복구, 흐름 제어와 중복 검사 등을 수행한다.
  • 데이터 전송을 위해서 Port 번호가 사용된다. 대표적인 프로토콜 TCP, UDP.
  • 전송 단위 : 세그먼트(Segment)

5. 세션 계층

  • 응용 프로세스가 통신을 관리하기 위한 방법을 정의한다.
  • TCP/IP 세션을 만들고 없애는 역할을 한다.
  • 통신 세션을 설정, 관리, 종료하는 역할을 한다.
  • 통신 세션을 시작하기 위한 필요한 절차를 수행한다. 핸드셰이크 절차를 포함할 수 있다.
  • 데이터 교환을 관리하며, 필요한 경우 통신을 동기화한다.
  • 세션을 종료하기 위한 절차를 수행한다. 핸드셰이크 절차를 포함할 수 있다.
  • 통신 중에 발생할 수 있는 예외 상황을 처리한다. 연결이 끊어진 경우, 세션 계층은 이를 감지하고 적절한 조치를 취할 수 있다.

6. 표현 계층

  • 전송하는 데이터의 표현 방식을 결정한다. (데이터 변환, 압축, 암호화 등)
  • GIF, JPEG, ASCII 등
  • 송신자에서 온 데이터를 해석하기 위한 응용계층 데이터 부호화, 변화
  • 수신자에서 데이터의 압축을 풀 수 있는 방식으로 된 데이터 압축
  • 데이터의 암호화와 복호화
  • 인코딩이나 암호화 등의 동작이 표현계층에서 이루어진다.

7. 응용 계층

  • 사용자와 가장 가까운 계층
  • 우리가 사용하는 응용 서비스나 프로세스가 응용계층에서 동작
  • HTTP, FTP 등의 프로토콜

TCP 3 way handshake & 4 way handshake

  • 상대와 연결되기 전에 가상 연결을 해서 패킷으로 보내서 확인하는 동작
  • 주의할 점은 진짜 연결된 것이 아니라, 논리적으로 연결이 된것이다. 실제로 연결된 것이 아니다.3-WAY-HANDSHAKE

3-WAY-HANDSHAKE

  1. SYN : 접속 요청
  2. SYN + ACK : 접속 요청 + 요청 수락
  3. ACK : ACK와 함께 데이터 전송 가능

4-WAY-HANDSHAKE

  1. FIN (클라이언트 -> 서버)
  2. ACK (서버 -> 클)
  3. FIN (서버 -> 클)
  4. ACK (클 -> 서버)

패킷을 순서대로 제어를 할 수 있는 이유는 TCP 데이터 안에 전송 제어, 순서, 정보들이 있기 때문이다.

 

TCP/IP 흐름제어 & 혼잡제어

흐름 제어(Flow Control)

  • 송신 측과 수신 측의 TCP 버퍼 크기 차이로 인해 생기는 데이터 처리 속도 차이를 해결하기 위한 기법
  • TCP 버퍼 : 송신 측은 버퍼에 TCP 세그먼트를 보관한 후 순차적으로 전송하고, 수신 측은 도착한 TCP 세그먼트를 애플리케이션이 읽을 때까지 버퍼에 보관한다.
  • 수신자가 처리할 수 있는 데이터 속도가 다르기 때문에, 송신 측은 수신 측의 데이터 처리 속도를 파악하고 얼마나 빠르게 어느 정도의 데이터를 전송할 지 제어
  • 슬라이딩 윈도우 방식을 사용
    • Window라는 데이터를 담는 공간을 동적으로 조절하여 데이터량을 조절
    • 수신 측이 한 번에 처리할 수 있는 데이터를 정해놓고 그때그때 수신 측의 데이터 처리 상황을 송신 측에 알려줘서 데이터의 흐름을 제어하는 방식.
    • 윈도우 크기는 수신 측에서 송신 측으로 확인 응답(ACK)를 보낼 때 TCP 헤더에 담아서 보낸다.

혼잡 제어(Congestion Control)

  • 네트워크가 불안정하여 데이터가 원활히 통신이 안되면 제어를 통해 재전송을 하게 되는데, 재전송 작업이 반복되면 네트워크가 붕괴될 수도 있다. 따라서 네트워크 혼잡 상태가 감지되면 송신 측의 전송 데이터 크기를 조절하여 전송량을 조절한다.
  • 데이터의 양이 라우터가 처리할 수 있는 양을 초과하면, 초과된 데이터는 라우터가 처리하지 못한다. 이때 송신 측은 손실 데이터로 간주하고 계속 재전송하여 네트워크를 혼잡하게 한다. 이와 같은 혼잡을 피하기 위하여 송신 측에서 보내는 데이터의 전송 속도를 강제로 줄인다. = 혼잡 제어
  • 흐름 제어는 송, 수신 측 사이의 패킷 수를 제어하는 기능이고
  • 혼잡 제어는 네트워크 내의 패킷 수를 조절하여 네트워크의 오버플로우를 방지하는 기능이다.
  • 호스트와 라우터를 포함한 보다 넓은 관점에서 전송 문제를 다룬다.
  • Tohoe, Reno, New Reno, Cubic 등 다양한 혼잡 제어 기법이 존재한다.

오류 제어(Error Control)

  • 통신 도중에 데이터가 유실되거나 잘못된 데이터가 수신되었을 경우 대처
  • Go Bank N 기법 : 어느 데이터로부터 오류가 발생하였는지 파악하여, 그 부분만 다시 순서대로 보내 제어한다.
  • Selective Repeat(선택적 재전송) 기법 : 에러난 데이터만 재전송하고 그 전에 받았던 순서가 잘못된 데이터 버퍼를 재정렬하여 제어한다.

UDP(User Datagram Protocol)

  • 데이터 전송 자체에만 초점을 맞추고 설계되었다.
  • UDP의 헤더에는 출발지와 도착지, 패킷의 길이, 체크섬 밖에 없다.
  • QUIC(Quick UDP Internet Connections)는 UDP를 기반으로 TCP + TLS + HTTP의 기능을 모두 구현한 프로토콜
  • DNS 서버에 대한 조회(대부분. 모두는 아님)
    • DNS는 데이터를 교환하는 경우이다. 이러한 경우 TCP를 사용하게 되면, 데이터를 송신할 때 세션 확립을 위한 처리를 해야하며, 송신한 데이터가 수신되었는지 점검하는 과정도 필요하기 때문에 UDP에 비해 프로토콜 오버헤드가 크다. 
    • TCP는 3WAYHAN가 있는 반면 UDP는 연결 설정에 드는 비용이 없다. DNS는 신뢰성보다 속도가 더 중요한 서비스이고, 연결 상태를 유지하지 않고 정보 기록을 최소화하여 많은 클라이언트를 수용할 수 있는 UDP가 더 적합하다.
    • TCP는 3WAYHAN을 통해 연결 상태를 유지하는 반면, UDP는 connection을 유지할 필요가 없다. 
    • DNS 응답이 UDP 패킷 하나에 담기지 않을 만큼 큰 경우나, DNS 존 전송 같은 특정 연산을 수행할때는 TCP 사용
  • 음성이나 동영상 데이터를 수신할 경우

프로토콜 : 클라이언트와 서버가 정보를 교환할 수 있도록 하는 메시지 형식에 대한 규칙.

 

 

 

Java

Error & Exception

논리 에러(Logic Error)

  • '버그'
  • 프로그램이 실행하고 작동하는데는 아무런 문제가 없는 오류지만, 결과가 예상과 달라 사용자가 의도한 작업을 수행하지 못하게 되어 서비스 이용에 지장 생길 수 있음
  • 컴퓨터 입장에서는 프로그램이 멀쩡히 돌아가는 것이니 에러 메시지를 알려주지 않는다. 따라서 개발자는 프로그램의 전반적인 코드와 알고리즘을 체크할 필요가 있다.

컴파일 에러(Compillation Error)

  • 컴파일러가 에러 메시지 출력
  • 대표적인 원인으로는 문법 구문 오류(syntax error)
  • 사실 컴파일 에러는 소스 코드를 javac.exe.로 컴파일 하는 과정에서 컴파일러가 전반적인 코드를 체크해서 에러 메시지를 보여주는 형태이지만, IDE에서는 일정주기로 계속 자동으로 컴파일을 해주기때문에 바로바로 문제를 알 수 있다

런타임 에러(Runtime Error)

  • 프로그램 실행 중에 에러가 발생해서 잘못된 결과를 얻거나, 혹은 외부적인 요인으로 기계적 결함으로 프로그램이 비정상적으로 종료
  • 실행 오류(런타임 에러)
  • 대체로 개발 시 설계 미숙(논리적)으로 발생하는 에러가 대부분이며, 런타임 에러 발생 시 프로그래머가 역추적해서 원인 확인해야 한다. 잠재적인 런타임 에러를 방지하기 위해서는 프로그램의 실행 도중 발생할 수 있는 경우의 수를 고려하여 이에 대한 대비를 철저히 해야 한다.

오류(Error)와 예외(Exception)

실행 시(runtime) 발생할 수 있는 오류를 error와 exception 두 가지로 구분한다.

error - 프로그램 코드에 의해서 수습될 수 없는 심각한 오류

exception - 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류

Error는 메모리 부족(OutOfMemoryError)이나 스택오버플로우(StackOverflowError)와 같이 일단 발생하면 복구할 수 없는 심각한 오류이고 예측이 불가능하다. 즉, 에러는 JVM 실행에 문제가 생긴 것이므로 개발자가 대처할 방법이 없다.

반면 Exception은 발생하더라도 수습될 수 있는 비교적 덜 심각한 오류를 말한다. 즉 알고리즘 오류로 Exception 예외가 계속 발생한다고 해도 Error처럼 프로그램이 죽거나 그럴 경우는 적다. 하지만 예외에 대한 오류 처리를 제대로 하지 않으면 전혀 예상하지 못한 오류 발생으로 프로그램에 작지 않은 문제를 야기한다.

대부분의 Exception은 개발자가 구현한 로직에서 발생한 실수나 사용자의 영향에 의해 발생한다. 그래서 예외는 에러와 달리 문제가 발생하더라도 이에 대한 대응 코드를 미리 작성해 놓음으로써 어느 정도 프로그램의 비정상적인 종료 혹은 동작을 막을 수 있다.

이 예외에 대한 대응 코드가 try - catch이다.

따라서 개발자는 예외 처리(exception handling)을 통해 언제나 예외 상황을 처리하여 프로그램이 종료되는 일이 없도록 코드의 흐름을 바꿀 필요가 있다.

 

자바에서는 오류를 Error와 Exception으로 나누었고 이들을 클래스로 구현하여 처리하도록 하였다.

JVM은 프로그램을 실행하는 도중에 예외가 발생하면 해당 예외 클래스로 객체를 생성하고서 예외 처리 코드에서 예외 객체를 이용할 수 있도록 해준다. getMessage()나 printStackTrace() 메서드 역시 예외 객체의 메서드를 가져와 오류를 출력하는 것이다.

 

Error 클래스는 외부적인 요인으로 인해 발생하는 오류이기 때문에 개발자가 대처할 수는 없다. 우리가 중점적으로 봐야할 클래스는 Exception 클래스이다.

 

* Throwable 클래스란?

  • 오류와 예외 모두 자바의 최상위 클래스인 Object를 상속받는다.
  • 그 사이에 Throwable 클래스와 상속관계가 있는데, Throwable 클래스의 역할은 오류나 예외에 대한 메시지를 담는 것이다. 대표적으로 getMessage() 와 printStackTrace() 메서드가 이 클래스에 속해 있다.
  • 당연히 Throwable을 상속받은 Error와 Exception 클래스에서도 위 두 메서드를 사용할 수 있게 된다.

자바에서 다루는 모든 예외 오류는 Exception 클래스에서 처리한다. 파란색 = 컴파일 에러, 빨간색 = 런타임 에러.

Unchecked Exception은 개발자의 충분한 주의로 미리 회피할 수 있는 경우가 대부분이라 그나마 상대적으로 미약한 예외로 처리되어 자바 컴파일러는 별도의 예외 처리를 하지 않도록 설계되어 있다.

 

Checked -> Unchecked 예외로 변환하기

  • 일일히 예외 처리 귀찮거나 오히려 가독성 해칠 경우
  • 별것 아닌 예외도 checked로 등록한 것이 많다.
  • 로직상 Runtime Exception으로 할 수 밖에 없는 경우
  • 연결된 예외(chained exception)을 이용해, checked 예외를 unchecked 예외로 바꾸면 예외처리가 선택적이 된다.

 

Stream API

  • 함수형 인터페이스(람다식)을 적용하여 컬렉션과 같은 저장요소를 반복적으로 처리할 수 있는 기능.
  • 원본의 데이터를 변경하지 않는다.
  • lazy하다. 필요할 때만 연산함으로 효율적인 처리 가능하다.
  • 재사용이 불가능하다.
  • 생성
    • 자바의 모든 Collection은 내부에 stream()이라는 메서드가 존재, 이 함수로 stream을 생성할 수 있다.
  • 중개연산
    • map, filter와 같이 stream을 return하는 함수들. stream을 리턴함으로, 중개연산은 메서드 체이닝이 가능하다. 중간 함수들 = 함수형 인터페이스 = 람다식 가능
  • 최종연산
    • 중개연산과는 달리 특정 자료형을 리턴하기에 stream api 연산을 이어서 할 수 없다.
  • 데이터의 시퀀스를 나타내며, 이 데이터에 대해 연산을 수행할 수 있는 기능을 제공.
  • 함수형 인터페이스를 기반으로 하므로, 람다 표현식이나 메서드 참조를 이용해 간결하고 가독성 높은 코드 작성 가능
  • 파이프 라이닝 : 여러 연산을 연결하여 하나의 표현식으로 표현 가능. 중간 결과 저장하거나 처리할 필요없이 원하는 최종 결과 얻을 수 있다.
  • 내부 반복 : 반복을 스트림이 내부에서 처리하며, 개발자는 반복에 대한 로직을 처리할 필요가 없다. 병렬 처리 쉽게함
  • 병렬 처리 : 멀티 코어 아키텍쳐를 활용한 병렬 처리를 지원함. parallel 메서드를 사용하면 스트림의 연산을 병렬로 수행할 수 있다.
  • 스트림의 연산은 함수형 인터페이스를 기반으로 하므로, 람다 표현식을 사용한다.

Record

  • 순수하게 데이터를 표현하는 간결하고 불변성을 가진 클래스를 선언하는데 사용됨.
  • 필드와 해당 필드에 접근하는 메서드, equals, hashcode, toString 메서드를 자동으로 생성해준다.
  • 불변성을 가진다. 즉, 한 번 생성된 Record의 필드 값을 변경할 수 없다.
  • 상속할 수 없으며, 필드를 추가하거나 메서드를 오버라이드 하는 것에 제한이 있다. 주로 데이터를 표현하는 데 사용되기 때문.

자바 빈즈 패턴과 Builder 패턴에 차이점

  1. 자바 빈즈 패턴 자바 빈즈 패턴은 객체의 속성을 설정하는 방식으로 객체를 생성하는 방법입니다. 기본 생성자를 통해 먼저 객체를 생성한 후, setter 메소드를 이용해 필요한 속성을 설정합니다. 이 패턴은 코드가 간결하고 이해하기 쉬우며, 개별 속성을 선택적으로 설정할 수 있다는 장점이 있습니다. 하지만, 객체가 생성되는 도중에는 일관성이 깨질 수 있으며(즉, 일부 속성만 설정된 상태가 될 수 있음), 불변 객체를 만들 수 없다는 단점이 있습니다.
  2. 빌더 패턴 빌더 패턴은 복잡한 객체를 생성하는 방법입니다. 빌더 객체를 통해 필요한 속성을 설정하고, 마지막에 build() 메소드를 호출하여 완성된 객체를 얻습니다. 빌더 패턴은 객체가 완전히 생성되기 전까지는 생성된 객체를 사용할 수 없으므로 객체의 일관성을 보장합니다. 또한, 빌더 패턴을 사용하면 불변 객체를 만들 수 있습니다. 하지만, 빌더 패턴을 사용하면 코드가 복잡해질 수 있습니다.

면접자님이 겪으신 N+1 문제와 구체적으로 어떠한 방법으로 해결

N+1 문제는 ORM(Object-Relational Mapping)을 사용할 때 발생하는 성능 이슈입니다. 예를 들어, 하나의 엔티티를 조회한 후, 이 엔티티와 관련된 다른 엔티티를 조회할 때, 관련된 엔티티 각각에 대해 별도의 쿼리를 실행하게 되면, 총 쿼리 수는 관련된 엔티티 수(N)에 1을 더한 값(N+1)이 됩니다.

 

이 문제를 해결하기 위한 방법 중 하나는 '조인 페치'입니다. 이는 관련된 엔티티를 처음에 함께 조회하는 방식으로, 한 번의 쿼리로 필요한 모든 데이터를 가져옵니다. 하지만, 이 방법은 필요 이상의 데이터를 가져오는 문제가 있을 수 있습니다.

 

또 다른 방법은 '배치 사이즈'를 설정하는 것입니다. 이는 관련된 엔티티를 한 번에 일정한 크기의 그룹으로 조회하는 방식입니다. 이렇게 하면 쿼리 수를 줄일 수 있지만, 적절한 배치 사이즈를 설정하는 것이 중요합니다.

 

 entity graph에 대해서 설명

Entity Graph는 JPA 2.1에서 도입된 기능으로, 엔티티를 조회할 때 연관된 엔티티까지 한 번에 조회하는 방법을 제공합니다. 이를 통해 N+1 문제를 효과적으로 해결할 수 있습니다.

 

Entity Graph는 '페치 조인'과 비슷하지만, 조회 대상이 되는 연관 엔티티를 동적으로 변경할 수 있다는 점에서 차이가 있습니다. 이를 통해 동일한 엔티티를 조회하는 다양한 상황에 대응할 수 있습니다.

 

실시간 양방향 통신에 대해 구현하셨다고 했는데 어떤 방식으로 구현하셨는지

실시간 양방향 통신을 구현하는 방법 중 하나는 WebSocket을 사용하는 것입니다. WebSocket은 HTTP와 달리 연결이 유지되는 프로토콜로, 서버와 클라이언트가 양방향으로 메시지를 주고받을 수 있습니다.

 

스프링에서는 @EnableWebSocketMessageBroker 어노테이션을 사용하여 WebSocket 메시지 브로커를 설정할 수 있습니다. 이를 통해 STOMP(단순 텍스트 지향 메시지 프로토콜) 기반의 메시지를 처리할 수 있습니다.

 

알고리즘을 꾸준히 하시는 것 같은데 자료구조 중 자신있는 내용

 

스프링 시큐리티에서 cors에러를 어떻게 대처

CORS(Cross-Origin Resource Sharing) 에러는 웹 페이지가 다른 도메인의 리소스에 접근하려 할 때 발생합니다. 스프링 시큐리티에서는 CorsConfigurationSource 또는 CorsFilter를 사용하여 CORS 정책을 설정할 수 있습니다.

 

예를 들어, HttpSecurity의 cors() 메소드를 사용하여 CORS를 활성화하고, CorsConfigurationSource를 제공하여 특정 도메인에서의 요청을 허용할 수 있습니다. 또는 CorsFilter를 사용하여 더 세밀한 CORS 설정을 할 수 있습니다.

 

'Question' 카테고리의 다른 글

DAY 4  (0) 2024.03.02
DAY 2  (0) 2024.02.16
DAY 1  (0) 2024.02.16

BELATED ARTICLES

more