0%

frontend - api cross domain 해결

frontend 와 backend api 통신에 있어 크로스도메인 이슈가 발생할 수 있습니다.

CORS: Cross Origin Resource Sharing

그러나 이 문제는 몇가지 방법으로 쉽게 해결할 수 있습니다.

  1. Access-Control-Allow-Origin
  2. Reverse Proxy

Access-Control-Allow-Origin

응답헤더 Access-Control-Allow-Orign 에 CORS 를 허용해줄 도메인을 지정하여 해결할 수 있습니다.

springboot

@CrossOrigin 어노테이션

controller 또는 method 상단에 @CrossOrigin 어노테이션을 선언하여 처리 합니다.
기본값은 * 로 모든 도메인을 허용합니다.

1
2
3
4
5
6
@CrossOrigin
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<List<Todo>> todos() {
List<Todo> todos = todoRepository.findAll(new Sort(Sort.Direction.DESC, "id"));
return ResponseEntity.ok(todos);
}

특정 도메인만을 처리하려 할 경우 아래와 같이 개별 설정이 가능합니다.

1
@CrossOrigin(origins = "http://domain.com, http://domain.co.kr")

Global CORS 설정

URI Path 를 지정하여 처리할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.todo.api.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/todos/**");
}
}

nodejs express

1
npm install cors
1
2
3
4
5
6
7
8
9
10
11
12
13
var express = require('express')
var cors = require('cors')
var app = express()

app.use(cors())

app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})

app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})

https://expressjs.com/en/resources/middleware/cors.html

Nginx reverse proxy

Reverse proxy 를 활용해 같은 도메인내에서 Frontend 와 API를 분기하여 사용할 수 있습니다.

IP domain
proxy 211.10.10.1 todos.com
frontend 211.10.10.2
API 211.10.10.3

nginx conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
http {
...

upstream frontend {
server 211.10.10.1:80;
}

upstream api {
server 211.10.10.2:80;
}

server {
listen 80;
server_name todos.com;

location /api/ {
proxy_pass http://api/;
}

location / {
proxy_pass http://frontend/;
}
}
}

fetch

http://todos.com 에서 API 를 사용할때 아래와 같이 호출할수 있습니다.

1
2
3
fetch('http://todos.com/api/todos')
.then(res => res.json())
.then(res => {console.log(res)});

CORS 가 발생하는 원인

SOP(Same-origin policy) 위배
https://developer.mozilla.org/ko/docs/Web/Security/Same-origin_policy

HTML 문서에서 일반적으로 외부 도메인의 자원을 호출하는것은 문제되지 않습니다.
하지만, <script></script> 내에서는 보안상의 이슈로 CORS 가 허용되지 않습니다.

오류 예시

Access to fetch at ‘http://localhost:8080/todos' from origin ‘http://localhost:3000' has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.