본문 바로가기
개인공부/Web API 게임 서버 공부

배경지식 - C#

by 하고싶은건많은놈 2023. 4. 20.

비동기 프로그래밍

C#에서는 asyncawait 키워드를 사용하여 비동기 프로그래밍을 구현

await 작업이 이루어지는 경우 await 이후의 작업은 쓰레드 풀의 유휴 쓰레드를 할당받아 수행하게됨

 

async

해당 메서드 내에 await 키워드를 사용할 수 있게 만들어줌
즉, await를 가지고 있을 수 있음을 알려주는 역할

  • 반드시 void / Task / Task<T> 중 하나를 반환해야함
    • Task : 백그라운드 속성의 쓰레드, 쓰레드 풀 사용
      System.Threading.Tasks 네임스페이스가 필요함
  • void를 사용시 비동기 메서드를 호출하는 쪽에서 비동기를 제어할 수 없음

await

비동기 작업의 흐름을 제어하는 키워드

단항 연산자로 쓰이며, awaitable 형식(Task 또는 Task<T>를 반환하는 함수 또는 메서드)의 인수를 가짐

  • 피연산자의 비동기 작업이 완료될 때까지 바깥쪽 async 메서드의 실행을 일시 중단시킴
  • 비동기 작업의 리턴값이 있다면 작업 결과를 리턴
  • 이미 완료된 비동기 작업 피연산자에 적용시 async 메서드를 중단시키지 않고 결과 즉시 반환
  • 비동기 메서드를 실행하는 쓰레드를 블로킹하지 않음
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    public static async void TaskA() // 작업 A
    {
        string syncString = "비동기임에도 동기 처럼 사용되는 것을 보여 주기 위한 변수";
        int n = await Task.Run(() => 
        {
            Console.WriteLine($"Do TaskA, returns 10 (ThreadID:{Thread.CurrentThread.ManagedThreadId})"); 
            Thread.Sleep(2000); // 작업이 오래 걸리고 있는 중
            return 10;
        });
        Console.WriteLine($"Do TaskB with {n} from TaskA (ThreadID:{ Thread.CurrentThread.ManagedThreadId})"); 
        Console.WriteLine(syncString);
    }
    
    public static void Main()
    {
        TaskA();
        
        for (int i = 0; i < 5; i++) 
        {
            Console.WriteLine($"Main thread waits UI event..{i + 1} (ThreadID:{ Thread.CurrentThread.ManagedThreadId})");
            Thread.Sleep(1000);
        }
        
        Console.WriteLine("Program finished");
    }
}

위 코드를 실행할 경우, 비동기로 작업하는 TaskA 내부에서 await가 걸려있는 Task에서 작업 흐름이 제어됨

따라서 실행 결과는 다음과 같음

Do TaskA, returns 10 (ThreadID:4) // 비동기 작업 시작 
Main thread waits UI event..1 (ThreadID:1)
Main thread waits UI event..2 (ThreadID:1)
Main thread waits UI event..3 (ThreadID:1)
Do TaskB with 10 from TaskA (ThreadID:4) // 비동기 작업 완료, 다음 작업 시작 
비동기임에도 동기 처럼 사용되는 것을 보여 주기 위한 변수
Main thread waits UI event..4 (ThreadID:1)
Main thread waits UI event..5 (ThreadID:1)
Program finished

Attribute

프로그램의 코드에 메타데이터를 추가하는 방법으로 사용 목적은 다음과 같음

  • 메타데이터 제공 - [Serializable], [Obsolete] 등
  • 컴파일 타임 검사 - [Conditional] 등
  • 런타임 동작 변경 - [Authorize] 등
  • 코드 생성 - [DataContract], [DataMember] 등

클래스, 메서드, 필드, 이벤트, 프로퍼티 등의 요소에 적용할 수 있으며 아래와 같은 형태로 사용됨

[AttributeUsage(AttributeTargets.SomeElement)]
public class MyAttribute : Attribute
{
    // 속성, 메서드, 이벤트 등을 정의
}

 

Conditional Attribute

컴파일러에게 조건부 컴파일을 지시하는데 사용

  • System.Diagnostics 네임스페이스가 필요
  • [Conditional("CONDITION_SYMBOL")] 형태로 사용
  • 클래스나 구조체 안에 있는 void형 메서드에서만 사용할 수 있음

아래 예시에서 Conditional Attribute에 의해 DEBUG 심볼이 정의되어있을 때만 MyMethod()가 컴파일됨

using System;
using System.Diagnostics;

class Program
{
    [Conditional("DEBUG")]
    static void MyMethod()
    {
        Console.WriteLine("Debug mode");
    }

    static void Main()
    {
        MyMethod();
    }
}

 

Obsolete Attribute

특정 코드가 더이상 사용되지 않는다는 경고를 표시

  • System 네임스페이스가 필요
  • [Obsolete(string message, bool error)] 형태로 사용
  • 두번째 매개변수인 error가 true일시 컴파일시 오류를 발생시켜 컴파일을 막음
  • 각 매개변수는 생략 가능
[Obsolete("This method is obsolete. Use a different method instead.", true)]
public void MyObsoleteMethod()
{
    // ...
}

 

Dll Import Attribute

외부의 DLL(동적 링크 라이브러리)을 코드에서 사용하기 위해 임포트하는데 사용

  • [DllImport("라이브러리 이름")] 형태로 사용
[DllImport("라이브러리 이름")]
public static extern 리턴타입 메서드이름(매개변수);

 

ApiController Attribute

컨트롤러 클래스에 부여되며, 해당 클래스가 웹 API 컨트롤러임을 나타냄

  • [ApiController] 형태로 사용
  • 사용하기 위해서는 Route Attribute가 필요
  • ApiController Attribute가 부여된 클래스는 다음과 같은 기능들을 제공함
    • 입력 모델 바인딩 : 요청의 body에 있는 데이터를 모델로 바인딩하는 기능을 자동으로 제공
    • 유효성 검사 : 데이터 모델에 대한 유효성 검사를 자동으로 수행
    • 예외 처리 : 예외 처리를 자동으로 수행
    • 라우팅 및 URL 생성 : 웹 API의 엔드포인트를 라우팅하고 URL을 생성하는데 필요한 기능들 제공
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    // GET api/users
    [HttpGet]
    public IActionResult Get()
    {
        // 사용자 목록을 조회하는 로직
        return Ok(users);
    }

    // POST api/users
    [HttpPost]
    public IActionResult Post([FromBody] User user)
    {
        // 새로운 사용자를 생성하는 로직
        CreateUser(user);
        return CreatedAtAction(nameof(Get), new { id = user.Id }, user);
    }

    // PUT api/users/{id}
    [HttpPut("{id}")]
    public IActionResult Put(int id, [FromBody] User user)
    {
        // 사용자 정보를 업데이트하는 로직
        UpdateUser(id, user);
        return NoContent();
    }

    // DELETE api/users/{id}
    [HttpDelete("{id}")]
    public IActionResult Delete(int id)
    {
        // 사용자를 삭제하는 로직
        DeleteUser(id);
        return NoContent();
    }
}

 

Route Attribute

컨트롤러 액션 메서드나 컨트롤러 클래스에 적용, 해당 액션 메서드나 컨트롤러의 라우팅 경로를 지정

웹 API 엔드포인트의 경로를 정의하고 클라이언트의 요청을 해당 경로와 일치하는 컨트롤러 액션 메서드로 라우팅

  • [Route("api/[controller]")] 형태로 사용하여 경로를 지정해 원하는 URL 패턴을 생성
  • [Route("api/[controller]/{id}")] 형태로 사용하여 경로 변수를 정의
  • [Route("api/[controller]/{id?}")] 형태로 사용하여 선택적 경로 변수를 정의, 해당 변수가 없어도 라우팅 가능
  • [Route("api/[controller]/{id:int}")] 형태로 사용하여 정규식 패턴을 지정
[Route("api/[controller]/{id}")]
public IActionResult GetById(int id)
{
    // id를 사용하여 특정 아이템을 가져오는 로직
    // ...
}

 

Frombody Attribute

웹 API에서 HTTP 요청의 body에 있는 데이터를 모델로 바인딩하기 위해 사용

  • [FromBody] 형태로 사용
  • JSON 형식 데이터를 C# 클래스로 변환하는 등의 기능으로 사용할 수 있음
public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

[HttpPost]
public IActionResult CreateUser([FromBody] User user)
{
    // 요청의 본문에 있는 데이터를 User 클래스로 바인딩하여 사용하는 로직
    if (ModelState.IsValid)
    {
        // 유효성 검사를 통과한 경우, User 객체를 사용하여 새로운 사용자 생성
        // ...
        return Ok();
    }
    else
    {
        // 유효성 검사에 실패한 경우, BadRequest를 반환하거나 오류 처리
        // ...
        return BadRequest();
    }
}

 

HttpXxx Attribute

웹 API에서 HTTP 요청 메서드를 지정하는데 사용

  • [HttpGet], [HttpPost], [HttpPut], [HttpDelete] 형태로 사용
  • 웹 API의 액션 메서드에 대한 라우팅 및 요청 처리 방식을 지정
[HttpGet]
public IActionResult Get()
{
    // HTTP GET 요청을 처리하는 로직
    // ...
}

[HttpPost]
public IActionResult Post([FromBody] MyModel model)
{
    // HTTP POST 요청을 처리하는 로직
    // ...
}

 

Require Attribute

컴파일 타임에 코드의 유효성을 검사하고 필요한 요구사항을 지정하는데 사용

  • [Require] 형태로 사용
  • 반드시 데이터가 입력되어야함(NULL이 허용되지 않음)
  • 메서드나 클래스의 입력 인자에 대한 유효성 검사 특성을 요구할 수 있음
  • 내장된 속성이 아닌 사용자가 직접 정의해야하는 커스텀 속성이기때문에 주의가 필요
using System.ComponentModel.DataAnnotations;

public class UserRegistrationModel
{
    [Required(ErrorMessage = "이름을 입력해주세요.")]
    public string Name { get; set; }

    [Required(ErrorMessage = "비밀번호를 입력해주세요.")]
    [MinLength(6, ErrorMessage = "비밀번호는 최소 6자 이상이어야 합니다.")]
    public string Password { get; set; }
}

'개인공부 > Web API 게임 서버 공부' 카테고리의 다른 글

배경지식 - Redis  (0) 2023.04.20
배경지식 - ORM  (1) 2023.04.20
배경지식 - ASP.NET  (0) 2023.04.19
배경지식 - API  (0) 2023.04.19
배경지식 - HTTP  (1) 2023.04.19

댓글