상세 컨텐츠

본문 제목

async await 사용의미, listen은 뭔가? await 실행되는 순서

카테고리 없음

by esoesmio 2024. 5. 9. 16:56

본문

 

 

### async와 await의 사용 이유와 의미

 

 


`async`와 `await`은 JavaScript에서 비동기 코드를 작성하는 특별한 문법입니다. 이 문법은 비동기 작업을 처리할 때 코드의 가독성을 높이고, 동기 코드와 유사한 방식으로 작성할 수 있게 해줍니다.

1. **`async` 함수**:
   - `async` 키워드는 함수가 비동기 함수임을 나타냅니다. 이 함수는 항상 프라미스(Promise)를 반환합니다. 함수 내부에서 `return`으로 값을 반환하면, 그 값은 프라미스의 해결(resolved) 값이 됩니다. 만약 함수 실행 중 예외가 발생하면, 그 예외는 프라미스의 거부(rejected) 상태로 처리됩니다.

2. **`await` 표현식**:
   - `await` 키워드는 `async` 함수 내에서만 사용됩니다. `await`은 프라미스의 해결을 기다립니다. 즉, 프라미스가 해결되어 결과 값이 반환되거나 거부되어 예외가 발생할 때까지 함수의 실행을 일시 중지합니다. 이를 통해 비동기 프라미스 기반 작업을 마치 동기적인 작업처럼 쉽게 처리할 수 있습니다.
   - 예를 들어, 데이터베이스 조회나 HTTP 요청과 같은 비동기 작업을 기다릴 때 `await`를 사용하면 해당 작업의 결과를 변수에 직접 할당할 수 있습니다. 이는 콜백(callback) 함수나 `.then()` 메서드를 사용하는 것보다 훨씬 간결하고 직관적입니다.

### `app.listen`의 의미

`app.listen`은 Express.js 프레임워크에서 서버를 시작하고 포트를 열어 외부에서 들어오는 요청을 받을 준비를 하는 메서드입니다. NestJS는 내부적으로 Express.js를 사용하거나 Fastify와 같은 다른 HTTP 서버 라이브러리를 사용할 수 있기 때문에, 이 메서드는 NestJS 애플리케이션에서도 중요합니다.

- **사용 방법**: `app.listen(port)` 호출 시, 애플리케이션은 지정된 `port`에서 네트워크 요청을 수신하기 시작합니다. 이는 서버가 "가동 중"이라고 볼 수 있으며, 이 포트를 통해 클라이언트의 요청을 받고 응답할 수 있습니다.
- **비동기 작업**: 서버의 시작은 실제로 네트워크 활성화를 포함하는 비동기 작업입니다. 서버가 준비되면 선택적으로 콜백 함수를 실행하거나 프라미스를 해결하여 서버가 준비된 것을 알릴 수 있습니다. 이 경우 `await app.listen(port)`을 사용하여 서버가 완전히 시작될 때까지 기다린 다음 다음 줄의 코드를 실행하게 됩니다.

이러한 방식으로 `async`와 `await`는 JavaScript에서 비동기 작업을 더욱 쉽고 효율적으로 다룰 수 있게 해주며, `app.listen`은 NestJS 애플리케이션에서 서버를 시작하는 데 필수적인 메서드입니다.

 

 

 

 

asyn는 promise 반환한다

 

맞아요, 이 `bootstrap` 함수에는 명시적인 `return` 문이 없습니다. 하지만 JavaScript에서 `async` 함수는 항상 프라미스(Promise)를 반환합니다. 이것은 함수의 정의가 어떻든 간에 자동으로 적용되는 규칙입니다.

`async` 함수에서 명시적인 `return` 값이 없을 경우, 함수는 기본적으로 `Promise.resolve(undefined)`를 반환합니다. 즉, 함수가 성공적으로 완료되고 어떤 값도 반환하지 않았을 때, 반환되는 프라미스는 `undefined`를 해결 값으로 가집니다.

여기서 `bootstrap` 함수는 다음과 같은 과정을 거칩니다:

1. `NestFactory.create(AppModule)`를 호출하여 NestJS 애플리케이션 인스턴스를 생성합니다. 이 호출은 비동기적이며, 완료될 때까지 `await`를 사용하여 함수의 실행을 일시 중지합니다.
2. 구성에서 서버 설정(`config.get('server')`)을 가져오고, 이를 통해 포트 번호를 추출합니다.
3. `app.listen(port)`를 호출하여 지정된 포트에서 서버를 시작합니다. 이 역시 비동기적으로 처리되며, 서버가 시작될 때까지 기다립니다.
4. `Logger.log()`를 사용하여 로그에 서버가 시작되었다는 메시지를 기록합니다.

함수가 종료되면, 실행이 성공적으로 완료되었다는 것을 나타내는 `undefined`가 포함된 프라미스가 반환됩니다. 이는 애플리케이션 또는 스크립트에서 `bootstrap` 함수를 호출하고, 그 완료를 기다리거나 후속 작업을 연결할 수 있게 해줍니다. 예를 들어, 테스트에서는 이 프라미스를 사용하여 서버가 시작된 후 테스트를 실행할 수 있습니다.

 

 

 

 

 

await를 쓰고 안쓰고 차이

 

 

`await` 키워드의 사용은 비동기 함수 호출의 결과 처리 방식을 근본적으로 변경합니다. 이 키워드는 JavaScript의 `async/await` 구문의 일부로, 프라미스(Promise)가 완료될 때까지 함수 실행을 일시 중지하고 프라미스가 해결(resolve) 된 후의 결과를 직접 처리할 수 있게 해줍니다.

### `await` 사용하는 경우:

```javascript
const app = await NestFactory.create(AppModule);
```

위 코드에서 `await`를 사용하면 `NestFactory.create(AppModule)`가 반환하는 프라미스가 해결될 때까지 현재 함수의 실행이 일시 중지됩니다. 프라미스가 해결되면 그 결과 값(여기서는 `app`)을 변수에 저장하고 코드의 다음 줄로 진행합니다. 이 방식은 코드를 직관적이고 동기적인 흐름으로 작성할 수 있게 해줍니다. 결과적으로, 함수의 나머지 부분에서 `app` 객체를 사용할 때 그것이 이미 완전히 초기화된 상태임을 보장받을 수 있습니다.

### `await` 사용하지 않는 경우:

```javascript
const app = NestFactory.create(AppModule);
```

이 경우 `NestFactory.create(AppModule)`는 여전히 프라미스를 반환하지만, `await` 없이 이 프라미스를 변수에 저장하게 되면, 변수 `app`은 프라미스 객체 자체를 참조하게 됩니다. 이 프라미스는 아직 해결되지 않았을 수 있으며, 실제 애플리케이션 인스턴스가 아니라 프라미스 객체를 가리키기 때문에, 이후 코드에서 `app`을 사용할 때 문제가 발생할 수 있습니다. 예를 들어, `app.listen(port)`와 같은 실제 메소드 호출을 시도하면, `app`이 아직 애플리케이션 인스턴스가 아니므로 오류가 발생합니다.

### 요약:

- **`await` 사용**: 비동기 호출의 결과를 직접적으로 처리하고, 프라미스가 해결된 후에 결과를 변수에 할당합니다. 이는 코드의 가독성과 유지 관리를 향상시키고, 동기 코드와 유사하게 작성할 수 있게 합니다.
- **`await` 미사용**: 비동기 호출의 프라미스를 변수에 할당하고, 프라미스의 상태나 결과에 대한 직접적인 처리 없이 다음 코드로 진행합니다. 이 경우 프라미스의 완료를 기다리지 않으므로, 후속 코드에서 프라미스가 해결된 상태를 가정하고 작성하는 경우 오류가 발생할 수 있습니다.

따라서, `await`의 사용은 함수 내에서 비동기 작업의 결과를 적절히 관리하고, 코드의 실행 흐름을 보다 안정적이고 예측 가능하게 만드는 중요한 역할을 합니다.

 

 

 

await 함수 호출 순서

 

 

이 `bootstrap` 함수에서의 호출 순서는 다음과 같습니다:

1. **`NestFactory.create(AppModule)` 호출**:
   - 이 함수는 비동기 함수로, NestJS 애플리케이션 인스턴스를 생성합니다. `await` 키워드를 사용하므로, 이 함수가 프라미스를 반환하고 그 프라미스가 해결될 때까지 함수의 실행이 일시 중지됩니다. 즉, `NestFactory.create(AppModule)`가 완전히 완료되고 반환된 애플리케이션 인스턴스가 `app` 변수에 할당될 때까지 다음 코드로 진행되지 않습니다.

2. **`config.get('server')` 호출**:
   - `NestFactory.create(AppModule)`가 완료된 후, `config.get('server')`가 호출됩니다. 이 함수는 `config` 모듈을 통해 설정 파일에서 서버 설정을 가져오는 동기 함수입니다. 따라서 이 함수의 호출은 즉각적으로 완료되며, 반환된 설정 객체가 `serverConfig` 변수에 저장됩니다.

3. **`port` 변수 할당**:
   - `serverConfig` 객체에서 `port` 속성을 추출하여 `port` 변수에 할당하는 작업은 역시 동기적으로 이루어집니다. 이것은 `serverConfig`가 이미 완전한 상태로 메모리에 존재하기 때문에 바로 처리됩니다.

4. **`app.listen(port)` 호출**:
   - `port` 변수가 설정된 후, 다시 비동기 함수인 `app.listen(port)`이 호출됩니다. 이 메서드는 서버를 지정된 포트에서 시작하고, 해당 포트에서 들어오는 네트워크 요청을 수신할 준비를 합니다. `await` 키워드를 사용하여 이 함수가 완료될 때까지 다음 코드로 진행되지 않습니다.

5. **`Logger.log(...)` 실행**:
   - 마지막으로, 서버가 성공적으로 시작되면, `Logger.log(...)` 함수가 호출되어 로그에 "application running on port ${port}" 메시지를 기록합니다. 이 호출은 동기적으로 처리됩니다.

요약하면, 함수 내에서 모든 작업은 순차적으로 실행됩니다. 첫 번째와 네 번째 주요 작업에서 비동기 함수가 호출되며, 나머지 작업은 동기적으로 처리됩니다. `await`을 사용한 비동기 함수들은 각각 완료될 때까지 코드의 진행을 일시 중지시키므로, 각 단계는 이전 단계가 완전히 완료된 후에 실행됩니다.

 

댓글 영역