본문 바로가기
C++ 200제/코딩 IT 정보

koa-static : next 사용 시 await / return 호출은 필수

by vicddory 2020. 3. 31.

◆ await return 둘 다 없다면 다음에 동작하는 미들웨어는 비동기 처리를 기다리지 않아요

◆ 비동기 처리 이후 설정이 없으면 Not Found 됩니다


아래는 단순히 정적 파일을 전달하는 Koa 애플리케이션 오류 예시입니다.

찾을 수 없는 경로에선 ok라는 문자열을 리턴합니다


const koa = require("koa")
const app = new koa()

app.use(require("koa-static")("."))

app.use(ctx => {
  ctx.body = "ok"
})

app.listen(3001)


"/"에 접속하면 ok가 표시됩니다.

여기에 테스트용으로 여러 가지를 추가합니다. 일단 아무것도 하지 않습니다. 미들웨어를 추가해도 동작하진 않습니다.


const koa = require("koa")
const app = new koa()

app.use((ctxnext=> {
  next()
})

app.use(require("koa-static")("."))

app.use(ctx => {
  ctx.body = "ok"
})

app.listen(3001)


"/"에 접속하면 Not Found가 표시됩니다.


이런 결과에 좀 당황했습니다.


추가된 미들웨어는 next를 호출한 뒤 아무것도 하지 않는 겁니다.

뒤죽박죽 뭔가 혼란하여 미들웨어 자체를 지우려고도 생각했습니다.


koa static 파일 서브 기능을 제거하니 동작하는 것 같습니다.


const koa = require("koa")
const app = new koa()

app.use((ctxnext=> {
  next()
})

app.use(ctx => {
  ctx.body = "ok"
})

app.listen(3001)


"/"에 접속하면 ok가 표시됩니다.


다른 표준 미들웨어처럼 async와 await를 사용해 보니 동작합니다.


const koa = require("koa")
const app = new koa()

app.use(async (ctxnext=> {
  await next()
})

app.use(require("koa-static")("."))

app.use(ctx => {
  ctx.body = "ok"
})

app.listen(3001)


"/"에 접속하면 ok가 표시됩니다.


async 함수로 Promise를 반환한다 해도 await가 없으면 동작하지 않습니다.


여태 잘 몰랐습니다만, 소스를 다시 보고 비동기 처리 흐름을 살펴보니 이해했네요.

해결

await 없이 next 만 호출하면 미들웨어 완료 응답을 기다리지 않고 Promise가 resolve 됩니다.

다음 동작이 모두 동기적이라면 괜찮지만, 비동기 작업이 있다면 완료를 기다리지 않습니다.

그 때문에 Koa가 미들웨어를 처리했다고 간주한 타이밍은 아직 ok가 떨어지지 않은 상황이죠.

그 상태에서 응답 값을 반환하기에 Not Found가 표시되는 것입니다.


이번 koa-static에는 파일을 읽는 비동기 처리가 들어갑니다.


const koa = require("koa")
const app = new koa()

app.use((ctxnext=> {
  next()
})

app.use(async ctx => {
  await new Promise(r => setTimeout(r1000))
  ctx.body = "ok"
})

app.listen(3001)


"/"에 접속하면 Not Found가 표시됩니다.


샘플 및 미들웨어 라이브러리 코드를 보면 async 함수가 아닌 것도 있어서 await로 기다리는 것이 필수라고 생각하지 못했습니다.

소스 코드를 잘 보면 next는 Promise를 return 하고 있습니다.

그래서!! 이후의 미들웨어 완료를 대기할 수 있습니다.


const koa = require("koa")
const app = new koa()

app.use((ctxnext=> {
  return next()
})

app.use(require("koa-static")("."))

app.use(ctx => {
  ctx.body = "ok"
})

app.listen(3001)


"/"에 접속하면 ok가 표시됩니다.


처리를 완료하고 return 해야 문제가 없습니다.


이런 이유로 Koa의 next를 호출하면 반환값을 return 할 때 await 대기가 필요합니다


일단, 비동기 동작이 아니라면 next만 호출해도 잘 동작합니다. 하지만, 앞으로 오류를 발생할 수 있는 요소이므로 return / await 사용은 필수입니다.



댓글