**CORS (Cross-Origin Resource Sharing)**는 웹 브라우저에서 다른 도메인의 자원에 접근할 수 있도록 해주는 보안 메커니즘이야. 기본적으로 웹 브라우저는 보안상의 이유로 **동일 출처 정책(Same-Origin Policy)**을 적용해서, 다른 도메인, 프로토콜, 또는 포트에서 자원에 접근하는 것을 제한해. CORS는 이 제한을 완화하는 역할을 해.
**동일 출처 정책(Same-Origin Policy)**란?
동일 출처 정책은 웹 브라우저의 보안 정책 중 하나로, 한 출처에서 로드된 웹 페이지가 다른 출처의 자원에 접근하는 것을 제한하는 규칙이야. 여기서 **출처(Origin)**는 도메인, 프로토콜, 포트로 구성돼. 예를 들어, 다음 두 URL은 서로 다른 출처로 간주돼:
• http://example.com (프로토콜이 다름)
• https://api.example.com (도메인이 다름)
• https://example.com:8080 (포트가 다름)
CORS의 필요성:
동일 출처 정책은 보안을 위해 중요하지만, 실제 웹 애플리케이션 개발에서는 다른 도메인에서 데이터를 가져와야 할 때가 많아. 예를 들어, 프론트엔드 애플리케이션에서 외부 API를 호출하거나, 다른 서버에서 데이터를 가져올 때 말이지. 이때 CORS를 설정하면 다른 출처의 자원에 안전하게 접근할 수 있어.
CORS 동작 원리:
CORS는 HTTP 헤더를 사용해서 브라우저와 서버 간의 권한을 부여하는 방식으로 동작해. 서버는 요청을 보낸 도메인이 허용된 출처인지 확인하고, 맞으면 해당 요청을 처리하도록 응답해.
1. 클라이언트가 서버에 요청을 보낼 때, 웹 브라우저는 출처(Origin) 헤더를 포함해.
2. 서버는 이 요청을 받고, Access-Control-Allow-Origin 헤더를 통해 허용된 출처를 응답으로 보냄.
3. 만약 서버가 응답에서 허용된 출처를 지정하면, 브라우저는 자원을 사용할 수 있게 돼.
기본 요청 예시:
GET /api/data
Origin: https://mydomain.com
서버 응답:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://mydomain.com
CORS 요청 종류:
1. 단순 요청(Simple Request):
• GET, POST, HEAD 메서드로 요청하는 경우, 그리고 요청에 추가적인 헤더나 쿠키 등이 없을 때.
• 이 경우, 브라우저는 자동으로 요청을 보내고, 서버가 Access-Control-Allow-Origin 헤더로 응답하면 자원을 사용할 수 있어.
2. 프리플라이트 요청(Preflight Request):
• 브라우저가 안전하지 않은 요청(예: PUT, DELETE, 또는 커스텀 헤더 포함)이나 쿠키를 동반한 요청을 보내기 전에, 서버에 OPTIONS 메서드로 프리플라이트(preflight) 요청을 보내서 서버가 해당 요청을 허용하는지 미리 확인해.
• 프리플라이트 요청은 브라우저가 자동으로 보내며, 서버가 이를 승인해야 이후 실제 요청이 진행돼.
프리플라이트 요청 예시:
OPTIONS /api/data
Origin: https://mydomain.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type
서버 응답:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://mydomain.com
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Headers: Content-Type
CORS 요청 종류:
1. 단순 요청(Simple Request):
• GET, POST, HEAD 메서드로 요청하는 경우, 그리고 요청에 추가적인 헤더나 쿠키 등이 없을 때.
• 이 경우, 브라우저는 자동으로 요청을 보내고, 서버가 Access-Control-Allow-Origin 헤더로 응답하면 자원을 사용할 수 있어.
2. 프리플라이트 요청(Preflight Request):
• 브라우저가 안전하지 않은 요청(예: PUT, DELETE, 또는 커스텀 헤더 포함)이나 쿠키를 동반한 요청을 보내기 전에, 서버에 OPTIONS 메서드로 프리플라이트(preflight) 요청을 보내서 서버가 해당 요청을 허용하는지 미리 확인해.
• 프리플라이트 요청은 브라우저가 자동으로 보내며, 서버가 이를 승인해야 이후 실제 요청이 진행돼.
프리플라이트 요청 예시:
OPTIONS /api/data
Origin: https://mydomain.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type
서버 응답:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://mydomain.com
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Headers: Content-Type
3. 자격 증명 있는 요청(Credentialed Request):
• 쿠키나 HTTP 인증 정보 같은 **자격 증명(Credentials)**을 포함한 요청. 이 경우, 서버는 Access-Control-Allow-Credentials: true 헤더를 통해 자격 증명을 허용할 수 있어야 해.
자격 증명 있는 요청 예시:
GET /api/data
Origin: https://mydomain.com
Cookie: sessionId=1234
서버 응답:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://mydomain.com
Access-Control-Allow-Credentials: true
CORS 주요 헤더:
1. Access-Control-Allow-Origin:
• 요청을 허용할 출처(도메인)를 지정해. *를 사용하면 모든 출처에서의 요청을 허용할 수 있지만, 자격 증명이 포함된 요청에서는 사용할 수 없어.
2. Access-Control-Allow-Methods:
• 서버가 허용하는 HTTP 메서드(예: GET, POST, PUT, DELETE)를 지정해. 이 헤더는 프리플라이트 요청에 응답할 때 사용됨.
3. Access-Control-Allow-Headers:
• 클라이언트가 요청에 포함할 수 있는 허용된 헤더 목록을 지정해. 이 헤더 역시 프리플라이트 요청에서 사용돼.
4. Access-Control-Allow-Credentials:
• 자격 증명이 포함된 요청(예: 쿠키, 인증 정보)을 허용할지 여부를 지정해. true 값이 설정되면 허용됨.
5. Access-Control-Max-Age:
• 프리플라이트 요청에 대한 결과를 브라우저가 캐시할 시간을 초 단위로 설정해. 이 값이 클수록 프리플라이트 요청을 자주 보내지 않게 돼.
CORS의 장점:
1. 보안 강화:
• 동일 출처 정책과 함께 동작해서, 다른 도메인의 악의적인 요청을 막아줘.
2. 유연성 제공:
• 허용된 출처를 명시적으로 설정하여, 특정 출처에만 자원 접근 권한을 줄 수 있어. 이로 인해 개발자들은 외부 API나 여러 도메인 간의 협력을 안전하게 관리할 수 있어.
CORS 설정의 예시 (서버 측):
Node.js (Express):
const express = require('express');
const cors = require('cors');
const app = express();
// 모든 도메인 허용
app.use(cors());
// 특정 도메인만 허용
app.use(cors({
origin: 'https://mydomain.com',
credentials: true // 자격 증명 허용
}));
app.get('/api/data', (req, res) => {
res.json({ message: 'CORS 설정 완료!' });
});
app.listen(3000, () => {
console.log('서버가 실행 중입니다.');
});
Spring Boot:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.CrossOrigin;
@RestController
public class MyController {
@CrossOrigin(origins = "https://mydomain.com")
@GetMapping("/api/data")
public String getData() {
return "CORS 설정 완료!";
}
}
CORS 문제 해결 방법:
CORS와 관련된 문제는 보통 클라이언트가 허용되지 않은 출처에서 서버 자원에 접근하려고 할 때 발생해. 이를 해결하려면 서버 측에서 Access-Control-Allow-Origin 헤더를 올바르게 설정해 줘야 해.
• 클라이언트에서 요청할 때 CORS 오류가 발생하면, 서버에서 적절한 헤더를 설정했는지 확인해야 해.
• 서버가 요청을 허용하도록 설정이 되어 있지 않으면, 브라우저에서 CORS 정책 위반 오류가 발생할 수 있어.
요약:
• CORS는 웹 브라우저가 다른 출처의 자원에 접근할 때, 해당 요청을 서버가 허용할 수 있도록 해주는 보안 메커니즘이야.
• 서버는 Access-Control-Allow-Origin과 같은 CORS 헤더를 통해 클라이언트의 요청을 허용할 수 있어.
• CORS는 동일 출처 정책을 완화하면서도, 웹 애플리케이션의 보안을 유지해줌.
• CORS는 프리플라이트 요청을 통해 서버가 특정 요청을 허용할지 여부를 확인할 수 있는 과정을 포함해.
**웹소켓(WebSocket)**은 클라이언트와 서버 간의 양방향 통신을 가능하게 하는 프로토콜로, 웹 애플리케이션에서 실시간 데이터 전송을 효율적으로 처리할 수 있어. 웹소켓의 특징은 HTTP 기반의 요청-응답 방식과는 다르게, 한 번 연결이 성립되면 클라이언트와 서버가 지속적으로 데이터를 주고받을 수 있다는 것이야.
하지만, 웹소켓은 클라이언트와 서버 간의 통신뿐만 아니라 서버 간 통신에도 사용할 수 있어. 이로 인해, 서버들 간에 실시간 데이터를 동기화하거나 빠르게 처리해야 할 때 매우 유용해.
웹소켓의 주요 특징
1. 양방향 통신: 클라이언트와 서버, 서버와 서버 간 모두 양방향으로 데이터를 주고받을 수 있어. 서버에서 클라이언트로 데이터를 푸시(push)하거나, 클라이언트에서 서버로 요청하는 방식과 달리, 언제든지 데이터 전송이 가능해.
2. 실시간 데이터 전송: 웹소켓은 데이터 전송 시 **지연 시간(Latency)**이 적고, 실시간성이 중요한 애플리케이션(예: 실시간 채팅, 게임, 주식 거래 등)에 적합해.
3. 지속적인 연결: 클라이언트와 서버가 한 번 연결되면 그 연결을 유지하면서 데이터를 주고받기 때문에, 매번 새로운 연결을 만들 필요가 없어. 이는 네트워크 자원 절약에 매우 효율적이야.
4. 낮은 오버헤드: HTTP와 다르게, 웹소켓은 연결을 맺고 나면 데이터 전송에 필요한 헤더 정보가 최소화돼서, 불필요한 네트워크 자원을 낭비하지 않지.
서버 간 웹소켓 통신
웹소켓은 서버와 서버 간에도 통신할 수 있다는 점에서 매우 강력해. 두 서버가 실시간으로 데이터를 주고받아야 하거나, 빠르게 처리해야 할 때 서버 간의 웹소켓 통신이 유용해.
예를 들어, 여러 서버가 각각의 클라이언트 요청을 처리하고 그 결과를 실시간으로 다른 서버들과 공유해야 할 때, 웹소켓을 사용해 서버 간 통신을 원활하게 할 수 있어. 이 방식은 마이크로서비스 아키텍처나 실시간 데이터 분석에서 특히 유용하지.
웹소켓의 사용 사례
1. 실시간 채팅: 클라이언트와 서버가 웹소켓을 사용해 실시간으로 메시지를 주고받을 수 있어. 메시지가 발생할 때마다 서버는 즉시 다른 클라이언트에게 해당 메시지를 푸시할 수 있어.
2. 실시간 게임: 웹소켓은 빠르게 변하는 게임 환경에서 실시간으로 위치, 상태 등의 데이터를 교환하는 데 적합해.
3. 주식 거래: 주식 가격, 거래 내역 등을 실시간으로 업데이트하기 위해 서버 간, 또는 서버와 클라이언트 간에 웹소켓을 활용해 즉각적인 데이터 전송이 가능해.
4. IoT(사물인터넷): 다양한 IoT 장치가 서버와 실시간으로 통신하며 데이터를 주고받을 때 웹소켓이 유용해. 여러 장치에서 발생하는 데이터를 서버에 전달하고, 서버에서 이를 처리해 다시 장치로 실시간으로 피드백을 줄 수 있어.
웹소켓(WebSocket) 요약
특징설명
양방향 통신 | 클라이언트와 서버 간 양방향 실시간 통신이 가능. 클라이언트와 서버가 데이터를 자유롭게 주고받을 수 있음. |
실시간 데이터 전송 | 데이터 전송 시 지연 시간이 적고, 실시간 통신에 매우 적합함. 채팅, 게임, 주식 거래 등에서 사용. |
지속적인 연결 | 한 번 연결이 성립되면 클라이언트와 서버 간 연결을 유지하며, 매번 새롭게 연결하지 않음. |
낮은 오버헤드 | HTTP 요청과 달리, 헤더 정보가 작아 네트워크 자원을 절약할 수 있음. |
웹소켓 사용 사례
사례설명
실시간 채팅 | 클라이언트가 서버로 메시지를 보내고, 서버는 실시간으로 다른 클라이언트에 메시지를 전달함. |
실시간 게임 | 게임 내에서 실시간으로 위치나 상태 정보를 빠르게 교환해야 할 때 사용. |
주식 거래 | 실시간으로 주식 가격이나 거래 내역을 즉시 업데이트하는 데 사용. |
IoT | IoT 장치가 서버와 실시간으로 데이터를 주고받는 데 활용. |
웹소켓 vs HTTP 비교
항목웹소켓HTTP
통신 방식 | 양방향 통신 가능 | 단방향 요청-응답 |
연결 유지 | 지속적인 연결 | 요청 시마다 새로운 연결 |
헤더 오버헤드 | 작음 | 큼 |
실시간성 | 실시간 통신 가능 | 실시간 통신 어려움 (Polling 필요) |
웹소켓의 장단점
구분설명
장점 |
|
단점 |
|
서버 간 웹소켓 통신
특징설명
서버 간 실시간 데이터 처리 | 서버와 서버 간에도 양방향 실시간 데이터 통신이 가능함. |
마이크로서비스 통신 | 여러 마이크로서비스가 실시간으로 데이터를 동기화하거나 주고받을 때 사용됨. |
웹소켓과 HTTP의 차이점
웹소켓과 HTTP는 모두 웹 애플리케이션에서 사용되지만, 그 방식은 다르지:
• HTTP: 요청과 응답의 단방향 통신 방식. 클라이언트가 서버에 요청을 보내면 서버는 그 요청에 응답한 뒤 연결을 끊음.
• 웹소켓: 양방향 통신이 가능하며, 한 번 연결되면 그 연결이 지속돼. 서버는 클라이언트가 요청하지 않아도 실시간으로 데이터를 푸시할 수 있어.
웹소켓의 장단점
장점:
• 실시간 통신: 양방향 실시간 통신이 가능해, 빠르게 변하는 데이터를 처리해야 하는 애플리케이션에 적합해.
• 낮은 오버헤드: HTTP처럼 매번 헤더 정보를 주고받을 필요가 없어서, 네트워크 자원을 효율적으로 사용할 수 있어.
• 효율적인 네트워크 자원 사용: 웹소켓은 지속적인 연결을 통해 불필요한 재연결을 줄이고, 네트워크 부하를 줄일 수 있어.
단점:
• 서버 리소스 사용 증가: 지속적인 연결을 유지해야 하므로, 많은 클라이언트가 연결되면 서버의 리소스를 많이 사용하게 돼.
• 복잡한 서버 구현: HTTP 요청-응답 방식보다 복잡한 서버 구성이 필요해. 특히 서버가 많은 연결을 관리해야 하므로 적절한 리소스 관리가 필수적이야.
결론
웹소켓은 클라이언트와 서버, 서버와 서버 간 양방향 실시간 통신을 지원하는 강력한 프로토콜이야. 실시간 데이터 처리가 필수적인 애플리케이션에 적합하며, 연결 유지와 빠른 응답 속도를 통해 효율적인 네트워크 사용이 가능해. 서버 간 실시간 동기화, 마이크로서비스 간의 빠른 통신에도 활용될 수 있으며, HTTP보다 실시간성이 요구되는 애플리케이션에서 큰 장점을 제공해.
Base64는 이진 데이터(바이너리 데이터), 즉 010101010 같은 2진수 데이터를 텍스트로 변환하는 방식이야. 이진 데이터를 직접 전송하거나 저장하기 어려운 경우가 있어서, 이를 사람이 읽을 수 있는 텍스트 형식으로 변환해주는 거지.
Base64의 동작 방식:
1. 이진 데이터를 가져와서 8비트씩 잘라(예를 들어, 01010101 같은 8비트).
2. 이 8비트 데이터를 6비트씩 나눠서 각 6비트 데이터를 Base64의 문자로 변환해.
• 6비트는 0부터 63까지의 값을 표현할 수 있고, Base64는 이 값에 대응하는 64개의 문자(영문 대문자, 소문자, 숫자, +, /)를 사용해 변환해.
3. 남은 비트는 **패딩 문자 =**로 채워서 처리해.
이 과정을 통해 이진 데이터를 텍스트로 변환하게 되는 거야.
왜 Base64를 쓰는가?
1. 이진 데이터는 일부 시스템에서 직접 처리하기 어려울 수 있어(예: 이메일 전송, URL에 포함하는 경우 등). 그래서 Base64로 변환해 텍스트 형식으로 전송하거나 저장하면 안전하게 처리할 수 있어.
2. Base64로 인코딩하면 모든 데이터가 ASCII 문자로 변환되기 때문에 문자 기반 시스템에서 안정적으로 다룰 수 있게 돼.
예시:
만약 이진 데이터가 01000001(A의 ASCII 값)이라면, 이를 Base64로 변환하면 **텍스트 “A”**로 변환되는 방식이야.
정리:
• Base64는 이진 데이터를 텍스트로 변환하는 방식이야.
• 이를 통해 텍스트 기반 시스템에서도 이진 데이터를 안전하게 전송하거나 저장할 수 있어.
• 8비트 이진 데이터를 6비트씩 나누어, 64개의 ASCII 문자로 변환해 텍스트로 만들어.
'Network' 카테고리의 다른 글
HoL Blocking, Pipelining, Multiplexing (2) | 2024.10.10 |
---|---|
Https 프로토콜 (3) | 2024.09.27 |
Http 프로토콜 (6) | 2024.09.27 |
UDP 소켓 프로그래밍 (0) | 2024.09.26 |
TCP 소켓 프로그래밍 (0) | 2024.09.26 |