Featured image of post No static resource

No static resource

.well-known/appspecific/com.chrome.devtools.json.

๐Ÿ“Œ๊ฐœ์š”

Spring ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ํฌ๋กฌ์—์„œ ๋กœ์ปฌ ํ˜ธ์ŠคํŠธ๋ฅผ ์ ‘์†ํ•œ ๋’ค ๊ฐœ๋ฐœ์ž ๋ชจ๋“œ๋ฅผ ํ™œ์„ฑํ™” ํ•  ๋•Œ ๊ณ„์† ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.

์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ์‹œ์ ์€ ์‚ฌ์šฉ์ž ์ •์˜ ์˜ˆ์™ธ๋ฅผ ๊ณตํ†ต์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•œ ์‹œ์ ์— ๋ฐœ์ƒํ–ˆ๋‹ค.

ํ”„๋กœ๊ทธ๋žจ์—๋Š” ์˜ํ–ฅ์ด ์—†๋Š” ๊ฒƒ ๊ฐ™์•˜์ง€๋งŒ ์˜ค๋ฅ˜๋‹ˆ๊นŒ ๊ฑฐ์Šฌ๋ฆฐ๋‹ค. ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„  ๋ฌธ์ œ ์—†๋Š” ๊ฒƒ ๊ฐ™์€๋ฐ ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ์ž์ฃผ ๋ฐœ๊ฒฌ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

๐Ÿ“Œ๋‚ด์šฉ

1
[http-nio-8080-exec-7] ERROR GlobalExceptionHandler - [์‹œ์Šคํ…œ ์˜ค๋ฅ˜] No static resource .well-known/appspecific/com.chrome.devtools.json.

๋กœ๊ทธ ํฌ๋งท์„ ๋ณ€๊ฒฝํ•ด์„œ ์ผ๋ฐ˜์ ์ด์ง„ ์•Š๊ฒ ์ง€๋งŒ ์ด ๋ถ€๋ถ„ .well-known/appspecific/com.chrome.devtools.json., ๊ฐœ๋ฐœ์ž ๋ชจ๋“œ๋ฅผ ํ™œ์„ฑํ™”ํ•  ๋•Œ๋งˆ๋‹ค ์ •์  ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•œ๋‹ค.

ํฌ๋กœ๋ฏธ์›€ ๊ธฐ๋ฐ˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋กœ์ปฌ ํ˜ธ์ŠคํŠธ์˜ ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์—ด ๋•Œ ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์€๋ฐ ๊ทธ๋ž˜์„œ ์ € ์˜ค๋ฅ˜๊ฐ€ ๋ญ”์ง€ ๊ถ๊ธˆํ–ˆ๋‹ค.

Chromium DevTools Ecosystem Guide๋ฌธ์„œ์—์„œ ๊ด€๋ จ ๋‚ด์šฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์–ด๋–ค ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ์„๊นŒ

ํฌ๋กฌ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ๊ฐ€ ์ž๋™์œผ๋กœ .well-known/appspecific/… ํŒŒ์ผ์„ ์š”์ฒญํ•˜๋ฉด์„œ ์ƒ๊ธฐ๋Š” ํ˜„์ƒ. ์„œ๋ฒ„์— ์‹ค์ œ๋กœ ํ•ด๋‹น ์ •์  ๋ฆฌ์†Œ์Šค๊ฐ€ ์—†์–ด์„œ Spring์ด ์˜ค๋ฅ˜๋ฅผ ๋˜์ง€๋Š” ๊ฒƒ์ด๋ฉฐ, ๋ณด์•ˆ ์œ„ํ—˜์€ ์—†๋‹ค.

  • ๋ฌด์‹œํ•˜๊ฑฐ๋‚˜
  • ๋”๋ฏธ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๊ฑฐ๋‚˜
  • ์š”์ฒญ ๊ฒฝ๋กœ ํ•„ํ„ฐ๋ง์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.

์ฝ”๋“œ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ดํŽด ๋ณด๊ธฐ

์ผ๋‹จ ๋‚ด ๊ฒฝ์šฐ๋Š” ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€๊นŒ์ง„ ์•ˆ ๋ณด์ด๋‹ค๊ฐ€ ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธฐ๋Š” ์‹œ์ ์— ๋ณด์ด๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค.

๋•œ๋นต(?)์„ ํ•˜๊ธด ํ–ˆ์ง€๋งŒ ๋ณ„๋กœ ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์€ ์•„๋‹Œ ๊ฒƒ ๊ฐ™๊ณ .. ์ผ๋‹จ ์ฝ”๋“œ ๋Œ€์ถฉ ๋ณด๊ณ  ์›์ธ๋ถ€ํ„ฐ ์•Œ์•„๋ณด์ž.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@ControllerAdvice  
public class GlobalExceptionHandler {  

    private static final Logger log = LogManager.getLogger(GlobalExceptionHandler.class);  
  
    @ExceptionHandler(BusinessException.class)  
    public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {  
        log.error("[์„œ๋น„์Šค ์˜ค๋ฅ˜] code: {}, messageKey: {}", e.getErrorCode().getCode(), e.getErrorCode().getMessageKey(), e);  
        ErrorCode errorCode = e.getErrorCode();  
        HttpStatus status = mapToHttpStatus(errorCode);  
        ...
        return ResponseEntity.status(status).body(response);  
    }  
  
    @ExceptionHandler(Exception.class)  
    public ResponseEntity<ErrorResponse> handleGeneralException(Exception e) {  
    
        // ํฌ๋กฌ ๋ฒ„์ „ ๋•Œ๋ฌธ์— ์ถœ๋ ฅ๋˜๋Š” ์—๋Ÿฌ  
        if (e.getMessage().equals("No static resource .well-known/appspecific/com.chrome.devtools.json.")) {  
            return ResponseEntity.status(HttpStatus.NOT_FOUND).build();  
        }  
        log.error("[์‹œ์Šคํ…œ ์˜ค๋ฅ˜] {}", e.getMessage(), e);  
        ...
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); 
    }  
  
    private HttpStatus mapToHttpStatus(ErrorCode errorCode) {  
        ...
    }  
}

Spring MVC๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.

  • ์ •์  ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์ง€ ๋ชปํ•˜๋ฉด NoResourceFoundException ๋˜๋Š” NoHandlerFoundException์„ ๋ฐœ์ƒ ์‹œํ‚จ๋‹ค.
  • ์ด ์˜ˆ์™ธ๋Š” ๊ธฐ๋ณด์ ์œผ๋กœ Spring ๋‚ด๋ถ€ DispatcherSevlet์ด ์ฒ˜๋ฆฌํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ €์—” 404 ์‘๋‹ต๋งŒ ๋ณด๋‚ด์ง€ ๋กœ๊ทธ๋กœ ๋‚จ๊ธฐ์ง€ ์•Š๋Š”๋‹ค.

๊ทธ๋Ÿฐ๋ฐ… ์ด๋ ‡๊ฒŒ ๋ช…์‹œ์ ์œผ๋กœ ๋กœ๊ทธ๋ฅผ ๋ฐ•์•„ ๋ฒ„๋ฆฌ๋ฉด

  • Spring์˜ ๋‚ด๋ถ€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๊ฐ€๋กœ์ฑˆ๋‹ค
  • .well-known/... ๊ฐ™์€ ์š”์ฒญ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋„ ์žกํžŒ๋‹ค.
  • ํ•ธ๋“ค๋Ÿฌ๋Š” ์•Œ ์ˆ˜ ์—†๋Š” ์‹œ์Šคํ…œ ์˜ค๋ฅ˜๋กœ ๊ฐ„์ฃผํ•˜๊ณ  log.error()๋ฅผ ๋‚จ๊ธด๋‹ค.
  • ๊ทธ ๊ฒฐ๊ณผ ํฌ๋กฌ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ ์ž๋™์œผ๋กœ ๋ณด๋‚ด๋Š” ์š”์ฒญ์—์„œ๋„ ์—๋Ÿฌ ๋กœ๊ทธ๊ฐ€ ์Œ“์ธ๋‹ค.
    1
    2
    3
    4
    5
    
    @ExceptionHandler(Exception.class)  
    public ResponseEntity<ErrorResponse> handleGeneralException(Exception e) {  
        log.error("[์‹œ์Šคํ…œ ์˜ค๋ฅ˜] {}", e.getMessage(), e);
        ...
    }  
    

์ง€๊ธˆ์˜ ๋‚˜๋กœ์„ ..

  • .well-known ์š”์ฒญ์„ ํ•„ํ„ฐ๋‚˜ ํ•ธ๋“ค๋Ÿฌ์—์„œ ๋”ฐ๋กœ ๋ฌด์‹œ ์ฒ˜๋ฆฌ
  • ๋˜๋Š” @ExceptionHandler์˜ ๋ฒ”์œ„๋ฅผ ์ขํ˜€์„œ ์‹œ์Šคํ…œ ์˜ˆ์™ธ ์™ธ์—๋Š” ๋ฌด์‹œ
  • ๊ฐ€์žฅ ๊น”๋”ํ•œ ๋ฐฉ๋ฒ•์€ ํ•„์š” ์—†๋Š” ๊ฒฝ๋กœ์˜ ์˜ˆ์™ธ๋Š” ๋กœ๊น…ํ•˜์ง€ ์•Š๋„๋ก ๋ถ„๊ธฐ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ

Automatic Workspace Folders๋ž€?

Chrome DevTools (๋ฒ„์ „ M-135 ์ด์ƒ) ์—์„œ ๋„์ž…๋œ ๊ธฐ๋Šฅ์œผ๋กœ, DevTools๊ฐ€ ๊ฐœ๋ฐœ ์„œ๋ฒ„(devserver)๋กœ๋ถ€ํ„ฐ ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ† ๋ฆฌ ์ •๋ณด๋ฅผ ์ž๋™์œผ๋กœ ์ธ์‹ํ•ด, ๋กœ์ปฌ ์›Œํฌ์ŠคํŽ˜์ด์Šค๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

๊ธฐ์กด์˜ Workspaces ๊ธฐ๋Šฅ์„ ์ž๋™ํ™”ํ•œ ๊ฒƒ์œผ๋กœ, ๋””๋ฒ„๊น… ์ค‘ DevTools์—์„œ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ ํ•ด๋‹น ์ˆ˜์ • ์‚ฌํ•ญ์ด ๋กœ์ปฌ ํŒŒ์ผ์— ์ง์ ‘ ๋ฐ˜์˜๋  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•ด์ค€๋‹ค๊ณ  ํ•œ๋‹ค.

์ด๋Ÿฐ ๊ธฐ๋Šฅ์ด ์ƒ๊ธด ๋ฐฐ๊ฒฝ

๊ธฐ์กด DevTools Workspaces ๊ธฐ๋Šฅ(M-63 ๋„์ž…)์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ถˆํŽธ์ด ์žˆ์—ˆ๋‹ค.

  1. ์ˆ˜๋™ ์„ค์ •์ด ํ•„์š”ํ•จ (Workspace ํƒญ์—์„œ ์ง์ ‘ ํด๋” ์ง€์ •)
  2. ํ”„๋กœ์ ํŠธ๋ณ„ ๊ด€๋ฆฌ๊ฐ€ ๋ถˆํŽธํ•จ (๋งค๋ฒˆ ํด๋” ์ถ”๊ฐ€/์‚ญ์ œ ํ•„์š”)

์ž‘๋™ ๋ฐฉ์‹

Chrome DevTools๋Š” ๋‹ค์Œ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•  ๋•Œ ์ž๋™์œผ๋กœ .well-known/appspecific/com.chrome.devtools.json ํŒŒ์ผ์„ ์š”์ฒญํ•œ๋‹ค.

  • ๋ธŒ๋ผ์šฐ์ €์—์„œ ์—ฌ๋Š” ํŽ˜์ด์ง€์˜ origin์ด localhost
  • DevTools๊ฐ€ ์—ด๋ ค ์žˆ๋Š” ์ƒํƒœ

์ด ํŒŒ์ผ์ด ์กด์žฌํ•˜๋ฉด DevTools๋Š” ํ•ด๋‹น ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž๋™์œผ๋กœ ์›Œํฌ์ŠคํŽ˜์ด์Šค๋กœ ์—ฐ๊ฒฐํ•œ๋‹ค.

์š”์ฒญ๋˜๋Š” JSON ํŒŒ์ผ

  • ์š”์ฒญ ๊ฒฝ๋กœ: /.well-known/appspecific/com.chrome.devtools.json
  • ์ด JSON ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง„๋‹ค.
    1
    2
    3
    4
    5
    6
    
    {
      "workspace": {
        "root": "/Users/foobar/Projects/my-awesome-web-project",
        "uuid": "53b029bb-c989-4dca-969b-835fecec3717"
      }
    }
    
  • ๊ฐ ํ•„๋“œ ์„ค๋ช…
    • workspace.root: ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ† ๋ฆฌ์˜ ์ ˆ๋Œ€ ๊ฒฝ๋กœ
    • workspace.uuid: ํ”„๋กœ์ ํŠธ ๊ณ ์œ  ์‹๋ณ„์ž (v4 UUID ๋“ฑ ๋ฌด์ž‘์œ„๋กœ ์ƒ์„ฑ)

์‚ฌ์šฉ ์กฐ๊ฑด

  • M-135 ์ด์ƒ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • M-136์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ธฐ๋Šฅ์ด ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์Œ
  • ์ด์ „ ๋ฒ„์ „์—์„œ๋Š” ๋‹ค์Œ ๋‘ ํ”Œ๋ž˜๊ทธ๋ฅผ ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•จ
    1
    2
    
    chrome://flags#devtools-project-settings
    chrome://flags#devtools-automatic-workspace-folders
    

์š”์•ฝ ์ •๋ณด

ํ•ญ๋ชฉ๋‚ด์šฉ
๊ธฐ๋Šฅ ์ด๋ฆ„Automatic Workspace Folders
๋„์ž… ๋ฒ„์ „M-135 (๊ธฐ๋Šฅ ๋น„ํ™œ์„ฑํ™”), M-136 (๊ธฐ๋ณธ ํ™œ์„ฑํ™”)
๋ชฉ์ DevTools์—์„œ ๋กœ์ปฌ ํ”„๋กœ์ ํŠธ์™€ ์ž๋™ ์—ฐ๊ฒฐํ•˜์—ฌ ์ฝ”๋“œ ์ˆ˜์ • ๋ฐ˜์˜
์ž‘๋™ ์กฐ๊ฑดorigin์ด localhost์ผ ๋•Œ DevTools์—์„œ JSON ์š”์ฒญ
๊ฒฝ๋กœ/.well-known/appspecific/com.chrome.devtools.json
JSON ํ•„๋“œworkspace.root, workspace.uuid
๋ถ€๊ฐ€ ๋„๊ตฌVite ํ”Œ๋Ÿฌ๊ทธ์ธ ์กด์žฌ, npx serve ์˜ˆ์‹œ ์ œ๊ณต๋จ

๐ŸŽฏ๊ฒฐ๋ก 

๋ช…ํ™•ํ•œ ํ•ด๊ฒฐ์ฑ…์€ ์—†์ง€๋งŒ ๋ถˆํ•„์š”ํ•œ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•˜์ง€ ์•Š๊ฒŒ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๊ฒ ๋‹ค. ํฌ๋กฌ ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์‹ค์ œ ์‚ฌ์šฉ ์˜ˆ์‹œ๋‚˜ ํ•œ๊ณ„, ์กฐ๊ฑด ๋“ฑ์„ ์•Œ์•„๋ณด๋Š” ๊ฒƒ๋„ ์ข‹๊ฒ ๋‹ค.

โš™๏ธEndNote

์ฐธ๊ณ  ์ž๋ฃŒ