부트캠프

[멋쟁이사자처럼 유니티 TIL] node.js을 통한 비동기 서버 구축 구현 (+ 서버 구축 관련 용어 정리, 벡터와 라디안으로 회전 구현, 비동기 프로그래밍)

맛난과자 2024. 6. 8. 00:02

벡터와 라디안 회전 구현

 

Mathf.Deg2Rad

: Vector 변수에 곱하면 라디안으로 변환해 준다.

 

● 벡터를 라디안으로 변환하여 회전 구현

Vector3 newDirection = Vector3.RotateTowards(transform.forward, rotDirection, 
                       rotSpeed * Mathf.Deg2Rad, 0.0f);
GetComponent<Rigidbody>().MoveRotation(Quaternion.LookRotation(NewDirection));

 

 

● 쿼터니온으로 회전 구현

Quaternion newQuaternion = Quaternion.RotateTowards(transform.rotation, 
                           Quaternion.LookRotation(rotDirection), 
                           rotSpeed * Time.fixedDeltaTime);
GetComponent<Rigidbody>().MoveRotation(newQuaternion);

 

이렇게 하면 rotSpeed 값에 똑같은 값을 입력해도 회전이 비슷하게 구현된다.

 


 

비동기 프로그래밍

 

강사님이 저번 수업에 이어 추가 설명을 해주셨다.

 

앞에서 main을 실행할 동안 뒤에서 연산을 할 수 있는 프로그래밍이라고 생각하면 쉽다.

 

하나의 코어(cpu) 안에 여러 개의 쓰레드가 있는데, 이것들을 돌려 메인이 멈추지 않게 한다.

 

 

● async 비동기 예시

 

Task.Run : 쓰레드 돌리는 함수

aync : 비동기 함수를 사용하기 위한 키워드
await : 쓰레드가 끝날때까지 기다리는 키워드

 

aync가 함수 선언부에 있어야 await를 쓸 수 있다.

// 별도의 쓰레드를 돌려서 메인 쓰레드가 멈추지 않게 한 뒤
// 뒤에서 계산한다.
 async void UseThreadCalc()
 {
     await Task.Run(() => NoThreadCalc());
     
     Debug.Log("AsyncFinish");
 }

 void NoThreadCalc(CancellationToken token)
 {
     for (Int64 i = 0; i < 50000000000; i++)
     {
     }
     Debug.Log("Calculator done");
 }

 void Start()
 {
     UseThreadCalc();
 }

 

 

 

● Task 중 중단할 수 있는 async (코루틴 이용)

 

중단 요청을 하는 코루틴을 만들어 async 함수와 함께 실행한다.

public CancellationTokenSource cancel;

async void UseThreadCalc()
{    
    // 쓰레드 중간에 멈추기 위해 캔슬 객체를 만듬
    cancel = new CancellationTokenSource();
    var myTask = Task.Run(() => NoThreadCalc(cancel.Token), cancel.Token);
    Debug.Log("AsyncFinish");
}

void NoThreadCalc(CancellationToken token)
{
    for (Int64 i = 0; i < 50000000000; i++)
    {
        // 캔슬 요청이 들어오면 멈춤
        if (token.IsCancellationRequested)
            break;
        // 멈춤 유무 파악
        Debug.Log($"{i}");
    }
    Debug.Log("Calculator done");
}

// 중단 요청 코루틴 함수
IEnumerator Test()
{
    // 4초 후 중단
    yield return new WaitForSeconds(4);
    cancel.Cancel();
}

void Start()
{
    UseThreadCalc();           // aync 함수 실행
    StartCoroutine(Test());    // 코루틴 실행
    Debug.Log("AsyncFinish");
}

 

CancellationToken

: 비동기 작업에 취소 가능성을 추가할 때 사용한다.

  작업 중간에 이 토큰을 테크하면 작업 진행 여부를 결정할 수 있다.

 

CancellationTokenSource

: CancellationToken를 생성한다.

  Cancel 메서드를 호출하여 작업을 취소할 수 있다.

 

token.IsCancellationRequested

: CancellationToken의 프로퍼티. 비동기 작업 내에서 취소 요청이 발생했는지를 확인한다. 

 

 

token.IsCancellationRequested 대신 bool 변수를 이용하여 코드를 작성할 수도 있다.

다만 상대적으로 불안정하다.

// 취소 여부를 담을 bool 타입 변수 생성
private bool isCancel = false;

async void ASyncFunction()
{
    Int64 result = await Task.Run(() => AwaitFunction());
}

Int64 AwaitFunction()
{
    Int64 i = 0;
    for (; i < 500000100000; i++)
    {
        // 캔슬 요청 들어오면 중단
        if (isCancel)
            break;
    }

    Debug.Log("Calculator finish");
    return i;
}

IEnumerator Test()
{
    yield return new WaitForSeconds(4);
    
    // 캔슬 요청
    isCancel = true;
}

 


 

비동기 서버 구축

▶ express 프레임워크를 사용하여 간단한 HTTP 서버를 설정하고 클라이언트 요청을 처리해보자

 

 

 

● 용어 정리

 

npm : Node Package Manager. Node.js용 패키지 관리자

 

"express" : Node.js 환경에서 웹 애플리케이션 및 API를 쉽게 구축할 수 있도록 도와주는 웹 프레임워크, Express.js

 

웹 프레임워크 : 앱 애플리케이션을 개발하는 데 필요한 기본 구조와 도구를 제공하는 소프트웨어.

 

REST API : Representational State Transfer Application Programming Interface. 클라이언트와 서버 간의 통신을 위한

                   설계 원칙과 아키텍처 스타일을 준수하는 API(애플리케이션 프로그래밍 인터페이스)

 - 자원(리소스) : 모든 것은 자원으로 표현된다.

 - HTTP 메소드 : 자원에 대한 작업을 수행하기 위해 사용한다. GET, POST 등으로 자원의 조회, 생성 등을 할 수 있다.

 

port(포트) : 특정 서버에 접속할 때, 해당 서버가 있는 컴퓨터에 실행되어 있는 여러 프로그램 중 특정 프로그램에

                   접속하도록 알려주는 정보

 

req.body : 요청 본문에 포함된 데이터를 가져온다. 주로 POST, PUT, PATCH 요청에서 사용된다.

 

req.query : url의 쿼리 문자열에 포함된 데이터를 가져온다. 주로 GET 요청에서 사용된다.

 

? : url의 쿼리 문자열에서 쿼리 스트링의 시작을 의미한다. '여기서부터 쿼리다' 라는 뜻이다.

 

콜백 함수: 특정 이벤트가 발생했을 때 실행되는 함수. 이 코드에서는 GET 요청이 들어오는 것이 특정 이벤트이다.

 

모르는 용어가 너무 많아서 다 찾아보았다...

 

 

 

● 환경 구축

 

① 'node.js' 설치 후 재부팅, 'Visual Studio Code' 설치

https://code.visualstudio.com/download

 

Download Visual Studio Code - Mac, Linux, Windows

Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows. Download Visual Studio Code to experience a redefined code editor, optimized for building and debugging modern web and cloud applications.

code.visualstudio.com

 

https://nodejs.org/en

 

Node.js — Run JavaScript Everywhere

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

 

② vsc 에서 원하는 폴더를 지정한 후, 터미널에 아래 코드를 입력하여 npm을 초기화한다.

npm init

 

 

③ 해당 폴더의 파일에 아래 코드를 입력하여 서버를 생성한다.

const express = require("express");   // 익스프레스 모듈 불러옴
const app = express();   // 익스프레스 객체를 생성
const port = 3000;   // 포트 3000

app.use(express.json());   // express json 기능 사용

app.get('/', (req, res) => {   // request가 오면 연산 후에 response를 반환
    const data = req.body;
    console.log("Received data", data);   // 받은 데이터 콘솔에 출력
    res.send('Data received successfully');   // 클라이언트에 받았음을 응답
})

app.listen(port, () => {   // port 3000으로 서버 실행
    console.log("server started");   // 콜백 함수. 서버가 무사히 실행되면 콘솔에 출력
});

 

app.get('/', (req, res) => {})

'/' : url 경로 '/'를 받는다.

req : 이 경로로 들어오는 GET 요청을 받는다.

res : 콜백 함수로서 요청이 들어오면 실행된다.

 

app.listen(port, () => {})

: 포트에서 서버를 실행하겠다.

listen 메서드 : 주어진 포트에서 HTTP 서버를 시작하며, 주어진 포트 번호로 들어오는 모든 HTTP 요청을 처리한다.

 

 

④ vsc 파일을 실행한다.

 

⑤ 해당 포트 주소를 'http://localhost:포트숫자'  형식으로 인터넷에 검색하면 생성된 서버를 확인할 수 있다.

http://localhost:3000    // port가 3000일 경우

서버가 구축된 것을 확인할 수 있다.

 

⑥ API 개발 및 테스트를 도와주는 플랫폼인 'Postman' 을 설치한다.

https://www.postman.com/downloads/?utm_source=postman-home

 

Download Postman | Get Started for Free

Try Postman for free! Join 30 million developers who rely on Postman, the collaboration platform for API development. Create better APIs—faster.

www.postman.com

 

⑦ new 버튼을 누르고 HTTP 를 선택한다.

 

⑧ vsc 파일에 아래 코드 추가로 입력한다.

클라이언트가 '/data' 경로로 GET 요청을 보내면서 쿼리 파라미터로 'name'을 포함할 때, 서버가 그 'name'값을 응답으로 보낸다.

같은 방법으로 '/hello' 경로로 GET 요청을 보내면서 쿼리 파라미터로 'name'과 'snack'을 포함할 때, 서버가 그 'name'과 'snack' 값을 응답으로 보낸다.

app.get('/data', (req, res) => {  
    const data = req.query;  // req.query: get의 파라미터 값(postman에 작성한 거)을 데이터 담을 쿼리로 가져옴. 
                             // 즉, { name: 'snack', id: 1234 }와 같은 객체가 됨
    console.log(data);
    res.send(data.name);  //data.name: 쿼리 파라미터에서 'name'이라는 키의 값('name' 파라미터의 값) 가져와서 응답으로 보냄
})

app.get("/hello", (req, res) => {
    const data = req.query;
    console.log(data);
    res.send("hello " + data.name + " " + data.snack);
})

 

 

⑨ Postman 에 다음과 같이 입력한다.

localhost:3000/hello?name=snack&snack=yammy

 

 

⑩ body 창에 아래와 같이 뜨면 성공이다.


 

고찰

네트워크 관련은 처음 접해보는 것이라 어려운 용어가 많았지만,

그만큼 새로운 것들이 많아 공부할 동기부여가 되어 좋았다.

게임에 서버는 거의 필수기에 앞으로도 열심히 배우고 꼭 써먹을 것이다.