Spring Cloud의 오픈소스. 

MSA의 기반 구조가 되는 Service Discovery 의 한 종류로 IP, PORT, ID값을 저장 / 관리하는 Rest 기반 미들웨어 서버.

 * Service Discovery : MSA에서 다수의 서비스 관리가 필요함에 따라 서비스 호출 경로 등의 정보들을 저장, 관리하는 것.  

  => 클라이언트가 서비스 호출 시 해당 서비스의 위치를 Eureka 에게 물어봄. (굳이 물어보는 이유? MSA에서는 서비스들의 IP와 PORT가 지속적으로 변함. 이를 관리하고 있는것이 Eureka 이기 때문.)

간단한 설정과 서비스별 LB(로드밸런싱) 이 가능한 장점.

 

Eureka 는 Server 와 Client로 나눔.

 - MSA 내 Client 서비스가 시작되면 유레카 Server  에 해당 Client 등록됨.

 - 주기적으로 ping으로 서버를 확인하며 리스트를 관리함.

 

 

특징

  • 인메모리 데이터베이스. : 메모리에 모든 데이터를 올려 동작하므로 빠른 처리가 가능함.
  • NoSQL 로서 key - value 형태의 데이터 구조를 가짐.
  • 다양한 형태의 자료구조 사용가능. : 개발 난이도가 낮아져 편의성 증대.

 

주 사용처

  • 캐싱 : 다른 DB 앞에 배치하여 빠른 응답시간과 RDB의 부담을 줄이는 역할.
  • 세션 관리 : TTL과 함께 빠른 key - value 스토어로 사용하여 손쉬운 세션관리.
  • 분산 환경에서의 이점 : 원격 시스템간 동일한 맵 형태의 데이터를 참고해야 할 때, 시스템 별 동기화가 어려운 문제가 있음. Redis 서버를 별도로 구축하여 값을 저장해두고 시스템마다 Redis 서버에서 값을 꺼내어 쓴다면 빠른 처리시간과 데이터 불일치 문제 해결 가능.

개요

PM2의 역할과 사용법을 간단하게 알아보자.

  • 목차
    • PM2란?
    • pm2 설치
    • pm2 명령어

 

PM2란?

공식 홈페이지에 나온 설명을 보면

PM2 is a daemon process manager that will help you manage and keep your application online. 요약하면 PM2는 어플리케이션의 관리와 온라인상태를 유지하도록 돕는 역할을 하는 데몬 프로세스 관리자 라고 한다.

PM2 장점

  • 어플리케이션의 예상치 못한 종료시 자동 재시작
  • 배포시에도 무중단 서비스
  • 클러스터 모드
  • 모니터링

 

PM2 설치

$ npm install pm2@latest -g

또는

$ yarn global add pm2

위 명령어로 최신버젼을 설치할 수 있다.

 

PM2 명령어

이 명령어로 간단한 pm2의 사용예를 볼 수 있다.

pm2 examples

 

서버 시작

app.js 라는 소스가 있다는 가정하에

$ pm2 start app.js

이 명령어 한 줄로 쉽게 서버를 데몬화 하고 모니터링 할 수 있다.

 

프로세스 관리

$ pm2 restart app_name
$ pm2 reload app_name
$ pm2 stop app_name
$ pm2 delete app_name

app_name 대신에 all 이나 id 를 사용할 수 있다.

  • all : 모든 프로세스를 실행한다.
  • id : 특정 프로세스 id만 실행한다.

 

목록 보기

$ pm2 [list|ls|status]

 

로그 보기

$ pm2 logs // 기본 15줄의 로그가 보인다.

$ pm2 logs --lines 200 // 여러줄을 보고 싶을 경우 --lines 옵션을 사용한다.

실시간 로그도 간단한 명령어 하나로 확인 가능하다.

 

모니터링

$ pm2 monit

이 명령어로 대쉬보드 형태로 모니터링도 가능하다.

클러스터 모드

pm2를 클러스터 모드로 실행하지 않으면 fork 모드로 실행이 되는데 fork모드는 싱글스레드로만 동작한다.
pm2의 장점인 멀티 스레드를 활용하기 위해 클러스터 모드로 실행해보자.

  • 클러스터 옵션
    --watch : PM2가 어플리케이션 변경사항을 자동으로 감지하여 서버를 재시작함
    -i (코어수) : 클러스터 모드로 실행할 시 사용할 코어수. max 로 적을시 cpu 코어 수 만큼 할당됨
    --name : 어플리케이션 이름
    --log (경로) : 로그 파일 경로
    -- arg1 arg2 arg3 : 스크립트에 전달 될 파라미터
    --restart-delay (딜레이 시간) : 재시작시 딜레이 시간 지정 (ms)
    --no-autorestart : 재시작 불가능하도록 설정함
    

클러스터를 더욱 편하게 관리하기 위해 전용 설정파일을 이용할 수도 있다.

$ pm2 ecosystem
File C:\ecosystem.config.js generated

위 명령어는 자동으로 ecosystem.config.js 파일을 생성한다.
이 파일에서 클러스터 옵션들을 설정하여 사용할 수 있다.

// ecosystem.config.js 설정 예
module.exports = {
  apps : [{
    name   : "app1",
    script : "./app.js",
    env_production: {
       NODE_ENV: "production"
    },
    env_development: {
       NODE_ENV: "development"
    }
  }]
}

ecosystem.config.js 을 실행하는 것으로 해당 옵션이 실행된다.

하단에는 간단히 적은 옵션들.

  • General
    • name : “my_app” // 어플리케이션 명칭
    • script : “./api/app.js” \/\/ pm2 시작 스크립트 경로
    • cwd : “/var/www/” // 앱이 실행될 디렉토리
    • args : “-a 13 -b 12” // CLI에서 실행하는 모든 아규먼트
    • interpreter : “/usr/bin/python” // 인터프리터 경로 (기본값은 node)
    • interpreter_args : “–harmony” // 인터프리터 파라미터 옵션
    • node_args : // interpreter_args 의 별칭
  • Advanced features
    • instances : 0 // 인스턴스 수. 0이면 CPU 코어수만큼.
    • exec_mode : “cluster” // cluster 또는 fork 모드 선택. 기본은 fork 모드
    • watch : true // 폴더 혹은 하위 폴더를 감시하여 변경시 어플리케이션 reload
    • ignore_watch : [”[\/\]./”, “node_modules”] // watch 제외경로
    • max_memory_restart : “150M” // 설정한 메모리를 초과하면 자동으로 어플리케이션 재시작
    • source_map_support : true // 소스 맵 파일의 활성화/비활성화 설정. 기본값은 true
  • Log files
    • log_date_format : “YYYY-MM-DD HH:mm Z” // 로그 날짜 포멧
    • error_file : // 에러로그 파일 경로 (기본 경로는 $HOME/.pm2/logs/-error-.log)
    • out_file : // 로그 파일 출력 경로 (기본 경로는 $HOME/.pm2/logs/-out-.log)
    • log_file : // error_file, out_file 두 파일의 경로. 기본은 비활성화
    • pid_file : // pid 파일경로 (기본 경로는 $HOME/.pm2/pids/-.pid)
  • Control flow
    • min_uptime : // 어플리케이션이 시작되었다고 생각하는 최소 시간
    • listen_timeout : 8000 // 강제 reload가 일어나기 전 대기시간(ms)
    • kill_timeout : 1600 // 최종 SIGKILL 을 보내기 전 대기시간(ms)
    • shutdown_with_message : false // 어플리케이션 종료 수행 시 process.kill(pid, SIGINT) 명령어 대신 process.send(‘shutdown’)로 수행
    • wait_ready : false // Reload 대기 이벤트 대신 어플리케이션의 process.send(‘ready’) 를 기다린다
  • Deployment
    • key : SSH key path. Default $HOME/.ssh
    • user : SSH user
    • host : SSH host
    • ssh_options : SSH options with no command-line flag, see ‘man ssh’
    • ref : GIT remote/branch
    • repo : GIT remote
    • path : path in the server
    • pre-setup : Pre-setup command or path to a script on your local machine
    • post-setup : Post-setup commands or path to a script on the host machine
    • pre-deploy-local : pre-deploy action
    • post-deploy : post-deploy action

그 외 옵션 링크

개요

Spring Cloud OpenFeign에 관해 간단하게 알아보자.

  • 목차
    • OpenFeign 이란?
    • 기본설정
    • 사용법
    • 기타설정
  •  

 

OpenFeign 이란?

  • 외부 API 호출을 쉽게할 수 있도록 도와주는 HTTP 클라이언트 도구로 어노테이션으로 손쉽게 구현가능하다. Spring Cloud에서 Open Feign을 스프링 클라우드로 통합하였다.

 

기본설정

  • spring-cloud-dependencies 와 openfeign 의존성 추가를 해준다.
// Gradle 기준 예시
compile("org.springframework.cloud:spring-cloud-dependencies:Finchley.SR3")
compile("org.springframework.cloud:spring-cloud-starter-openfeign:2.1.4.RELEASE")
  • Application 파일에 @EnableFeignClients 어노테이션을 추가해준다.
@SpringBootApplication
@EnableFeignClients	// 요거 추가 필요.
public class WebApplication {
	public static void main(String[] args) {
		SpringApplication.run(WebApplication.class, args);
	}
}

 

사용법

jpa 사용법과 유사하다.

interface 를 만들고,
@FeignClient 어노테이션을 정의하고
호출하기만 하면 된다.

// 동일한 도메인을 이용하는 여러 API의 경우 @FeignClient URL 속성에 공통부분을 적어주고, 
// interface 내부에 메서드를 정의할 때 개별 url 뒷부분의을 적어주면 이용 가능하다.
@FeignClient(name = "testApi", url = "https://api.test.com", configuration = TestApi.Configuration.class)
public interface TestApi {
	@GetMapping(value = "/abc/auth", headers = "Accept=application/json")	
	String getAuth(@RequestHeader("aaa") String param1, @RequestHeader("bbb") String param2);	// 헤더에 들어갈 파라미터를 정의할 수도 있다.


	@GetMapping(value = "/def/select", headers = "Accept=application/json")
	List<UserDao> getSelect(@SpringQueryMap UserDao param);

	// interface 내에 설정을 정의할 수도 있다.
	class Configuration {
		@Bean
		Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> converters) {
			return new SpringFormEncoder(new SpringEncoder(converters));
		}
	}
}

위 클래스 안의 메서드를 호출하기만 하면 API 통신이 가능하다.

 

기타설정

타임아웃 설정

OpenFeign 이 제공하는 타임아웃은 두 종류가 있다.

  • connectTimeout: 1000
  • readTimeout: 30000

시간은 ms 기준으로, 1000 = 1초 이다.

설정은 properties 파일과 java Configuration 에서도 가능하며, properties가 우선순위를 가진다.
각 클라이언트 별로 다른 설정이 필요하면 @FeignClient 에 직접 Configuration을 설정하면 된다.

#yml 사용 예
feign:
   client:
      config:
         default:
            connectTimeout: 15000
            readTimeout: 15000

로그설정

로그는 각각의 Feign client 마다 만들어지며 기본적으로 로그의 이름은 Feign client를 사용하는 인터페이스 명이다. Feign logging 은 오직 DEBUG level 에서 동작한다.

  • NONE : 로그 없음 (기본)
  • BASIC : 요청 메서드와 URL, 응답 상태코드와 실행 시간만 남긴다.
  • HEADERS : 요청, 응답 헤더와 가본정보들만 남긴다.
  • FULL : 헤더, 바디, 요청과 응답의 메타 데이터 모두 남긴다.

다음은 full 속성으로 로그를 설정한 예제이다.

@Configuration
public class FooConfiguration {
	@Bean
	Logger.Level feignLoggerLevel() {
		return Logger.Level.FULL;
	}
}

개요

실무에 필요한 HTTP 핵심 기능과 HTTP API설계 방법을 학습한다.

  • 목차
    • HTTP 정의
    • HTTP의 비연결성 (Connectionless)
    • HTTP(Protocol) 오버헤드
    • HTTP의 무상태성 (Stateless)
    • HTTP 통신의 구성 요소
    • HTTP 상태 코드
    • HTTP 메서드 종류와 특징
    • HTTP 캐싱
    • HTTP 쿠키
    • CORS(Cross-Origin Resource Sharing)

HTTP 정의

HTTP(Hypertext Transfer Protocol)란?

  • 인터넷에서 데이터를 주고 받을 수 있는 텍스트 기반의 통신 규칙 또는 프로토콜. -> 인터넷 통신규칙

HTTP 동작방식

  • “요청” 과 “응답” 메세지로 대응되는 구조로서 클라이언트는 특정 형식의 요청 메서드, URI 와 request modifiers, 클라이언트 정보, body contents를 포함한 MIME 타입의 프로토콜 버전을 서버로 전송한다. 서버는 프로토콜 버전, 상태 코드, 상태 메세지, 서버정보, 구성 메타정보와 응답 본문을 포함하여 응답한다.

 

HTTP의 비연결성 (Connectionless)

  • 클라이언트와 서버가 한 번 연결을 맺은 후, 클라이언트 요청에 대한 응답을 마치면 연결을 끊어 버리는 특성. HTTP는 불특정 다수의 통신 기반으로 설계되어 있으므로 연결 유지를 위한 리소스를 줄여 더 많은 유저의 요청을 처리할 수 있다는 장점을 가지게 됨.

 

HTTP(Protocol) 오버헤드

  • 네트워크를 통해 대상으로 라우팅되는 데이터와 함께 전송되어야하는 정보를 말하며, 올바른 대상에 도달하기 위해 전송중인 데이터에 추가로 보내지는 정보.
  • 통상 패킷/프레임 등의 선두에 있는 헤더(Header) 상에 위치하므로 Header 라고도 함.
  • 전송 기능 자체는 내가 보내고자 하는 대상에게 제대로 도착했는지를 확인하지 않는다. “보내다” 라는 행위의 본질은 아니지만 원하는 대상을 정확히 찾아내어라는 간접적인 처리를 프로토콜 오버헤드를 통해 하는 것.
  • 전송중인 데이터와 관련없는 정보들이 담겨 있지만 출발지 및 도착지 주소와 같이 주 기능을 보완해 줄 수 있는 정보들이 담겨있음. -> 정보 전송의 신뢰성 상승 및 안정적 시스템 운용 가능.
  • 오버헤드에 관한 정보통신기술용어해설에 기술된 정의
    • 목적
    • 정보 전송의 신뢰성 확보 및 시스템의 안정적 운용 등을 위함
    • 성격
    • 실제 운반되는 정보(페이로드)에 추가되는 성격의 운용 및 유지보수를 위한 신호
    • 담겨진 정보
    • 각 전송 구간별 페이로드의 종류,형태, 출발지 및 도착지 주소, 운용 유지보수 정보 등
    • 위치
    • 통상, 오버헤드는 패킷/프레임 등의 선두에 있는 헤더(Header) 상에 위치함

 

HTTP의 무상태성 (Stateless)

  • Connectionless로 인해 클라이언트를 식별할 수 없는 상태. -> 요청에 대한 응답을 처리한 후 연결을 끊어버린 서버가 클라이언트의 이전 상태를 알 수 없는 현상을 말함.
    • cookie, session, token 으로 상태를 기억하여 단점을 보완함.

 

HTTP 통신의 구성 요소

  • 클라이언트 (user Agent) : 사용자를 대신해 요청을 보내는 일을 수행
  • 서버 (server) : 클라이언트가 요청하게 되는 대상으로, 개발자가 특정 기능을 수행하도록 설계해 놓은 코드를 실행하여 클라이언트에게 정보를 제공함.
  • 프록시 (proxy) : 서버와 클라이언트 사이의 중계 역할을 함. 동일 프로토콜로 연결하며 캐싱, 필터링, 로드 밸런싱, 인증, 로깅 역할 수행
  • 참고. 중계역할을 하는 요소들
    • 게이트웨이 (gateway) : 프록시 처럼 중계 역할을 하나, HTTP 프로토콜 이외 기능 수행 (프로토콜 변환 등)
    • 릴레이 (relay) : 단순 프록시 (단순 중계)역할만 함

 

HTTP 상태 코드

클라이언트가 서버에 요청을 하면, 서버는 요청에 대한 처리 상태를 숫자로 반환하는 것

  • 상태코드의 분류
    • 1XX: Informational(정보 제공) 요청이 수신되어 처리중이라는 의미.
    • 2XX: Success(요청 성공) 클라이언트의 요청이 서버에서 성공적으로 처리되었다는 의미.
    • 3XX: Redirection(리다이렉션) 완전한 처리를 위해서 추가 동작이 필요한 경우로 주로 서버의 주소 또는 요청한 URI의 웹 문서가 이동되었으니 그 주소로 다시 시도하라는 의미.
    • 4XX: Client Error(클라이언트 에러) 없는 페이지를 요청하는 등 클라이언트의 요청 메시지 내용이 잘못된 경우를 의미.
    • 5XX: Server Error(서버 에러) 서버 사정으로 메시지 처리에 문제가 발생한 경우입니다. 서버의 부하, DB 처리 과정 오류, 서버에서 익셉션이 발생하는 경우를 의미.
  • 주요 상태코드
    • 200 : 서버가 요청을 제대로 처리함
    • 400 : 잘못된 요청 (주로 헤더 포멧이 HTTP 규약에 맞지 않을 경우)
    • 401 : 권한 없음 (지정한 리소스에 대한 접근권한 없음)
    • 403 : 금지됨 (지정한 리소스에 대한 접근 금지. 서버가 요청을 거부하고 있다는 의미)
    • 404 : 찾을 수 없음 (요청한 자원이 서버에 존재하지 않음)
    • 500 : 내부 서버 오류 (서버에 에러가 발생한 것을 의미)
    • 503 : 서비스 불가능 (주로 Proxy 장비에서 서버에 서비스가 불가능할 때 사용됨)

 

HTTP 메서드 종류와 특징

GET - Cacheable

  • 조회를 목적으로 사용하는 메서드. 데이터를 읽거나(Read) 검색(Retrieve)할 때 사용함.

POST

  • 서버로 데이터를 전송할 때 사용하는 메서드. 본문 유형은 Content-Type 헤더로 나타냄.
  • POST 요청은 보통 HTML form을 통해 서버에 전송하며, 서버에 변경사항을 만듬(멱등성이 없음).
  • 신선도 정보 포함시에만 캐싱

PUT

  • 데이터 갱신, 작성시 사용하며 주로 수정 시 사용하는 메서드.(모든 자원이 변경되므로 주의)
  • PUT은 한 번을 보내도, 여러 번을 연속으로 보내도 같은 효과를 보임(멱등성이 있음).

DELETE

  • 지정한 리소스의 삭제를 목적으로 함.

HEAD - Cacheable

  • 서버 리소스의 헤더(메타 데이터)의 취득이 목적으로 특정 리소스를 GET 메서드로 요청했을 때 돌아올 헤더를 요청함.

OPTIONS

  • URL 또는 서버에 대해 허용된 통신 메서드를 요청함. 클라이언트는 이 방법으로 URL을 지정하거나 “*” 을 지정하여 전체 서버 참조 가능.
  • CORS 사전 요청시 OPTIONS 로 요청함.

PATCH

  • 리소스의 일부분을 수정시 사용함.
  • PUT 과는 달리 일부의 자원만 수정 가능.

CONNECT

  • 요청한 리소스에 대해 양방향 연결을 시작하는 메소드로 터널을 열기 위해서 사용될 수 있음.
  • SSL을 사용하는 웹사이트에 접속하는데 사용될 수 있음. 1) 클라이언트는 원하는 목적지와의 TCP 연결을 HTTP 프록시 서버에 요청 2) 서버는 클라이언트를 대신하여 연결 생성 3) 한번 서버에 의해 연결이 수립되면, 프록시 서버는 클라이언트에 오고가는 TCP 스트림을 계속 프록시 함.

TRACE

  • 클라이언트와 목적지 서버 사이에 있는 모든 HTTP 애플리케이션의 요청/응답 연쇄를 따라가면서 자신이 보낸 메시지의 이상 유무 파악 가능함.

 

HTTP 캐싱

  • 한 번 가져온 데이터를 가까운 곳에 저장해 두고 다음번에 다시 먼 곳에서 그것을 가져올 필요 없이 저장해둔 것을 사용하는 일종의 성능 향상 기법
  • HTTP 응답을 저장해 두고 다음번에 동일한 HTTP 요청이 시도되면 저장해 둔 HTTP 응답을 재활용.
  • HTTP 응답을 저장해 두는 저장소
    • 사설 캐시(Private Cache). 지역 캐시(Local Cache)라고도 부름.
      • 한 사용자에 의해서만 재활용될 수 있는 것들이 저장되는 저장소. 최초의 HTTP 요청은 서버에게 전송되어 HTTP 응답을 받아오게 되고, 이를 사설 캐시에 저장해 두면 다음번에 동일한 HTTP 요청이 시도될 때는 서버에 해당 HTTP 요청을 다시 보내지 않고 저장되어 있는 HTTP 응답을 재활용하게 된다. 대표적인 사설 캐시로는 브라우저 캐시가 있다. 브라우저 캐시는 기본적으로 사용자가 HTTP 요청을 통해 다운로드한 모든 문서들을 저장하고 있다. 이렇게 저장된 문서들은 뒤로 가기 혹은 앞으로 가기를 할 때, 문서 저장을 할 때, 페이지 소스 보기를 할 때 등의 경우에 재활용이 된다.
    • 공유 캐시(Shared Cache).
      • 여러 사용자들에 의해 재활용될 수 있는 것들이 저장되는 저장소. 최초의 HTTP 요청은 공유 캐시를 거쳐 서버에게 전송되어 HTTP 응답을 받아오게 되고, 이를 공유 캐시에 저장해 두면 다음번에 동일한 HTTP 요청이 공유 캐시에게 전달될 때 서버에 해당 HTTP 요청을 다시 보내지 않고 저장되어 있는 HTTP 응답을 클라이언트에게 반환하게 된다. 대표적인 공유 캐시로는 프록시 캐시가 있다. ISP 혹은 회사 측에서 로컬 네트워크 인프라의 일부로서 구축해둔 웹 프록시가 이러한 역할을 담당할 수 있다. 그러면 자주 사용되는 데이터들의 경우에 네트워크 트래픽을 최소화하여 많은 구성원들이 해당 데이터를 효율적으로 사용할 수 있게 되는 것이다.

 

HTTP 쿠키

HTTP 쿠키란?

  • 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각. 브라우저는 그 데이터 조각들을 저장해 놓았다가, 동일한 서버에 재 요청 시 저장된 데이터를 함께 전송.
  • 쿠키는 stateless 한 HTTP 통신에서 클라이언트에게 정보(표시)를 주어 해당 클라이언트를 식별하기 위한 목적으로 만들어짐.

HTTP 쿠키 특징

  • 쿠키는 한개에 4KB 까지 저장 가능하며, 최대 300개 까지 저장할 수 있다.
  • 쿠키는 클라이언트에 저장된다.
  • 쿠키에는 이름, 값, 만료날짜, 경로 정보가 들어있다.
  • 기본적으로 쿠키는 웹 브라우저가 종료되면 삭제된다. (만료날짜를 지정해 주면 만료일이 되야 삭제된다.)
  • 웹 브라우저에 해당 서버의 쿠키 정보가 있으면 HTTP 요청 (HTTP 헤더의 Cookie)에 무조건 담아 보낸다.

HTTP 쿠키 동작방식

요청을 받은 서버에서 쿠키를 클라이언트(웹 브라우저)로 보내고 클라이언트는 쿠키를 받으면 도메인 서버 이름으로 정렬된 쿠키 디렉토리에 쿠키(정보)를 저장한다.
이후 클라이언트가 동일한 서버로 HTTP 요청을 보내면 저장된 쿠키도 같이 전송되며, 만약 서버에서 쿠키에 업데이트된 내용이 있으면 응답할 때 다시 업데이트된 쿠키를 보내준다.

HTTP 쿠키 보안

  • Secure
    쿠키는 기본적으로 http, https를 구분하지 않고 전송함.
    Secure 옵션을 적용하면 https인 경우에만 쿠키를 전송하게 됨.
  • HttpOnly 해당 옵션 적용 시 자바스크립트에서 document.cookie 접근이 불가능 하게 되며, HTTP 전송에만 사용 가능하게 됨.
  • SameSite
    • Strict : 동일한 도메인에서만 쿠키 전송 허용
    • Lax : 기본적으로는 Strict과 동일하지만 safe한 요청(http get 방식, anker tag, 를 통한 접근은 허용
    • None : 모든 전송 허용. 보안에 취약하므로 주로 https 프로토콜에 secure 속성과 함께 사용.

 

CORS(Cross-Origin Resource Sharing)

CORS 란?

  • 교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 말 그대로 다른 출처의 리소스 공유에 대한 허용 / 비허용 정책을 말함.
  • 웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행함.
  • <img>, <video>, <script>, <link> tag 등은 기본적으로 Cross-Origin 정책을 지원함.
  • XMLHttpRequest나 Fatch API는 same-origin 정책을 따르므로 Cross-Origin 불가 (보안상의 이유로 브라우저에서는 내부에서 작성된 cross-origin HTTP를 제한하고 있음.)

브라우저의 CORS 동작방식

  1. 클라이언트에서 HTTP request header에 Origin을 담아 전달
  2. 서버는 응답헤더에 Access-Control-Allow-Origin 을 담아 클라이언트로 전달
  3. 클라이언트에서 Origin과 서버가 보내준 Access-Control-Allow-Origin을 비교 후 유효하지 않다면 CORS 에러 발생

CORS 작동 방식 3가지

  1. 예비 요청 (Preflight Request): 본 요청을 보내기 전에 브라우저 스스로 안전한 요청인지 확인하기 위해 OPTIONS 메서드를 이용하여 예비 요청을 보내는 것. - 예비 요청에 대한 응답으로 서버로부터 허용, 금지에 대한 헤더 정보를 받게 됨. 브라우저는 해당 요청이 안전한지 확인 한 후 본 요청을 보냄.
  2. 단순 요청 (Simple Request) : 예비 요청(Prefilght)을 생략하고 바로 서버에 본 요청을 보낸 후, 서버가 Access-Control-Allow-Origin 헤더를 응답해주면 브라우저가 CORS정책 위반 여부를 검사하는 방식.
    - 3가지 경우를 만족할 때만 가능
    1) 요청의 메소드는 GET, HEAD, POST 중 하나여야 함.
    2) 요청이 Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width 헤더일 경우 에만 가능.
    3) Content-Type 헤더가 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나여야 함.
  3. 인증된 요청 (Credentialed Request) : 클라이언트에서 서버로 요청을 보낼 때 자격 인증 정보(Credential)를 함께 전달하는 것.
    • 자격 인증 정보란 세션 ID가 저장되어있는 쿠키(Cookie) 혹은 Authorization 헤더에 설정하는 토큰 값 등
	/* 
	 * 클라이언트 설정 
	 * request 요청 script에서 credentials 옵션을 설정해 준다. 
	 */
	// credentials 설정 옵션 값 
	same-origin (기본값) : 같은 출처 간 요청에만 인증 정보 전송 가능
	include	: 모든 요청에 인증 정보 전송 가능
	omit : 모든 요청에 인증 정보 전송 불가

	// 서버 설정   
	Access-Control-Allow-Credentials : true
	Access-Control-Allow-Origin : "*" 불가
	Access-Control-Allow-Methods : "*" 불가
	Access-Control-Allow-Headers : "*" 불가

 

CORS 해결책

  • 서버 문법에 맞게 Access-Control-Allow-Origin 헤더값에 허용할 출처 설정
  • 프록시 서버 직접 구축
  • 서버에서 직접 통신 구현

+ Recent posts