728x90
반응형
728x90
반응형
반응형

레이트 리미팅(Rate Limiting)과 캐싱(Caching) 전략

애플리케이션의 성능을 높이고 서버 자원을 효율적으로 관리하기 위해서는 레이트 리미팅(Rate Limiting)캐싱(Caching) 전략을 적절히 사용하는 것이 중요합니다. 특히 대규모 사용자 기반을 가진 애플리케이션에서는 서버 과부하를 방지하고 빠른 응답 속도를 유지하는 데 필수적입니다. 아래에서는 각 전략의 원리와 함께 구체적인 예제 코드를 살펴보겠습니다.

레이트 리미팅(Rate Limiting)

레이트 리미팅은 API 호출이나 데이터베이스 쿼리의 빈도를 제한하여 성능을 최적화하고, 자원을 절약하며, 서비스 오버로드를 방지하는 데 유용합니다. 예를 들어, 특정 IP 주소에서 1시간 동안 100번 이상 요청할 경우 접근을 차단하는 식으로 빈도 제한을 설정할 수 있습니다.

구현 전략: IP 주소 또는 사용자별로 특정 시간 안에 호출 가능한 요청 수를 설정하여 서버의 안정성을 유지합니다. Redis와 같은 메모리 기반 데이터 스토어를 사용해 호출 빈도를 기록하고, 초과 요청 시 대기나 실패 응답을 반환할 수 있습니다.

예제: Node.js + Redis를 이용한 레이트 리미팅

아래 코드는 Node.js와 Redis를 사용하여 특정 IP 주소에서 일정 시간 안에 호출 가능한 요청 수를 제한하는 방법을 보여줍니다.

const redis = require('redis');
const client = redis.createClient();

function rateLimiter(req, res, next) {
    const userIP = req.ip;
    client.incr(userIP, (err, count) => {
        if (count > 100) { // 예: 1시간 동안 100번 이상 요청 금지
            res.status(429).send("요청 제한 초과");
        } else {
            client.expire(userIP, 3600); // 1시간 동안 카운트 유지
            next();
        }
    });
}

위 코드에서 rateLimiter 함수는 클라이언트의 IP를 기반으로 요청 횟수를 Redis에 기록하며, 설정한 제한 횟수를 초과하면 429 상태 코드로 요청을 차단합니다. 이를 통해 서버의 과부하를 방지할 수 있습니다.

캐싱(Caching)

캐싱은 반복적으로 요청되는 데이터를 저장해 두고 빠르게 반환하는 방법으로, API나 데이터베이스의 호출 빈도를 줄여 성능을 크게 향상시킬 수 있습니다. 특히 오래 걸리는 데이터 처리 작업이나 고빈도 요청에서 효과적입니다.

캐싱 레이어 설정: 클라이언트, 서버, 데이터베이스 수준에서 캐싱을 적용할 수 있으며, Redis 같은 인메모리 스토리지를 통해 빈번히 요청되는 데이터를 캐시할 수 있습니다. 또한 TTL(Time-to-Live)을 설정하여 오래된 데이터를 자동으로 갱신하거나 삭제해 실시간성을 유지할 수 있습니다.

예제: Python + Flask + Redis를 이용한 캐싱

아래 코드는 Python의 Flask와 Redis를 사용하여 데이터베이스에서 가져온 데이터를 캐싱하여 빠르게 반환하는 예제입니다.

from flask import Flask, request
import redis

app = Flask(__name__)
cache = redis.StrictRedis(host='localhost', port=6379, db=0)

@app.route('/data')
def get_data():
    data_key = 'expensive_data'
    cached_data = cache.get(data_key)
    
    if cached_data:
        return cached_data
    else:
        data = retrieve_expensive_data()  # 오래 걸리는 데이터 처리 함수
        cache.setex(data_key, 3600, data) # 1시간 동안 캐싱
        return data

위 코드에서 get_data 함수는 먼저 Redis에 저장된 expensive_data 캐시를 확인하고, 캐시된 데이터가 있으면 즉시 반환합니다. 만약 없다면 retrieve_expensive_data 함수를 호출하여 데이터를 생성한 후, Redis에 1시간 동안 캐싱합니다. 이렇게 함으로써 동일한 요청에 대한 응답 시간을 대폭 줄일 수 있습니다.

결론

레이트 리미팅과 캐싱은 고급 애플리케이션에서 성능을 최적화하는 데 핵심적인 전략입니다. 레이트 리미팅은 서버의 안정성을 유지하며, 캐싱은 응답 속도를 향상시키는 데 기여합니다. 이 두 가지 전략을 결합하여 API 서버에서 캐시된 응답을 사용하되 요청이 많아질 경우 레이트 리미팅을 적용하면 서버 성능을 최적화할 수 있습니다.

728x90
반응형
반응형

Starship : Cross-shell Prompt

Starship with iTerm2 and the Snazzy theme

모든 셸에 사용할 수 있는 최소의, 매우 빠른, 무한히 사용자 정의가 가능한 프롬프트!

  • 빠름 : 빠릅니다 – 정말 정말 빠릅니다! 🚀
  • 사용자 정의 가능 : 프롬프트의 모든 측면을 구성합니다.
  • 범용 : 모든 셸, 모든 운영 체제에서 작동합니다.
  • 지능형 : 관련 정보를 한눈에 보여줍니다.
  • 풍부한 기능 : 모든 인기 도구 지원.
  • 쉬움 : 설치가 빠르며 몇 분 안에 사용을 시작할 수 있습니다.

🚀 설치

필수 조건

역자 주) 너드 폰트와 유사한 문자를 지원하는 글꼴이면, 해당 글꼴을 사용하셔도 됩니다.

1단계. Starship 설치

설치 지침을 보려면 아래 목록에서 운영 체제를 선택하세요.

리눅스

  • 시스템에 맞는 최신 버전을 설치하세요:
curl -sS https://starship.rs/install.sh | sh
  • 다음 패키지 관리자를 사용하여 Starship을 설치할 수 도 있습니다.
배포 저장소 명령어
Any [crates.io] cargo install starship --locked
Any [conda-forge] conda install -c conda-forge starship
Any [Linuxbrew] brew install starship
Alpine Linux 3.13+ [Alpine Linux Packages] apk add starship
Arch Linux [Arch Linux Extra] pacman -S starship
CentOS 7+ [Copr] dnf copr enable atim/starship
dnf install starship
Gentoo [Gentoo Packages] emerge app-shells/starship
Manjaro pacman -S starship
NixOS [nixpkgs] nix-env -iA nixpkgs.starship
openSUSE [OSS] zypper in starship
Void Linux [Void Linux Packages] xbps-install -S starship

윈도우

  • 릴리스 섹션 에서 MSI 설치 프로그램을 사용하여 시스템에 최신 버전을 설치하세요.

  • 다음 패키지 관리자를 사용하여 Starship을 설치할 수 도 있습니다.

저장소 명령
[crates.io] cargo install starship --locked
[Chocolatey] choco install starship
[conda-forge] conda install -c conda-forge starship
[Scoop] scoop install starship
[winget] winget install --id Starship.Starship

2단계. Starship을 사용하기 위해 셸을 설정하세요

쉘을 구성하여 우주선을 초기화합니다. 아래 목록에서 선택하세요:

  • bash
    • ~/.bashrc의 끝에 다음을 추가합니다.
eval "$(starship init bash)"
  • Windows 명령 프롬프트 (Cmd)
    • Cmd와 함께 Clink (v1.2.30+)를 설치하여 사용해야 합니다.
    • 다음 내용으로 %LocalAppData%\clink\starship.lua 경로에 파일을 만듭니다.
load(io.popen('starship init cmd'):read("*a"))()
  • PowerShell
    • PowerShell 구성의 끝에 다음을 추가합니다($PROFILE을 실행하여 찾을 수 있음):
Invoke-Expression (&starship init powershell)
  • 나머지 구성은 starship 홈페이지를 참조하세요.

3단계. Starship 구성

새로운 셸 인스턴스를 시작하면 아름다운 새 셸 프롬프트가 표시됩니다. 기본 설정에 만족하신다면 즐겨보세요!

Starship을 더욱 맞춤화하고 싶다면:

  • 구성 – 프롬프트를 원하는 대로 조정하기 위해 Starship을 구성하는 방법을 알아보세요.

  • 사전 설정 – 다른 사람의 사전 구축된 구성에서 영감을 얻으세요

📝 라이센스

728x90
반응형
반응형

다양한 언어에서의 Mix-in 패턴 구현: Ruby부터 다른 언어들까지

Mix-inRuby 언어에서 매우 중요한 개념으로, 다중 상속의 복잡성을 피하면서도 여러 클래스에 기능을 공유할 수 있게 해줍니다. 이 글에서는 Ruby의 Mix-in 기능과 함께, 이를 다른 언어에서 어떻게 유사하게 구현할 수 있는지 소개하겠습니다.


1. Ruby의 Mix-in 예제

Ruby에서 Mix-in은 모듈을 통해 구현되며, 클래스에 포함(include)하여 여러 메서드를 쉽게 추가할 수 있습니다. 예제는 다음과 같습니다:

module Walkable
  def walk
    "I'm walking!"
  end
end

class Animal
end

class Dog < Animal
  include Walkable
end

dog = Dog.new
puts dog.walk  # 출력: "I'm walking!"

여기서 Walkable 모듈을 Dog 클래스에 포함함으로써 Dog 클래스는 walk 메서드를 사용할 수 있습니다. Ruby는 이처럼 모듈을 활용해 코드 재사용성을 높입니다.


2. Python에서의 Mix-in 유사 기능

Python은 다중 상속을 직접 지원하므로, Mix-in 클래스를 상속하는 방식으로 유사한 패턴을 구현할 수 있습니다. Python에서의 예제는 다음과 같습니다:

class Walkable:
    def walk(self):
        return "I'm walking!"

class Animal:
    pass

class Dog(Animal, Walkable):
    pass

dog = Dog()
print(dog.walk())  # 출력: "I'm walking!"

이 예제에서는 Walkable 클래스를 Dog 클래스에 상속하여 walk 메서드를 추가했습니다. Python에서는 이런 방식으로 Mix-in을 구현합니다.


3. JavaScript에서의 Mix-in 구현

JavaScript는 클래스 기반 언어가 아니지만, 객체 지향 프로그래밍과 관련된 여러 패턴을 지원합니다. Mix-in은 Object.assign을 통해 구현할 수 있습니다:

let Walkable = {
  walk: function() {
    return "I'm walking!";
  }
};

class Animal {}

class Dog extends Animal {}

Object.assign(Dog.prototype, Walkable);

let dog = new Dog();
console.log(dog.walk());  // 출력: "I'm walking!"

여기서 Object.assign을 사용해 Walkable 객체의 메서드를 Dog 클래스의 프로토타입에 복사하여 Mix-in 패턴을 적용했습니다.


4. C#에서의 Mix-in 구현

C#은 다중 상속을 지원하지 않지만, 인터페이스와 조합하여 Mix-in과 비슷한 구조를 만들 수 있습니다. 예제는 다음과 같습니다:

using System;

interface IWalkable
{
    void Walk();
}

class Walkable : IWalkable
{
    public void Walk()
    {
        Console.WriteLine("I'm walking!");
    }
}

class Animal
{
}

class Dog : Animal, IWalkable
{
    private Walkable _walkable = new Walkable();

    public void Walk()
    {
        _walkable.Walk();
    }
}

class Program
{
    static void Main()
    {
        Dog dog = new Dog();
        dog.Walk();  // 출력: "I'm walking!"
    }
}

여기서는 Walkable 클래스를 별도로 만들어 Dog 클래스에서 해당 인스턴스를 사용해 메서드를 호출하는 방식으로 구현했습니다.


5. Java에서의 Mix-in 구현

Java는 기본적으로 다중 상속을 지원하지 않지만, Java 8부터는 default 메서드를 포함한 인터페이스를 사용하여 Mix-in을 구현할 수 있습니다:

interface Walkable {
    default String walk() {
        return "I'm walking!";
    }
}

class Animal {
}

class Dog extends Animal implements Walkable {
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println(dog.walk());  // 출력: "I'm walking!"
    }
}

여기서는 Walkable 인터페이스에 default 메서드를 정의하고, Dog 클래스가 이를 구현하도록 했습니다.


결론

Ruby의 Mix-in은 모듈을 사용해 클래스에 쉽게 기능을 추가할 수 있게 해주며, Python, JavaScript, C#, Java와 같은 언어에서도 유사한 기능을 구현할 수 있습니다. 각 언어는 자신만의 방식을 사용하지만, 핵심 개념은 다중 상속의 복잡성을 줄이고 코드 재사용성을 높이는 데 있습니다.

이렇게 다양한 언어에서 Mix-in 패턴을 활용하면 더 효율적이고 유지보수가 쉬운 코드를 작성할 수 있습니다.

728x90
반응형
반응형

cctz : 시간대 규칙을 사용하여 절대 시간과 상용 시간을 변환하기 위한 C 라이브러리

이것은 공식 Google 제품이 아닙니다.

개요

CCTZ에는 <chrono>와 협력하여 C++ 프로그래머에게 간단하고 올바른 방식으로 날짜, 시간대, 시간대를 가진 컴퓨팅에 필요한 모든 도구를 제공하는 두 개의 라이브러리가 포함되어 있습니다.

CCTZ의 라이브러리는 다음과 같습니다:

  • 지역시간(Civil-Time) 라이브러리 - 날짜(cctz::civil_day 클래스로 표시됨)와 같은 지역 규모의 시간으로 컴퓨팅을 지원하는 헤더 전용 라이브러리입니다. 이 라이브러리는 include/cctz/civil_time.h 에 정의되어 있습니다.

  • 시간대(Time-Zone) 라이브러리 - 이 라이브러리는 절대 시간과 지역 시간을 변환하기 위해 시스템에 설치된 IANA 시간대 데이터베이스를 사용합니다. 이 라이브러리는 include/cctz/time_zone.h 에 정의되어 있습니다.

이 라이브러리는 현재 Linux, Mac OS X 및 Android에서 작동하는 것으로 알려져 있습니다. zoneinf 파일을 설치하면 Windows에서도 작동합니다. 하지만 대신 Windows 시간 API를 호출하는 cctz:TimeZoneIf 인터페이스를 구현하는 데 관심이 있습니다. 기여에 관심이 있으시면 연락해 주세요.

시작하기

CCTZ는 Bazel 빌드 시스템과 Google 테스트 프레임워크를 사용하여 구축 및 테스트하는 것이 가장 좋습니다. (Bazel을 사용할 수 없는 경우 작동하는 간단한 MakefileCMakeLists.txt도 있습니다.)

  1. 바젤 다운로드 / 설치 https://docs.bazel.build/versions/master/install.html
  2. cctz 소스를 가져옵니다: git clone https://github.com/google/cctz.git 그런 다음 cd cctz
  3. cctz를 빌드하고 테스트를 실행합니다: bazel test :all

CMake를 사용하기:

  1. CMake >= 2.8.12가 설치되어 있는지 확인하세요.
  2. cctz 소스를 가져옵니다: git clone https://github.com/google/cctz.git 그런 다음 cd cctz.
  3. 공유 라이브러리에서 사용할 수 있도록 cctz를 빌드하고 테스트를 실행합니다 (-DBUILD_TESTING=OFF를 사용하면 테스트를 건너뛸 수 있습니다.)
mkdir mybuild
cd mybuild
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON ..
cmake --build . --config Release
ctest
cmake --build . --config Release --target install
  1. CMake 기반 프로젝트에서 다음을 사용하세요.
find_package(cctz REQUIRED)
add_executable(mytarget file.cc)
target_link_libraries(mytarget cctz::cctz)

참고: 자신의 프로젝트에서 CCTZ를 사용하는 경우 컴파일하는 것이 가장 쉬울 수 있습니다. 기존 빌드 시스템을 사용하여 소스를 사용합니다.

다음 단계:

  1. CCTZ의 라이브러리에 대한 설명서를 참조하세요.
  2. https://github.com/google/cctz/tree/master/examples의 예를 살펴보세요.
  3. 질문을 하고 변경 사항을 계속 알아보려면 메일링 목록에 가입하세요.

기본 개념

[여기에 제시된 개념은 문제 영역에 대한 일반적인 진실을 설명하며 라이브러리와 언어에 구애받지 않습니다. 이러한 개념을 이해하면 프로그래머가 가장 복잡한 시간 프로그래밍 문제도 올바르게 추론하고 가능한 가장 간단한 솔루션을 생성하는 데 도움이 됩니다.]

컴퓨터 프로그램에서 시간에 대해 생각하는 방법에는 절대 시간과 지역 시간이라는 두 가지 주요 방법이 있습니다. 두 가지 모두 사용법이 있으며, 각 시간대가 언제 적절한지 이해하는 것이 중요합니다. 절대 시간과 지역 시간은 시간대를 사용하여 앞뒤로 변환할 수 있으며, 이것이 두 시간대를 올바르게 변환할 수 있는 유일한 방법입니다. 이제 시간 프로그래밍의 세 가지 주요 개념인 절대 시간, 지역 시간, 시간대에 대해 자세히 살펴보겠습니다.

절대 시간은 고유하고 보편적으로 특정 순간을 나타냅니다. 캘린더, 날짜, 하루 중 시간에 대한 개념은 없습니다. 대신 실시간의 흐름을 측정하는 척도이며, 일반적으로 어떤 시대 이후의 단순한 틱 수로 사용됩니다. 절대 시간은 모든 시간대와 독립적이며 일광 절약 시간(DST)과 같은 인간이 부과하는 복잡성으로 인해 발생하지 않습니다. 많은 C++ 유형이 절대 시간을 나타내기 위해 존재하며, 고전적으로는 time_t, 그리고 최근에는 std:chrono:time_point.

지역 시간은 일반적인 일에 대한 법적으로 인정되는 시간을 표현하는 것입니다(https://www.merriam-webster.com/dictionary/civil) 참조). 지역 시간은 연도, 월, 일, 시간, 분, 초의 6가지 분야(때로는 "YMDHMS"로 단축되기도 함)로 구성된 인간 규모의 시간 표현이며, 24시간을 60분 시간과 60초로 나눈 프롤레틱 그레고리안 캘린더의 규칙을 따릅니다. 절대 시간과 마찬가지로 지역 시간도 모든 시간대와 관련 복잡성(예: DST)과 독립적입니다. std:tm에는 6개의 지역 시간 필드(YMDHMS)가 포함되어 있지만, 지역 시간의 규칙을 시행하는 행동이 없습니다.

시간대는 절대 시간 영역과 지역 시간 영역 간에 변환하기 위해 인간이 정의한 규칙을 공유하는 지정학적 영역입니다. 시간대의 규칙에는 UTC 시간 표준에서 해당 지역의 상쇄, 일광 절약 조정, 짧은 약어 문자열과 같은 것이 포함됩니다. 시간대에는 특정 지역의 지방 정부가 마음대로 규칙이 변경될 수 있기 때문에 특정 기간에만 적용되는 이질적인 규칙의 역사가 있는 경우가 많습니다. 이러한 이유로 시간대 규칙은 일반적으로 런타임에 절대 시간대와 지역 시간대 간의 변환을 수행하는 데 사용되는 데이터 스냅샷으로 컴파일됩니다. 현재 임의의 시간대를 지원하는 C++ 표준 라이브러리는 없습니다.

프로그래머가 이러한 개념을 올바르게 다루는 애플리케이션을 추론하고 프로그래밍하려면 위의 개념을 올바르게 구현하는 라이브러리가 있어야 합니다. CCTZ는 위의 개념을 완전히 구현하기 위해 기존 C++11 라이브러리에 추가됩니다.

  • 절대 시간(Absolute time) - 이는 수정 없이 기존 C++11 <chrono> 라이브러리에서 구현됩니다. 예를 들어, 절대 시점은 std::chrono::time_point로 표시됩니다.

  • 지역시간(Civil Time) - 이 기능은 CCTZ의 일부로 제공되는 include/cctz/civil_time.h 라이브러리에서 구현됩니다. 예를 들어, "날짜"는 cctz::civil_day로 표시됩니다.

  • 시간대(Time zone) - 이 기능은 CCTZ의 일부로 제공되는 include/cctz/time_zone.h 라이브러리에 의해 구현됩니다. 예를 들어, 시간대는 클래스 cctz::time_zone의 인스턴스로 표시됩니다.

예시

안녕하세요 2016년 2월

이 "안녕 세상(Hello World)" 예제에서는 for-loop를 사용하여 2월 1일부터 3월까지 날짜를 반복합니다. 각 날짜는 출력으로 스트리밍되며, 날짜가 29일인 경우 요일도 출력합니다.

#include <iostream>
#include "cctz/civil_time.h"

int main() {
  for (cctz::civil_day d(2016, 2, 1); d < cctz::civil_month(2016, 3); ++d) {
    std::cout << "Hello " << d;
    if (d.day() == 29) {
      std::cout << " <- leap day is a " << cctz::get_weekday(d);
    }
    std::cout << "\n";
  }
}

위 프로그램의 출력은 다음과 같습니다.

Hello 2016-02-01
Hello 2016-02-02
Hello 2016-02-03
[...]
Hello 2016-02-27
Hello 2016-02-28
Hello 2016-02-29 <- leap day is a Monday

하나의 거대한 도약

이 예제는 세 라이브러리(, civil time, time zone)를 모두 함께 사용하는 방법을 보여줍니다. 이 예제에서는 뉴욕의 시청자들이 1969년 7월 20일 오후 10시 56분에 닐 암스트롱의 첫 달맞이 산책을 시청한 것으로 알고 있습니다. 하지만 호주 시드니에서 친구가 몇 시에 시청했는지 알고 싶습니다.

#include <iostream>
#include "cctz/civil_time.h"
#include "cctz/time_zone.h"

int main() {
  cctz::time_zone nyc;
  cctz::load_time_zone("America/New_York", &nyc);

  // Converts the input civil time in NYC to an absolute time.
  const auto moon_walk =
    cctz::convert(cctz::civil_second(1969, 7, 20, 22, 56, 0), nyc);

  std::cout << "Moon walk in NYC: "
            << cctz::format("%Y-%m-%d %H:%M:%S %Ez\n", moon_walk, nyc);

  cctz::time_zone syd;
  if (!cctz::load_time_zone("Australia/Sydney", &syd)) return -1;
  std::cout << "Moon walk in SYD: "
            << cctz::format("%Y-%m-%d %H:%M:%S %Ez\n", moon_walk, syd);
}

위 프로그램의 출력은 다음과 같습니다.

Moon walk in NYC: 1969-07-20 22:56:00 -04:00
Moon walk in SYD: 1969-07-21 12:56:00 +10:00

이 예는 달에서 첫 걸음의 절대 시간(std::chrono::time_point)이 시청자의 시간대에 관계없이 동일하다는 것을 보여줍니다(format ()에 대한 두 통화 모두에서 동일한 시간대가 사용됨). 유일한 차이점은 moon_walk 시점이 렌더링되는 시간대입니다. 이 경우 시드니에 있는 친구가 아마도 그 역사적인 사건을 보면서 점심을 먹고 있었을 것이라는 것을 알 수 있습니다.

참고문헌

728x90
반응형
반응형

Boost.Utility 개요

Boost.Utility는 언어 지원을 위한 작고 유용하며 일반적인 용도의 구성 요소 모음입니다.

  • 시간이 지나면서,
    • 여러 구성 요소가 더 적합한 Boost 라이브러리로 이동되었습니다.
    • 이러한 구성 요소 중 다수는 C++ 표준에 수용된 변형을 가지고 있습니다.

해당 구성 요소가 다른 Boost 라이브러리로 이동한 경우에도 Boost.Utility 헤더는 다른 라이브러리의 해당 헤더로 연결됩니다.

Boost.Utility Moved to Boost C++ Standard variant
addressof Boost.Core C++11 std::addressof
base_from_member
BOOST_BINARY C++14 Binary integer literal
call_traits
checked_delete Boost.Core
compressed_pair
declval Boost.TypeTraits C++11 std::declval
enable_if Boost.Core C++11 std::enable_if
generator iterator adaptors Boost.Iterator
in_place_factory
iterator_adaptors Boost.Iterator
next / prior Boost.Iterator C++11 std::next / std::prev
noncopyable Boost.Core
operators
ostream_string Boost.IO
result_of C++11 std::result_of
string_view C++17 std::string_view
throw_exception Boost.ThrowException
value_init C++11 List initialization
728x90
반응형
반응형

OpenXLSX : Excel(.xlsx) C++ 라이브러리

  • 홈페이지 : https://github.com/troldal/OpenXLSX

  • OpenXLSX.xlsx 형식의 Microsoft Excel® 파일 읽기, 쓰기, 생성 및 수정을 위한 C++ 라이브러리입니다.


개발 동기

  • 많은 프로그래밍 언어는 기본적으로 또는 오픈 소스 라이브러리 형태로 Excel 파일을 수정할 수 있습니다.

  • 여기에는 Python, JavaC#이 포함됩니다. 그러나 C++의 경우 상황이 더 흩어져 있습니다.

  • 일부 라이브러리는 있지만 일반적으로 다른 언어에 비해 성숙도가 낮고 기능 집합이 작습니다.

  • 제 요구 사항에 완전히 맞는 오픈 소스 라이브러리가 없기 때문에 OpenXLSX 라이브러리를 개발하기로 결정했습니다.


희망 사항

  • OpenXLSX는 엑셀 파일(데이터와 포맷)을 읽고, 쓰고, 만들고, 수정할 수 있어야 하며, 가능한 한 적은 의존도로 그렇게 할 수 있어야 한다는 것이 목표입니다.

  • 현재 OpenXLSX는 다음 타사 라이브러리에 의존하고 있습니다:

    • PugiXML
    • Zippy (C++ wrapper around miniz)
    • Boost.Nowide (for opening files with non-ASCII names on Windows)
  • 이러한 라이브러리는 모두 헤더 전용이며 저장소에 포함되므로 별도로 다운로드하고 빌드할 필요가 없습니다.

  • 또한 메모리 사용량이 아닌 속도 에 초점을 맞추고 있습니다(속도를 희생하면서 메모리 사용량을 줄일 수 있는 옵션이 있지만 나중에 자세히 알아보세요).


호환성

  • OpenXLSX는 다음 플랫폼/컴파일러에서 테스트되었습니다.
  • '-'는 OpenXLSX가 작동하지 않는다는 것을 의미하지 않습니다.
  • GCC Clang MSVC
    Windows MinGW MinGW +
    Cygwin - - N/A
    MacOS + + N/A
    Linux + + N/A

  • 다음 컴파일러 버전은 오류 없이 OpenXLSX를 컴파일할 수 있어야 합니다:

    • GCC: 버전 7
    • Clang: 버전 8
    • MSVC: 비주얼 스튜디오 2019
  • Clang 7OpenXLSX를 컴파일할 수 있어야 하지만, std::variant 구현에 버그가 있어 컴파일러 오류가 발생하는 것 같습니다.

  • Visual Studio 2017도 작동하지만 테스트되지 않았습니다.


빌드 지침

  • OpenXLSX는 빌드 시스템(또는 빌드 시스템 생성기)으로 CMake를 사용합니다.
  • 따라서 OpenXLSX를 빌드하려면 먼저 CMake를 설치해야 합니다. 설치 지침은 https://www.cmake.org 에서 확인할 수 있습니다.

  • OpenXLSX 라이브러리는 이 레포의 OpenXLSX 하위 디렉토리에 있습니다.
  • OpenXLSX 하위 디렉토리는 독립형 CMake 프로젝트이며, 자체 프로젝트에 CMake를 사용하는 경우 OpenXLSX 폴더를 하위 디렉토리로 추가할 수 있습니다.
  • 또는 CMake를 사용하여 원하는 도구 체인에 대한 파일을 만들거나 프로젝트 파일을 생성할 수 있습니다.
  • 두 가지 방법 모두 다음에 설명되어 있습니다.

CMake 프로젝트 구조에 통합

  • 자신의 프로젝트에서 OpenXLSX를 사용하는 가장 쉬운 방법은 직접 CMake를 사용한 다음 OpenXLSX 폴더를 자신의 프로젝트의 소스 트리에 하위 디렉토리로 추가하는 것입니다.

  • 여러 IDECMake 프로젝트, 특히 Visual Studio 2019, JetBrains CLion, Qt Creator 를 지원합니다.
  • Visual Studio를 사용하는 경우 새 프로젝트를 만들 때 'CMake 프로젝트'를 특별히 선택해야 합니다.

  • OpenXLSX 라이브러리를 소스 하위 폴더로 포함하면 라이브러리와 헤더 파일을 특별히 찾을 필요가 없고, CMake가 이를 처리해준다는 점이 가장 큰 장점입니다.
  • 또한 라이브러리는 프로젝트와 동일한 구성(디버그, 릴리스 등)을 사용하여 구축됩니다.
  • 특히 Windows의 경우, OpenXLSX에서와 같이 STL 개체가 라이브러리 인터페이스를 통과할 때 디버그 프로젝트에서 릴리스 라이브러리를 사용할 수 없으며 그 반대의 경우도 마찬가지입니다.
  • OpenXLSX 소스를 포함하면 문제가 되지 않습니다.

  • 프로젝트의 CMakeLists.txt 파일에 있는 add_subdirectory() 명령을 사용하면 OpenXLSX의 헤더 및 라이브러리 파일에 액세스할 수 있습니다.
  • OpenXLSX는 공유 라이브러리 또는 정적 라이브러리를 생성할 수 있습니다.
  • 기본적으로 공유 라이브러리가 생성되지만 OpenXLSX CMakeLists.txt 파일에서 이를 변경할 수 있습니다.
  • 라이브러리는 OpenXLSX라는 네임스페이스에 있으므로 라이브러리의 전체 이름은 OpenXLSX:OpenXLSX 입니다.

  • 다음 스니펫은 자체 프로젝트를 위한 최소 CMakeLists.txt 파일로, 하위 디렉토리로 OpenXLSX가 포함되어 있습니다.
  • 바이너리의 출력 위치는 공통 디렉토리로 설정되어 있습니다.
  • LinuxMacOS에서는 이 작업이 실제로 필요하지 않지만 Windows에서는 실행하기 위해 OpenXLSX 공유 라이브러리 파일을 실행 파일의 위치로 복사해야 하므로 사용자의 삶이 더 쉬워집니다.
     cmake_minimum_required(VERSION 3.15)
     project(MyProject)
    
     set(CMAKE_CXX_STANDARD 17)
    
     # Set the build output location to a common directory
     set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output)
     set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output)
     set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output)
    
     add_subdirectory(OpenXLSX)
    
     add_executable(MyProject main.cpp)
     target_link_libraries(MyProject OpenXLSX::OpenXLSX)
    

  • 위의 코드를 사용하여 다음 코드를 컴파일하고 실행할 수 있어야 하며, 이 코드를 사용하면 'Spreadshet.xlsx'라는 이름의 새 Excel 파일이 생성됩니다:
      #include <OpenXLSX.hpp>
      
      using namespace OpenXLSX;
    
      int main() {
    
          XLDocument doc;
          doc.create("Spreadsheet.xlsx");
          auto wks = doc.workbook().worksheet("Sheet1");
    
          wks.cell("A1").value() = "Hello, OpenXLSX!";
    
          doc.save();
    
          return 0;
      }
    

별도 라이브러리로 빌드하기

  • OpenXLSX 바이너리를 직접 제작하여 프로젝트에 포함시키려면 원하는 CMake와 컴파일러 툴체인을 사용하여 작업할 수 있습니다.

  • 명령줄에서 프로젝트 루트의 OpenXLSX 하위 디렉토리를 탐색하고 다음 명령을 실행합니다
      mkdir build
      cd build
      cmake ..
    

  • 마지막 명령은 프로젝트를 구성합니다.
  • 이렇게 하면 기본 도구 체인을 사용하여 프로젝트가 구성됩니다.
  • 도구 체인을 지정하려면 Unix Makefiles, Ninja, Xcode 또는 Visual Studio 16 2019와 같이 사용하려는 도구 체인을 사용하여 cmake -G "<toolchain>...을 입력합니다.
  • 자세한 내용은 CMake 설명서를 참조하세요.

  • 마지막으로 다음 명령을 사용하여 라이브러리를 구축할 수 있습니다:
      cmake --build . --target OpenXLSX --config Release
    
  • --target 인수와 --config 인수를 사용자가 원하는 대로 변경할 수 있습니다.

  • 빌드할 때 다음 명령을 사용하여 설치할 수 있습니다:
      cmake --install .
    

  • 이 명령은 라이브러리 및 헤더 파일을 플랫폼의 기본 위치(일반적으로 LinuxMacOS에서는 /usr/local/, Windows에서는 C:\Program Files)에 설치합니다.
  • --prefix 인수를 사용하여 다른 위치를 설정할 수 있습니다.

  • 플랫폼에 따라 디버그 라이브러리와 릴리스 라이브러리를 모두 설치하지 못할 수도 있습니다.
  • LinuxMacOS에서는 릴리스 라이브러리를 디버그 실행 파일과 릴리스 실행 파일 모두에 사용할 수 있기 때문에 이 문제는 큰 문제가 아닙니다.
  • 하지만 라이브러리의 구성이 라이브러리에 연결되는 실행 파일의 구성과 같아야 하는 Windows의 경우에는 그렇지 않습니다.
  • 따라서 Windows에서는 OpenXLSX 소스 폴더를 CMake 프로젝트의 하위 디렉토리로 포함하는 것이 훨씬 쉬워서 많은 골칫거리를 줄일 수 있습니다.

현재 상태

  • OpenXLSX는 아직 작업 중입니다.
  • 다음은 구현되었으며 제대로 작동해야 하는 기능 목록입니다:
    • 파일 생성/열기/저장
    • 셀 내용 읽기/쓰기/수정
    • 셀 및 셀 범위 복사
    • 워크시트 복사
    • 셀 범위 및 반복자
    • 행 범위 및 반복자

  • 포맷, 플롯 및 도형과 관련된 기능은 구현되지 않았으며 가까운 미래에 구현될 계획도 없습니다.
  • 현재 XLD 문서 객체를 생성하는 것이 작동하지 않는다는 점에 유의해야 합니다!

성능

  • 아래 표는 초당 약 4,000,000셀의 속도로 읽기/쓰기 액세스를 수행할 수 있음을 보여주는 벤치마크(Google Benchmark 라이브러리 사용)의 출력입니다.
  • .xml 파일의 문자열로 변환하거나 문자열에서 변환하기 때문에 부동소수점 숫자는 다소 낮습니다.
     Run on (16 X 2300 MHz CPU s)
     CPU Caches:
       L1 Data 32 KiB (x8)
       L1 Instruction 32 KiB (x8)
       L2 Unified 256 KiB (x8)
       L3 Unified 16384 KiB (x1)
     Load Average: 2.46, 2.25, 2.19
     ---------------------------------------------------------------------------
     Benchmark                 Time             CPU   Iterations UserCounters...
     ---------------------------------------------------------------------------
     BM_WriteStrings        2484 ms         2482 ms            1 items=8.38861M items_per_second=3.37956M/s
     BM_WriteIntegers       1949 ms         1949 ms            1 items=8.38861M items_per_second=4.30485M/s
     BM_WriteFloats         4720 ms         4719 ms            1 items=8.38861M items_per_second=1.77767M/s
     BM_WriteBools          2167 ms         2166 ms            1 items=8.38861M items_per_second=3.87247M/s
     BM_ReadStrings         1883 ms         1882 ms            1 items=8.38861M items_per_second=4.45776M/s
     BM_ReadIntegers        1641 ms         1641 ms            1 items=8.38861M items_per_second=5.11252M/s
     BM_ReadFloats          4173 ms         4172 ms            1 items=8.38861M items_per_second=2.01078M/s
     BM_ReadBools           1898 ms         1898 ms            1 items=8.38861M items_per_second=4.4205M/s
    

주의사항

파일 크기

  • .xlsx 파일은 기본적으로 .zip 아카이브의 .xml 파일 묶음입니다.
  • 내부적으로 OpenXLSXminiz 라이브러리를 사용하여 .zip 아카이브를 압축/압축 해제하는데, miniz는 처리할 수 있는 파일 크기에 대한 상한이 있는 것으로 밝혀졌습니다.

  • 아카이브의 파일(아카이브 자체가 아닌 .zip 아카이브의 항목)에 대한 최대 허용 파일 크기는 4GB(압축되지 않음)입니다.
  • 일반적으로 .xlsx 파일/아카이브에서 가장 큰 파일은 워크시트 데이터가 저장된 .xml 파일입니다.
  • 즉, 워크시트 데이터는 4GB를 초과할 수 없습니다.
  • 행과 열로 환산하면 데이터 유형에 따라 크게 달라지지만, 4자리 정수로 채워진 1,048,576개의 행 x 128개의 열이 차지합니다.
  • 압축된 아카이브의 크기는 워크시트에 저장된 데이터와 사용된 압축 알고리즘에 따라 다르지만, 워크시트가 4GB인 워크북의 압축 크기는 일반적으로 300~350 MB입니다.

  • 4GB 제한은 아카이브의 전체 아카이브 크기가 아닌 단일 항목에만 관련이 있습니다.
  • 즉, 아카이브에 4GB 크기의 항목이 여러 개 있는 경우 miniz는 여전히 이를 처리할 수 있습니다. OpenXLSX의 경우 여러 개의 대형 워크시트가 있는 워크북을 계속 열 수 있습니다.

메모리 사용량

  • OpenXLSX.xlsx 아카이브에서 .xml 파일을 구문 분석하고 조작하기 위해 PugiXML 라이브러리를 사용합니다.
  • PugiXML은 전체 .xml 문서를 메모리로 읽는 DOM 파서입니다.
  • 따라서 구문 분석과 조작이 엄청나게 빠릅니다.

  • 그러나 모든 선택에는 결과가 있으며, DOM 파서를 사용하면 많은 메모리가 필요할 수도 있습니다.
  • 작은 스프레드시트의 경우 문제가 되지 않지만 큰 스프레드시트를 조작해야 하는 경우 많은 메모리가 필요할 수 있습니다.

  • 아래 표는 OpenXLSX가 처리할 수 있는 데이터 열 수를 나타냅니다(1,048,576행으로 가정):

  • Columns
    8GB RAM 8-16
    16GB RAM 32-64
    32GB RAM 128-256
  • 마일리지는 다를 수 있습니다.

  • OpenXLSX의 성능은 스프레드시트의 데이터 유형에 따라 달라집니다.


  • 또한 64비트 모드에서는 OpenXLSX를 사용하는 것이 좋습니다.
  • 32비트 모드에서는 쉽게 사용할 수 있지만 4GB RAM에만 액세스할 수 있으므로 대규모 스프레드시트를 처리할 때 유용성이 크게 제한됩니다.

  • 메모리 소비가 문제인 경우 컴팩트 모드에서 OpenXLSX 라이브러리를 구축하면(CMakeLists.txt 파일에서 ENABLE_COMPACT_MODE를 찾아보세요) PugiXML의 컴팩트 모드를 활성화할 수 있습니다.
  • 그러면 OpenXLSX는 메모리 사용량이 적지만 실행 속도도 느려집니다.
  • 자세한 내용은 여기 에서 PugiXML 설명서를 참조하세요.
  • 8GB RAM이 있는 Linux VM에서 실행된 테스트 사례에 따르면 OpenXLSX는 컴팩트 모드에서는 1,048,576행 x 32열로 워크시트를 처리할 수 있는 반면 기본 모드에서는 1,048,576행 x 16열로 처리할 수 있는 것으로 나타났습니다.

유니코드

  • 지금까지 Github에서 OpenXLSX에 대해 가장 많이 들은 질문은 유니코드와 관련이 있습니다.
  • 이 질문은 많은 사람들에게 큰 혼란의 원인인 것으로 보입니다(그리고 당연히 이해할 수 있습니다).

  • 초기에 저는 OpenXLSX가 텍스트 인코딩/변환 유틸리티가 아닌 엑셀 부분에 초점을 맞춰야 한다고 결정했습니다.
  • 따라서 OpenXLSX에 대한 모든 텍스트 입출력은 UTF-8 인코딩이어야 합니다.
  • 그렇지 않으면 예상대로 작동하지 않습니다.
  • 소스 코드 파일을 UTF-8 형식으로 저장해야 할 수도 있습니다.
  • 예를 들어 소스 파일이 UTF-16 형식으로 저장되면 모든 문자열 리터럴도 UTF-16 형식으로 저장됩니다.
  • 따라서 소스 코드에 하드 코딩된 문자열 리터럴이 있는 경우 소스 파일도 UTF-8 형식으로 저장해야 합니다.

  • OpenXLSX의 모든 문자열 조작 및 사용은 불가지론적 인코딩이지만 UTF-8 인코딩에 쉽게 사용할 수 있는 C++ std::string을 사용합니다.
  • 또한 Excel은 내부적으로 UTF-8 인코딩을 사용합니다(실제로 다른 인코딩을 사용할 수도 있지만 잘 모르겠습니다).

  • 위와 같은 이유로 다른 텍스트 인코딩과 함께 작업하는 경우 직접 UTF-8로 변환하거나 변환해야 합니다.
  • 다양한 옵션(예: Boost.Nowide 또는 Boost.Text)이 있습니다.
  • 내부적으로 OpenXLSXBoost.Nowide를 사용하며, 파일을 열고 std::stringstd:wstring 간에 변환할 수 있는 여러 가지 편리한 기능을 갖추고 있습니다.
  • 또한 CppCon 2014 에서 제임스 맥넬리스의 프레젠테이션을 시청하고 조엘 스폴스키의 블로그 를 읽어보는 것도 좋습니다.

  • Windows의 유니코드는 특히 어렵습니다.
  • UTF-8LinuxMacOS에서 잘 지원되지만 Windows에서는 지원이 더 제한적입니다.
  • 예를 들어, 터미널 창에 ASCII가 아닌 문자(예: 중국어 또는 일본어 문자)가 출력되면 횡설수설하는 것처럼 보일 수 있습니다.
  • 앞서 언급했듯이 소스 파일 자체의 텍스트 인코딩도 염두에 두어야 할 때도 있습니다.
  • 일부 사용자는 ASCII가 아닌 파일 이름으로 .xlsx 파일을 열거나 만들 때 OpenXLSX가 충돌하는 문제가 있었는데, 테스트 프로그램의 소스 코드UTF-8 인코딩이 아닌 것으로 밝혀졌기 때문에 OpenXLSX에 입력되는 문자열도 UTF-8이 아닌 것으로 나타났습니다.
  • 정상 상태를 유지하려면 소스 코드 파일은 항상 UTF-8 파일에 있는 것이 좋으며, 제가 아는 모든 IDEUTF-8 인코딩의 소스 코드 파일을 처리할 수 있습니다. Windows🤮의 멋진 유니코드 세계에 오신 것을 환영합니다

Zip 라이브러리

  • 엑셀 파일은 기본적으로 .zip 아카이브로 포장된 .xml 파일 묶음에 불과합니다.
  • OpenXLSX는 타사 라이브러리를 사용하여 .zip 아카이브에서 .xml 파일을 추출합니다.
  • OpenXLSX에서 사용하는 기본 라이브러리는 미니즈를 중심으로 한 객체 지향 래퍼인 Zippy입니다.
  • 미니즈 라이브러리는 빠르고 헤더 전용으로, OpenXLSX에 이상적입니다.

  • 하지만 원한다면 다른 지퍼 라이브러리를 사용할 수도 있습니다.
  • 드물게 미니즈의 안정성 문제가 발생할 수도 있습니다.
  • 이러한 경우 다른 지퍼 라이브러리를 사용해 보는 것이 유용할 수 있습니다.

  • Zippy/miniz 라이브러리를 사용하려면 특별한 노력이 필요하지 않으며, 즉시 사용할 수 있습니다.
  • 하지만 다른 Zip 라이브러리를 사용하려면 몇 가지 작업이 필요합니다.

  • 다른 Zip 라이브러리를 사용하려면 IZipArchive 클래스에서 지정한 인터페이스를 준수하는 래퍼 클래스를 만들어야 합니다.
  • 이 클래스는 형식 삭제를 사용하여 구현되므로 상속이 필요하지 않으며 클래스에 적합한 인터페이스만 있으면 됩니다.
  • 그런 다음 클래스의 개체를 제공하고 OpenXLSX 생성자에게 제공합니다.

  • 이 작업의 예를 보려면 예제 폴더에서 데모1A를 살펴보세요. 이 예제에서는 예제/외부/커스텀Zip 아래에서 찾을 수 있는 커스텀Zip(libzipzip 라이브러리로 사용)이라는 클래스를 사용합니다.
  • 예제 프로그램을 구축하려면 컴퓨터에 libzip(및 종속성)이 설치되어 있는지 확인하고 OpenXLSX 루트의 CMakeLists.txt 파일에서 OPENXLSX_ENABLE_LIBZIP 옵션을 활성화합니다.

  • 앞서 언급했듯이 데모1A 예제 프로그램은 libzip을 사용합니다.
  • libzip은 매우 안정적인 라이브러리이며 널리 사용되고 있습니다.
  • 하지만 제 경험에 따르면 대형 스프레드시트와 같은 대형 zip 파일의 경우 상당히 느립니다.
  • 이러한 이유로 libzip이 이상적인 솔루션은 아니지만 다른 zip 라이브러리를 어떻게 사용할 수 있는지 보여주는 데 유용합니다.

예제 프로그램

  • 'Examples' 폴더에는 OpenXLSX 사용 방법을 설명하는 몇 가지 예제 프로그램이 있습니다.
  • 이러한 예제 프로그램을 공부하는 것이 OpenXLSX 사용 방법을 배우는 가장 좋은 방법입니다.
  • 예제 프로그램에는 주석이 달려 있으므로 상황을 비교적 쉽게 이해할 수 있습니다.
      XLDocument doc;
      doc.create("./Demo01.xlsx", XLForceOverwrite);
      auto wks = doc.workbook().worksheet("Sheet1");
      
      wks.cell("A1").value() = 3.14159265358979323846;
    
      XLCellValue A1 = wks.cell("A1").value();
      
      double vA1 = wks.cell("A1").value();
    

라이선스

  • BSD-3-Clause



  • 도움이 되셨으면 하단의 ❤️ 공감 버튼 부탁 드립니다. 감사합니다! 😄
  • 일부 모바일 환경에서는 ❤️ 버튼이 보이지 않습니다.

728x90
반응형
반응형

다양한 언어에서의 Tuple과 불변성에 대한 이해

Tuple은 다양한 프로그래밍 언어에서 데이터 집합을 효율적으로 표현하는 자료 구조로 사용됩니다. 여러 개의 값을 하나의 묶음으로 표현할 수 있다는 점에서 배열과 유사하지만, 다루는 방식이나 특성은 언어에 따라 차이를 보입니다. 특히, 불변성(Immutable)의 여부는 언어마다 다르게 구현될 수 있습니다. 이번 글에서는 여러 언어에서의 Tuple 개념과 불변성에 대해 알아보겠습니다.


Python의 Tuple

Python의 tuple은 대표적인 불변 자료 구조입니다. 생성된 후에는 요소를 수정, 추가, 삭제할 수 없습니다. 이러한 불변성은 코드에서 의도하지 않은 데이터 변조를 방지하고, 메모리 사용 효율을 높이는 데 기여합니다. tuple은 소괄호 ()를 사용해 정의되며, 여러 자료형을 함께 저장할 수 있습니다.

예제:

my_tuple = (10, 20, 30)
# my_tuple[1] = 40  # 오류 발생: 요소를 변경할 수 없음

C++의 Tuple

C++에서는 std::tuple을 사용해 다양한 자료형을 하나로 묶을 수 있습니다. 그러나 std::tuple 자체는 불변성을 강제하지 않으며, 필요에 따라 const 키워드를 사용해 요소의 변경을 막을 수 있습니다. 따라서 C++에서 tuple을 불변으로 사용할지 여부는 프로그래머의 선택에 달려 있습니다.

예제:

const std::tuple<int, std::string> myTuple(1, "Hello");
// myTuple은 불변으로 정의됨

Swift의 Tuple

Swift의 튜플은 직관적이며 여러 값을 쉽게 묶을 수 있도록 합니다. 하지만 기본적으로 불변성을 갖지 않으며, let 키워드를 사용해 불변성을 지정할 수 있습니다. 이렇게 하면 튜플의 값을 수정할 수 없게 됩니다.

예제:

let myTuple = (404, "Not Found")
// myTuple은 불변이므로 수정할 수 없음

JavaScript와 TypeScript의 Tuple

JavaScript는 tuple 개념을 제공하지 않지만, TypeScript에서는 정해진 순서와 자료형을 갖는 tuple을 정의할 수 있습니다. 불변성을 보장하기 위해 const 키워드를 사용할 수 있지만, 여전히 요소의 값을 변경할 수 있는 점은 주의가 필요합니다.

예제 (TypeScript):

const myTuple: [number, string] = [1, "Hello"];
// 요소 값은 여전히 변경 가능

Haskell의 Tuple

Haskell에서는 모든 값이 기본적으로 불변성을 갖습니다. 따라서 Haskell의 tuple 역시 불변이며, 데이터의 무결성을 보장합니다. 이러한 특성은 함수형 프로그래밍의 철학과 일치합니다.

예제:

let myTuple = (1, "Hello", 3.14)
-- myTuple의 요소는 수정할 수 없음

결론

Tuple은 언어마다 특성과 활용 방법이 다릅니다. Python과 Haskell에서는 tuple이 불변성을 갖지만, C++, Swift, TypeScript에서는 필요에 따라 불변성을 구현할 수 있습니다. 이처럼 tuple의 불변성 여부는 언어 설계 철학과 목적에 따라 결정되며, 효율적인 데이터 관리를 위해 각 언어의 특징을 이해하는 것이 중요합니다.

728x90
반응형
반응형

SOCI : C++ 데이터베이스 액세스 라이브러리

SOCI는 표준 C++ 범위 내에서 일반 C++ 코드에 SQL 쿼리를 내장한 것 같은 효과를 내는 C++용 데이터베이스 액세스 라이브러리입니다.

이 아이디어는 C++ 프로그래머에게 가장 자연스럽고 직관적인 방식으로 SQL 데이터베이스에 액세스할 수 있는 방법을 제공하는 것입니다. 기존 라이브러리가 필요에 비해 너무 어렵거나 방해가 된다면 SOCI가 좋은 대안이 될 수 있습니다.

단일 행을 검색해야 하는 SQL 쿼리에 대한 가장 간단한 동기 부여 코드 예는 다음과 같습니다.

int id = ...;
string name;
int salary;

sql << "select name, salary from persons where id = " << id,
       into(name), into(salary);

그리고 객체 관계 매핑에 대한 광범위한 지원으로 다음과 같은 이점을 얻을 수 있습니다.

int id = ...;
Person p;

sql << "select first_name, last_name, date_of_birth "
       "from persons where id = " << id,
       into(p);

STL과의 통합도 지원됩니다.

Rowset<string> rs = (sql.prepare << "select name from persons");
copy(rs.begin(), rs.end(), ostream_iterator<string>(cout, "\n"));

SOCI는 Boost 데이터 유형(선택 사항, 튜플 및 퓨전)과의 광범위한 통합과 사용자 정의 데이터 유형에 대한 유연한 지원을 제공합니다.

SOCI는 주로 C++ 라이브러리이지만, 다른 프로그래밍 언어에서도 사용할 수 있습니다. 현재 패키지에는 Ada 바인딩이 포함되어 있으며, 앞으로 더 많은 바인딩이 추가될 가능성이 있습니다.

2.0.0 릴리스부터 SOCI는 백엔드에 플러그인 아키텍처를 사용합니다. 이를 통해 다양한 데이터베이스 서버를 타겟팅할 수 있습니다. 현재(4.0.2) 다음 데이터베이스 시스템이 지원됩니다.

  • DB2
  • Firebird
  • MySQL
  • ODBC (generic backend)
  • Oracle
  • PostgreSQL
  • SQLite3

라이브러리의 의도는 가능한 한 많은 데이터베이스 기술을 포괄하는 것입니다. 이를 위해 프로젝트는 기존 데이터베이스 인터페이스에 대한 전문 지식을 가지고 있고 전담 백엔드 작성을 돕고 싶어하는 다른 프로그래머의 자원 봉사 기여에 의존해야 합니다. 참여에 관심이 있으시면 프로젝트 관리자 에게 문의하세요.

SOCI 라이브러리는 Boost 소프트웨어 라이선스 조건에 따라 배포됩니다.

모든 SOCI 다운로드는 SourceForge.net 서버에 호스팅됩니다. 현재 안정적인 릴리스(4.0.2)는 여기 에서 다운로드할 수 있으며 , 모든 이전 릴리스는 여기 에서 사용할 수 있습니다 .

SOCI 개발은 GitHub 에서 이루어집니다. 모든 저장소는 모든 Git 저장소가 사용 가능한 SOCI 조직에 속합니다.

SOCI 소스 코드가 있는 기본 Git 저장소는 다음을 사용하여 복제할 수 있습니다.

$ git clone git://github.com/SOCI/soci.git

이슈 추적기 는 버그 보고와 패치 제출을 위해 열려 있습니다.

SOCI에 기여하는 가장 좋은 방법은 일반적인 GitHub 워크플로를 따르는 것입니다. SOCI를 포크하고, 편집 내용을 적용하고, 풀 리퀘스트 를 제출하세요. SOCI 개발에 자유롭게 참여하세요!

다른 사용자를 만나려면 SOCI 사용자 메일링 목록 에 가입하는 것을 고려하세요. 개발 토론에만 전념하는 SOCI 개발자 메일링 목록 도 있습니다.

또한 GitHub에서 커뮤니티 중심의 위키FAQ 가 호스팅되고 있으며, 누구나 참여할 수 있습니다.




  • 도움이 되셨으면 하단의 ❤️ 공감 버튼 부탁 드립니다. 감사합니다! 😄
  • 일부 모바일 환경에서는 ❤️ 버튼이 보이지 않습니다.

728x90
반응형
반응형

Python 가상환경 venv 입문 가이드: 생성부터 활용까지

  • venv를 사용하여 독립적인 파이썬 가상환경을 설정하고 사용하는 방법을 자세히 안내드리겠습니다.

1. venv란?

  • venv는 Python 표준 라이브러리에 포함된 가상환경 생성 도구로, 프로젝트마다 독립된 환경을 만들어 서로 다른 Python 버전과 패키지를 관리할 수 있도록 도와줍니다.

2. venv 설치 준비

  • Python 3.3 이상 버전에서 기본적으로 제공됩니다.
    • 다음과 같은 명령으로 파이썬 버전을 확인하세요.
      python3 --version
      
  • 파이썬이 없으시면 다음 경로에서 다운로드하시면 됩니다.

3. venv 가상환경 생성

  1. 가상환경 생성 명령어 실행:
    • 다음과 같은 명령으로 가상환경을 생성합니다.
    python3 -m venv 가상환경_폴더명
    
    • 예제> myenv 라는 가상환경 폴더를 생성합니다.
    python3 -m venv myenv
    
  2. 결과:
    • 지정한 폴더(myenv) 안에 가상환경 디렉토리가 생성됩니다.
    • 주요 폴더:
      • bin (Linux/Mac) 또는 Scripts (Windows) : 활성화/비활성화 스크립트 포함.
      • lib : Python 패키지 저장소.
      • include : 헤더 파일 저장소.

4. 가상환경 활성화

  • Linux/Mac:

    • 다음과 같은 명령으로 가상환경을 활성화 합니다.
    source 가상환경_폴더명/bin/activate
    
    • 예제> myenv 디렉토리의 가상환경을 활성화합니다.
    source myenv/bin/activate
    
  • Windows (CMD):

    • 다음과 같은 명령으로 가상환경을 활성화 합니다.
    가상환경_폴더명\Scripts\activate
    
    • 예제> myenv 디렉토리의 가상환경을 활성화합니다.
    myenv\Scripts\activate
    
  • Windows (PowerShell):

    • 다음과 같은 명령으로 가상환경을 활성화 합니다.
    .\가상환경_폴더명\Scripts\Activate.ps1
    
    • 예제> myenv 디렉토리의 가상환경을 활성화합니다.
    .\myenv\Scripts\Activate.ps1
    
  • 활성화 확인:

    • 활성화된 상태에서는 프롬프트 앞에 가상환경 이름이 표시됩니다.
      (myenv) $ 
      

5. 패키지 설치

  • 활성화된 상태에서 원하는 패키지를 설치합니다.

    pip install 패키지명
    
  • 예제> 필요한 라이브러리(requests, flask)를 설치합니다.

    pip install requests flask
    
  • pip install -U를 입력하면, 라이브러리가 상위 버전으로 업그레이드(Upgrade)가 됩니다.

  • 특정 버전의 라이브러리에서만 작동하는 코드일 경우 다음과 같은 명령어로 설치하세요.

    • 예제> pip install numpy==1.21.0

6. 설치된 패키지 확인

  • 현재 가상환경에 설치된 패키지를 확인하려면, 다음 명령을 입력합니다.
    pip list
    

7. 가상환경 비활성화

  • 가상환경 사용을 종료하려면, activate 명령이 있는 경로에서 다음 명령을 입력합니다.
    deactivate
    

8. 가상환경 삭제

  • 가상환경을 삭제하려면 해당 폴더를 제거하면 됩니다.

    # 리눅스 또는 bash 인 경우,
    rm -rf 가상환경_폴더명
    
  • 예제> 가상환경 myenv를 삭제합니다.

    rm -rf myenv
    

9. 유용한 팁

  • 특정 Python 버전(version)으로 가상환경 생성하려면, 다음과 같은 명령어를 입력합니다.

    python3.x -m venv 가상환경_폴더명
    
  • 예제> 가상환경 myenv를 파이썬 3.9 버전으로 생성합니다.

    python3.9 -m venv myenv
    
  • 패키지(라이브러리) 의존성(dependency)을 기록 및 복원

    • 의존성을 기록하면 다음과 같이 입력합니다.
      # requirements.txt 파일에 현재 가상환경의 의존성을 기록
      pip freeze > requirements.txt
      
    • 의존성을 복원하려면 다음과 같이 입력합니다.
      # requirements.txt 파일에 있는 의존성 파일들을 현재 가상환경에 설치(복원)
      pip install -r requirements.txt
      
728x90
반응형
반응형

QHotkey : 데스크톱 Qt 애플리케이션을 위한 글로벌 단축키/핫키

Desktop Qt-Applications를 위한 글로벌 단축키shortcut/핫키hotkey 입니다.

QHotkey는 핫키/글로벌 단축키를 만드는 데 사용할 수 있는 클래스로, 애플리케이션 상태와 무관하게 어디에서나 작동하는 단축키입니다.

즉, 애플리케이션이 활성화, 비활성화, 최소화 또는 전혀 표시되지 않더라도 단축키를 받을 수 있습니다.

특징

  • Windows, Mac 및 X11에서 작동합니다.
  • 사용이 간편하고 QKeySequence를 사용하여 간편한 단축키 입력이 가능합니다.
  • 거의 모든 일반 키 지원(OS 및 키보드 레이아웃에 따라 다름)
  • 키/수정자 조합을 직접 입력할 수 있습니다.
  • 동일한 단축키에 대해 여러 QHotkey 인스턴스 지원(최적화 포함)
  • 스레드 안전 - 모든 스레드에서 사용 가능(스레드 안전 섹션 참조)
  • 필요한 경우 기본 키코드 및 수정자 사용 허용

참고: 현재 Wayland는 지원되지 않습니다. Wayland로 글로벌 단축키를 등록할 수 없기 때문입니다. 자세한 내용이나 Wayland에서 단축키를 작동시키는 방법에 대한 아이디어는 Issue #14 를 참조하세요.

빌딩

QHotkey는 Qt6와 Qt5를 모두 지원합니다. Qt6를 사용하는 경우 버전 6.2.0 이상이 필요합니다. CMake 빌드 시스템을 사용하여 빌드할 수 있습니다.

CMake

CMake QT_DEFAULT_MAJOR_VERSION 변수는 빌드에 사용되는 Qt의 주요 버전을 제어하며 기본값은 5입니다. 예를 들어, Qt6로 빌드하려면 CMake 명령줄 옵션 -DQT_DEFAULT_MAJOR_VERSION=6을 사용합니다. 테스트 애플리케이션 QHotkeyTest를 빌드하려면 -DQHOTKEY_EXAMPLES=ON을 지정합니다.

CMake 예제:

$ cd QHotkey
$ cmake -B build -S . -DQT_DEFAULT_MAJOR_VERSION=6
$ cmake --build build
# cmake --install build

설치

패키지는 qpm 패키지, de.skycoder42.qhotkey 로 제공됩니다. qpmx(선호)를 통해 또는 qpm을 통해 직접 설치할 수 있습니다.

qpmx를 통해

qpmx 는 추가 기능이 있는 qpm(및 기타 도구)의 프런트엔드이며, 패키지를 설치하는 데 선호되는 방법입니다. 사용하려면:

  1. qpmx 설치 (GitHub - 설치 참조)
  2. qpm 설치 (GitHub - 설치 참조, Windows의 경우 아래 참조)
  3. 프로젝트 루트 디렉토리에서 qpmx install de.skycoder42.qhotkey를 실행합니다.

qpm을 통해

  1. qpm 설치 (GitHub - 설치 참조, Windows의 경우 아래 참조)
  2. 프로젝트 루트 디렉토리에서 qpm install de.skycoder42.qhotkey를 실행합니다.
  3. .pro 파일에 include(vendor/vendor.pri)를 추가하여 프로젝트에 qpm을 포함합니다.

qpm에 대해 자세히 알아보려면 GitHub - 앱 개발자를 위한 사용 설명서 를 확인하세요.

Windows 사용자에게 중요: QPM 버전 0.10.0(웹사이트에서 다운로드할 수 있는 버전)은 현재 Windows에서 작동하지 않습니다! 마스터에서 이미 수정되었지만 아직 출시되지 않았습니다. 새 버전이 출시될 때까지 여기에서 최신 개발 빌드를 다운로드할 수 있습니다.

사용법

일반적인 사용법은 특정 단축키에 대한 QHotkey 인스턴스를 생성하고 이를 등록한 다음 단축키를 눌렀을 때 방출되는 신호에 간단히 연결하는 것입니다.

다음 예제는 Ctrl+Alt+Q(Mac에서는 ++Q) 키 조합을 누를 때까지 백그라운드에서 창 없이 실행되는 간단한 애플리케이션을 보여줍니다. 이렇게 하면 애플리케이션이 종료됩니다. 디버그 출력은 핫키가 성공적으로 등록되었는지, 그리고 눌렸는지 알려줍니다.

#include <QHotkey>
#include <QApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
	QApplication app(argc, argv);

	QHotkey hotkey(QKeySequence("Ctrl+Alt+Q"), true, &app); //The hotkey will be automatically registered
	qDebug() << "Is segistered:" << hotkey.isRegistered();

	QObject::connect(&hotkey, &QHotkey::activated, qApp, [&](){
		qDebug() << "Hotkey Activated - the application will quit now";
		qApp->quit();
	});

	return app.exec();
}

참고: 이 작업을 수행하려면 .pri include가 필요합니다.

테스트

./HotkeyTest에서 예제를 실행하면 QHotkey 클래스를 테스트할 수 있습니다. 4개의 섹션이 있습니다.

  • Playground: 여기에 몇 가지 시퀀스를 입력하고 다양한 키 조합으로 시도해 볼 수 있습니다.
  • Testings: 선택된 단축키 목록입니다. 활성화하고 어떤 단축키가 당신에게 맞는지 시도해보세요 (힌트: OS와 키보드 레이아웃에 따라 몇 가지는 작동하지 않을 가능성이 매우 높습니다).
  • Threading: 플레이그라운드의 핫키 2개를 스레드로 분리하려면 체크박스를 활성화합니다. 아무런 차이 없이 작동해야 합니다.
  • Native Shortcut: 네이티브 단축키를 직접 사용해 볼 수 있습니다.

로깅

기본적으로 QHotkey는 무언가 잘못되면(예: 번역할 수 없는 키) 경고 메시지를 출력합니다. QHotkey의 모든 메시지는 QLoggingCategory "QHotkey"로 그룹화됩니다. 로깅을 비활성화하려면 코드 어딘가에 다음 함수를 호출합니다.

QLoggingCategory::setFilterRules(QStringLiteral("QHotkey.warning=false"));

이렇게 하면 QHotkey의 모든 경고가 꺼집니다(지금은 경고만 사용하므로 이것으로 충분합니다). 로깅 범주로 할 수 있는 모든 작업에 대한 자세한 내용은 Qt 문서를 확인하세요.

스레드 안전성

QHotkey 클래스 자체는 재진입 가능합니다. 즉, 모든 스레드에서 필요한 만큼 많은 인스턴스를 만들 수 있습니다. 이를 통해 모든 스레드에서 QHotkey를 사용할 수 있습니다. 하지만 인스턴스가 속한 스레드와 다른 스레드에서는 QHotkey 인스턴스를 사용해서는 안 됩니다! 내부적으로 시스템은 핫키 이벤트를 처리하고 이를 QHotkey 인스턴스에 분배하는 싱글톤 인스턴스를 사용합니다. 이 내부 클래스는 완전히 스레드 안전합니다.

그러나 이 싱글톤 인스턴스는 메인 스레드에서만 실행됩니다. (한 가지 이유는 일부 OS 함수가 스레드 안전하지 않기 때문입니다.) 스레드 핫키를 가능하게 하기 위해 중요한 함수(핫키 등록/등록 해제 및 키 변환)도 모두 메인 스레드에서 실행됩니다. 다른 스레드의 QHotkey 인스턴스는 Qt::BlockingQueuedConnection과 함께 QMetaObject::invokeMethod를 사용합니다.

여러분에게 이는 다음을 의미합니다. 메인 스레드가 아닌 다른 스레드의 QHotkey 인스턴스는 핫키를 등록/등록 해제/변환하는 데 약간 더 오래 걸릴 수 있습니다. 메인 스레드가 이를 대신 수행할 때까지 기다려야 하기 때문입니다. 중요: 그러나 이 기능에는 한 가지 추가 제한이 있습니다. 메인 스레드가 아닌 다른 스레드의 QHotkey 인스턴스는 메인 이벤트 루프가 끝나기 전에 등록 해제되거나 파괴되어야 합니다. 그렇지 않으면 핫키 파괴 시 애플리케이션이 중단됩니다. 이 제한은 메인 스레드의 인스턴스에는 적용되지 않습니다. 또한 루프가 시작되기 전에 단축키를 변경하거나 등록/등록 해제하는 경우에도 실제로 시작될 때까지 동일한 일이 발생합니다.

문서

문서는 릴리스 버전과 github 페이지 에서 사용할 수 있습니다.

문서는 doxygen 을 사용하여 작성되었습니다. 여기에는 HTML 문서와 Qt-Help 파일이 포함되어 있으며, 이를 QtCreator(QtAssistant)에 포함시켜 F1-Help를 표시할 수 있습니다(자세한 내용은 외부 문서 추가를 참조하세요).

기술적

요구 사항

  • 명시적 지원은 최신 Qt LTS에만 제공되지만 이전 버전에서도 작동할 수 있습니다.
  • 최소한 QtGui-Module(QGuiApplication). 콘솔 기반 애플리케이션의 단축키는 지원되지 않습니다(운영 체제에서). 그러나 보이는 창 없이 GUI 애플리케이션을 만들 수 있습니다.
  • C++11

알려진 제한 사항

  • 단일 키/수정자 조합만 가능합니다. QKeySequence를 사용하는 경우 시퀀스의 첫 번째 키+수정자만 사용됩니다.
  • Qt::Key는 일반 숫자와 숫자패드 숫자 사이에 차이를 두지 않습니다. 그러나 대부분의 키보드는 이것을 요구합니다. 따라서 네이티브 단축키를 사용하지 않는 한 숫자패드에 대한 단축키를 등록할 수 없습니다.
  • 모든 키를 지원하지는 않지만, 일반적인 키는 대부분 지원합니다. 플랫폼 간에 차이가 있으며 키보드 레이아웃에 따라 달라집니다. 예를 들어 "Delete"는 Windows와 Mac에서는 작동하지만 X11에서는 작동하지 않습니다(적어도 제 테스트 머신에서는 그렇습니다). 가능한 한 OS 함수를 사용하려고 했지만, Qt::Key 값을 네이티브 키로 변환해야 하기 때문에 몇 가지 제한이 있습니다. 필요한 키를 사용할 수 있으므로 네이티브 단축키를 사용해 보세요.
  • 등록된 키는 QHotkey에서 "취득"됩니다. 즉, 핫키가 애플리케이션에서 사용된 후에는 활성 애플리케이션으로 전송되지 않습니다. 이는 운영 체제에서 이런 방식으로 수행되며 변경할 수 없습니다.
  • X11에서 QHotkey: Failed to register hotkey. Error: BadAccess (attempt to access private resource denied) 오류가 발생하는 경우 X11에 개인용 핫키를 등록하려고 한다는 의미입니다. 이러한 키는 일반 API를 사용하여 등록할 수 없습니다.
728x90
반응형
반응형

SQLite DB와 CSV 파일 간 데이터 변환

데이터를 다루다 보면 CSV 파일과 SQLite 데이터베이스(DB) 파일 간의 변환이 필요한 경우가 많습니다. Python의 pandassqlite3 모듈을 활용하면 CSV 파일을 SQLite DB로 변환하거나, 반대로 SQLite DB를 CSV 파일로 변환하는 작업을 간단히 수행할 수 있습니다. 이 글에서는 각 변환 과정의 방법과 코드를 단계별로 설명합니다.

1. CSV 파일을 SQLite DB 파일로 변환하기

필요한 모듈 설치

pandas는 데이터를 처리하고 변환하는 데 유용한 라이브러리입니다. 설치가 필요하다면 다음 명령어를 실행합니다.

pip install pandas

CSV 파일을 SQLite DB로 변환하는 코드

아래 코드는 CSV 파일을 SQLite DB 파일로 변환하는 코드입니다. CSV 파일을 읽어와 SQLite 데이터베이스에 저장할 수 있습니다.

import pandas as pd
import sqlite3

# CSV 파일 불러오기
df = pd.read_csv('your_file.csv')

# SQLite DB 연결 생성 및 테이블에 데이터 입력
conn = sqlite3.connect('your_database.db')
df.to_sql('your_table_name', conn, if_exists='replace', index=False)

# 연결 종료
conn.close()

코드 설명

  • pandasread_csv 함수로 CSV 파일을 읽습니다.
  • sqlite3connect 함수로 SQLite DB를 생성하거나 연결한 뒤, to_sql 함수를 사용해 DataFrame을 DB의 테이블로 변환해 저장합니다.
  • if_exists='replace'는 동일한 이름의 테이블이 있을 경우 덮어쓰기합니다.
  • 작업이 끝나면 conn.close()로 연결을 종료합니다.

2. SQLite DB 파일을 CSV 파일로 변환하기 (역변환)

이번에는 SQLite DB 파일을 CSV 파일로 내보내는 방법을 알아보겠습니다.

필요한 모듈 설치
위와 마찬가지로 pandas가 필요합니다. 설치가 필요하면 다음 명령어를 사용하세요.

pip install pandas

SQLite DB를 CSV 파일로 변환하는 코드

아래 코드는 SQLite DB 파일에서 데이터를 읽어와 CSV 파일로 저장하는 예제입니다.

import pandas as pd
import sqlite3

# SQLite DB 연결 및 테이블에서 데이터 불러오기
conn = sqlite3.connect('your_database.db')
df = pd.read_sql_query("SELECT * FROM your_table_name", conn)

# 데이터프레임을 CSV 파일로 저장
df.to_csv('output_file.csv', index=False)

# 연결 종료
conn.close()

코드 설명

  • pandasread_sql_query로 지정한 SQLite DB 테이블 데이터를 DataFrame으로 불러옵니다.
  • to_csv 함수를 사용하여 DataFrame을 CSV 파일로 저장합니다.
  • index=False를 설정해 DataFrame의 인덱스 값이 CSV 파일에 포함되지 않도록 합니다.
  • 마지막으로 conn.close()로 연결을 종료하여 작업을 마칩니다.

결론

위와 같이 Python의 pandassqlite3 모듈을 활용하여 CSV 파일을 SQLite DB 파일로 변환하거나, 반대로 SQLite DB 파일을 CSV 파일로 변환하는 방법을 손쉽게 구현할 수 있습니다. 이를 통해 데이터 처리 과정에서 다양한 파일 포맷을 자유롭게 활용할 수 있습니다.

728x90
반응형
반응형

Recurse : 미들웨어 디자인을 갖춘 Qt 기반 마이크로 웹 프레임워크

리커즈(Recurse)는 두 세계의 모든 최고의 기능을 활용하는 Qt 라이브러리를 사용하여 최신 C++(14)로 작성된 최신 웹 마이크로 프레임워크가 될 것으로 예상됩니다.

우리는 깔끔하고 이해하기 쉬운 코드를 작성하는 데 중점을 두고, 기여를 장려하기 위해 템플릿 사용을 피합니다.

리커즈는 코어에 미들웨어가 번들로 제공되지 않는 소형을 목표로 합니다.

이를 통해 차세대 웹 애플리케이션과 API를 작성하는 데 매우 견고할 수 있을 것입니다.

Node.js, koa 및 Express 마이크로 프레임워크에서 영감을 받았습니다.

예제

#include "recurse.hpp"

int main(int argc, char *argv[])
{
    Recurse app(argc, argv);

    // logger
    app.use([](auto &ctx, auto next)
    {
        qDebug() << ctx.request.ip;
        next();
    });

    // hello world
    app.use([](auto &ctx)
    {
        ctx.response.send("Hello world");
    });

    app.listen(3000);
};

설치

이것은 헤더 전용 라이브러리입니다.

사용하려면 프로젝트 내에 recurse.hpp를 포함하기만 하면 됩니다.

자세한 내용은 예시를 참조하세요.

참고 recurse.hpp가 다음에 종속적이므로, context.hpp, request.hpp, response.hpp도 필요합니다.

미들웨어

핵심에는 미들웨어가 포함되어 있지 않습니다.

예를 들어 라우팅의 경우 라우터 를 사용할 수 있습니다.

#include "router.hpp"

int main(int argc, char *argv[])
{
    Recurse app(argc, argv);

    Module::Router router;

    router.GET("/hello/:user", [](auto &ctx, auto /* next */)
    {
        ctx.response.send("Hello World " + ctx.request.params["user"]);
    });

    app.listen();
}

404 - Not Found

기본적으로 미들웨어가 응답하지 않으면 RecurseNot Found 메시지와 404 HTTP 오류 코드로 응답합니다.

자신의 응답을 만들려면 목록 에 새 미들웨어를 추가하기만 하면 됩니다.

// if any middleware before this responds this won't get called
app.use([](auto &ctx)
{
    ctx.response.status(404).send("Custom Not Found");
});

전체 예를 보려면 404 예제 를 참조하세요.

첫 번째 미들웨어로도 사용할 수 있습니다(이미 기록 등을 수행하는 첫 번째 미들웨어가 있는 경우)

app.use([](auto &ctx, auto next, auto prev)
{
    next([&ctx, prev]
    {
        // this is last code to be called before sending response to client
        if(ctx.response.status() == 404)
            ctx.response.body("Custom Not Found");

        prev();
    });
});

스타일링

코드를 작성할 때는 제공된 .clang-format 파일을 사용하세요.

vim에서 사용할 수 있는 좋은 vim-clang-format 플러그인이 있습니다.

수동으로 호출할 수도 있습니다

clang-format -i source.hpp

# to format all files
find . -name "*.hpp" -or -name "*.cpp" | xargs clang-format -i

그리고 단축키 명령도 사용할 수 있습니다

clang-format -i -style="{BasedOnStyle: WebKit, PointerAlignment: Right, Standard: Cpp11, TabWidth: 4, UseTab: Never, BreakBeforeBraces: Allman, AllowShortFunctionsOnASingleLine: false, ContinuationIndentWidth: 0, MaxEmptyLinesToKeep: 1, NamespaceIndentation: All, AccessModifierOffset: 0}" source.hpp
728x90
반응형

+ Recent posts