[SOPT 세미나] 서버 파트 2차 세미나 회고, 비동기 처리와 라우팅. Promise? Async&Await?

SSO·2022년 5월 3일
0

SOPT 30기

목록 보기
3/9

👩‍💻 2차 세미나

2차 세미나 회고 시작!~! 1차 때는 언어를 배우는 느낌이었다면 2차부터는 슬슬 비동기 처리와 라우팅을 배우기 시작했다. 스프링이나 장고에서 쓰던 url 매핑과는 또 다른 느낌이라 신기!! url을 한 곳에 모으는 것은 장고랑 조금 비슷했던 것 같긴 하다..!
장고는 캡스톤으로 어영부영 활용했고, 스프링은 인턴십을 통해서 한정된 것만 써봐서 제대로 라우팅을 배우고 처음부터 url을 연결시켜보는 것이 재밌었다 :)

느낀점 배운점 정리!! 회고!!



💜 비동기 처리


비동기 처리에는 대표적으로 Callback Function, Promise, Async/Await 가 있다는 것을 배웠다.

  • Callback Function (콜백 함수)
    어떤 이벤트 발생 시, 특정 시점에 도달했을 때 시스템에서 호출하는 함수로, 다른 함수의 인자로 사용된다.
console.log('안녕하세요.');

setTimeout(() => {
    console.log('Set Time Out');
}, 2000); // 2000 : 2초

console.log('끝');

/*
[실행 결과]
안녕하세요.
끝
Set Time Out
*/

👆 비동기식 Callback Function 코드 및 실행 결과

비동기식 Callback Function에는 대표적으로 setTimeout 함수가 사용된다.
동기식이었다면 '안녕하세요'이 출력되고 2초 후, 'Set Time out'이 출력된 후 '끝'이 출력되어야 할 것이다. 하지만 2초를 기다리지 않고 '끝'이 먼저 출력된 것으로 보아 비동기로 진행된 것을 확인할 수 있었다.

  • Promise (프로미스)
    (Pending, 대기) 비동기 처리가 완료되지 않은 상태
    (Fullfiled, 이행) 비동기 처리가 완료되어 Promise 결과 반환
    (Rejected, 실패) 실패하거나 오류
const condition: boolean = true;

// pending : 최초 생성 시점
const promise = new Promise((resolve, reject) => {
    if (condition) {
        // resolve : 동작에 대한 결과를 제공
        resolve('성공');
    } else {
        // reject : 동작을 실패하면 호출
        reject(new Error('reject !! error'));
    }
});

promise
    .then((resolveData): void => { // fullfiled
        console.log(resolveData);
    })
    .catch(error => console.log(error)); // rejected

/*
[실행 결과]
(condition == true) : 성공
(condition == false) : Error: reject !! error
*/

👆 비동기식 Promise 코드 및 실행 결과

Promise를 생성하여 then과 catch로 받아 성공하면 resolve, 실패하면 reject의 동작을 호출하는 것을 확인할 수 있었다.

  • Promise Chaining
    여러 개의 Promise를 연결하여 사용

콜백 함수가 너무 많이 사용되면, 콜백 안에 콜백 안에 콜백 안에 콜백.. 가독성 헬인 코드가 된다. 이러한 콜백 함수의 단점을 Promise Chaining으로 보완할 수 있다.

const restaurant = (callback: () => void, time: number) => {
    setTimeout(callback, time);
}

const order = (): Promise<string> => {
    return new Promise((resolve, reject) => {
        restaurant(() => {
            console.log('[레스토랑 진행 상황: 음식 주문]');
            resolve('음식 주문 시작');
        }, 1000);
    });
}

const cook = (progress: string): Promise<string> => {
    return new Promise((resolve, reject) => {
        restaurant(() => {
            console.log('[레스토랑 진행 상황: 음식 조리 중]');
            resolve(`${progress} -> 음식 조리 중`);
        }, 2000);
    });
}

const serving = (progress: string): Promise<string> => {
    return new Promise((resolve, reject) => {
        restaurant(() => {
            console.log('[레스토랑 진행 상황: 음식 서빙 중]');
            resolve(`${progress} -> 음식 서빙 중`);
        }, 2500);
    });
}

const eat = (progress: string): Promise<string> => {
    return new Promise((resolve, reject) => {
        restaurant(() => {
            console.log('[레스토랑 진행 상황: 음식 먹는 중]');
            resolve(`${progress} -> 음식 먹는 중`);
        }, 3000);
    });
}

order()
    .then(progress => cook(progress))
    .then(progress => serving(progress))
    .then(progress => eat(progress))
    .then(progress => console.log(progress));

/*
[실행 결과]
[레스토랑 진행 상황: 음식 주문]
[레스토랑 진행 상황: 음식 조리 중]
[레스토랑 진행 상황: 음식 서빙 중]
[레스토랑 진행 상황: 음식 먹는 중]
음식 주문 시작 -> 음식 조리 중 -> 음식 서빙 중 -> 음식 먹는 중
*/

👆 Promise Chaining 코드 및 실행 결과

함수 안에 함수를 넣지 않고, 여러 개의 promise를 then으로 연결하여 깔끔한 가독성으로 chaining 된 것을 확인할 수 있었다.

  • Async
    암묵적으로 Promise 반환
  • Await
    Promise(resolve/reject)를 기다림
const asyncFun = async () => {
    let progress = await order();
    progress = await cook(progress);
    progress = await serving(progress);
    progress = await eat(progress);
    console.log(progress);

}

asyncFun();

/*
[실행 결과]
[레스토랑 진행 상황: 음식 주문]
[레스토랑 진행 상황: 음식 조리 중]
[레스토랑 진행 상황: 음식 서빙 중]
[레스토랑 진행 상황: 음식 먹는 중]
음식 주문 시작 -> 음식 조리 중 -> 음식 서빙 중 -> 음식 먹는 중
*/

👆 Async/Await 코드 및 실행 결과

Async/Await으로 Promise Chaining에서 then으로 연결한 코드보다 더 간결하고 직관적인 코드를 쓸 수 있었다.



💜 HTTP Status


404, 500 등 여러 응답 코드를 본 적이 있었다. 그 외에는.. 많이 본 적도 없다 ㅎㅎ.. 응답 코드가 엄청 많다는 것은 알고 있었지만, 세미나를 통해서 외워두면 좋을 응답 코드를 배웠다!

응답 코드상태
403요청 거부 (Forbidden)
404리소스를 찾을 수 없음 (Not Found)
409요청 충돌 (Conflict)
500서버 내부 오류 (Internal Server Error)
503일시적 서버 이용 불가 (Service unavaiable)



💜 REST API


  • REST API
    REST 아키텍처를 준수하는 API
  • REST (REpresentational State Transfer)
    서버의 자원을 정의하고, 자원에 대한 주소를 지정하는 방법
  • API (Application Programming Interface)
    서버 어플리케이션의 기능을 사용하기 위한 방법

간단하게 REST API가 무엇인지도 배워보았다! URI와 URL 뭐 그런 것들..!



💜 Express


본격적으로 프로젝트를 생성하여 서버를 만들어 볼 수 있었다 ㅎㅎ

그 전에 먼저!! 실습할 프로젝트 폴더를 만들고 환경세팅을 준비해준다 :)

npm install yarn -g // yarn 패키지 설치
yarn --version // yarn 패키지 version 확인


( 폴더 만들기 (ex. express) )
cd 폴더(express)


yarn init // -> package.json 파일 생성
yarn add express // express : node.js를 위한 서버 프레임워크
yarn add -D @types/node @types/express // ts용 모듈 설치
yarn add -D nodemon // 서버 코드 변경 시 자동 재시작


tsc --init // -> tsconfig. json 파일 생성


import express, { Request, Response, NextFunction } from 'express';

// express 객체 받아오기
const app = express();


// get -> http method
app.get('/', (req: Request, res: Response, next: NextFunction) => {
    res.send('Message');
});
// + app.post, app.put, app.delete


// 8000번 포트에서 서버 실행
app.listen('8000',  () => {
    console.log(`서버 실행 시 console에 출력할 Message`);
});

👆 express/src/index.ts

yarn run dev // 서버 실행
yarn run build // 프로젝트 build

위 명령어로 서버 실행 후, 브라우저에 localhost:8000 을 입력하면, Message를 볼 수 있었다.



💜 Routing (라우팅)


URI의 정의로, URI가 클라이언트 요청에 응답하는 방식이다.

// express 모듈에서 타입 정의를 위해 불러옴
import express, { Request, Response, Router } from 'express';

// 라우터를 받아와서 저장
const router: Router = express.Router();

// status 200이면 json 파일 반환
router.get('/', (req: Request, res: Response) => {
    return res.status(200).json({
        status: 200,
        message: '유저 조회 성공'
    });
});

// 생성한 라우터 객체를 모듈로 반환
module.exports = router;

👆 express/src/api/user.ts

src 폴더 내부에 api 폴더를 생성하여, user.ts 파일을 만들었다. 유저 조회 성공 json을 반환하는 API이다.

import express, { Router } from 'express';

// express 라우팅 시스템 받아오기
const router: Router = express.Router();

// router.use
router.use('/user', require('./user'));

// 라우터 객체 모듈로 반환
module.exports = router;

👆 express/src/api/index.ts

api 폴더 내부에 index.ts 파일을 생성했다. 라우팅하여 user.ts 파일을 호출한다.
router.use('/user', require('./user')); 으로 URI 엔드포인트에 /user이 들어오면 user.ts 파일을 호출함으로써 유저 조회 성공 json을 반환하게 된다.

import express, { Request, Response, NextFunction } from 'express';

// express 객체 받아오기
const app = express();


// express에서 request body를 json으로 받아올 것
app.use(express.json());

// use -> 모든 요청
app.use('/api', require('./api'));
// localhost:8000/api -> api 폴더
// localhost:8000/api/user -> user.ts


// get -> http method
app.get('/', (req: Request, res: Response, next: NextFunction) => {
    res.send('Message');
});
// + app.post, app.put, app.delete


// 8000번 포트에서 서버 실행
app.listen('8000',  () => {
    console.log(`서버 실행 시 console에 출력할 Message`);
});

👆 express/src/index.ts

그럼 이제 src 내부의 index.ts를 수정해주어야 한다. app.use를 통해 api 폴더로 분기해준다.
라우팅이 끝났다! 서버 실행 후, localhost:8000/api/user URI를 통해 유저 조회 성공 json을 확인할 수 있다.





👩‍💻 Concluding

세미나를 들을 땐 따라가기도 벅찼는데, velog로 다시 써보면서 파일은 많아도 좀 더 익숙해진 느낌이다 ㅎㅎ 하지만 간단한 라우팅이라는 것 ㅠㅠ 더 열심히 공부해야지!~!!

profile
쏘's 코딩·개발 일기장

0개의 댓글