특성 pgvector FAISS Pinecone
설정 난이도 ● 중간
– PostgreSQL 설치 및 CREATE EXTENSION vector 필요
● 낮음
– pip install faiss-cpu 로 즉시 사용 가능
● 낮음
– 라이브러리 설치 후 API 키 설정 필요
메타데이터 필터링 ● 강력
– SQL WHERE·JOIN으로 사전 필터링 가능
● 제한적
– 검색 후 애플리케이션 레벨 후처리 필요
● 지원
– 쿼리 시 메타데이터 필터 인수로 사용 가능
비용 ● 무료 오픈소스
– 인프라(서버) 비용 별도
● 무료 오픈소스 ● 유료 매니지드 서비스
– 사용량 기반 과금
네트워크 의존도 ● 로컬/사내 네트워크
– DB 서버 필요(실습시로컬도 가능)
● 오프라인 지원
– 완전 로컬 실행 가능
● 원격 호출 필수
– 네트워크 레이턴시 존재
운영·모니터링 ● 기존 Postgres 툴
(PgAdmin, Datadog 등) 활용
● 별도 구축 필요
– 모니터링·백업 전략 직접 수립
● 관리형 대시보드·모니터링 제공
저장공간 ● Postgres 테이블 내에 벡터∙메타데이터 저장
– DB 크기에 비례
– 백업/압축 툴 활용 가능
● 기본은 메모리 인덱스
– save_local() 시 로컬 파일(index.faiss) 생성
– 디스크 사용량 ≈ 4바이트×dim×N + 인덱스 오버헤드
– PQ 등 압축 옵션 가능
● 매니지드 스토리지
– 사용량 기반 과금에 스토리지 포함
– 자동 복제·압축 옵션 제공
– 백업·고가용성 내장

 

반응형

'Programming > LLM RAG' 카테고리의 다른 글

Pinecone  (0) 2025.06.13
LangChain/LangGraph  (0) 2025.06.13
TensorRT-LLM  (1) 2025.06.13
SGLang  (0) 2025.06.13
vLLM  (0) 2025.06.12

 

순서

먼저 https://app.pinecone.io/ 방문해서 api-key를 생성한다.

 

vs pgvector

  • pgvector
    • 이미 PostgreSQL 기반 인프라가 있고, 자체 호스팅을 선호할 때
    • SQL과 벡터를 한 곳에서 관리하며, 커스터마이징·확장성을 직접 책임지고 싶을 때
  • Pinecone
    • “운영 부담 없이” 곧바로 대규모 서비스 전환이 필요할 때
    • 메타데이터·하이브리드 검색·자동 스케일링 같은 고급 기능을 즉시 활용

 

실습

 

#!/usr/bin/env python3
"""
demo_pinecone.py ─ Pinecone 4.x + OpenAI 임베딩 실습
"""

import os, sys, time, logging
from dotenv import load_dotenv
import openai
from pinecone import Pinecone, ServerlessSpec      # ⬅️ 새 방식

# ──────── 로그 설정 ────────
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    datefmt="%H:%M:%S",
)
log = logging.getLogger(__name__)

# ──────── 환경 변수 읽기 ────────
load_dotenv()
try:
    OPENAI_API_KEY  = os.environ["OPENAI_API_KEY"]
    PINECONE_API_KEY = os.environ["PINECONE_API_KEY"]
    PINECONE_ENV     = os.environ["PINECONE_ENV"]    # ex) us-east-1-aws
except KeyError as e:
    log.error("환경변수 %s 가 없습니다 (.env 확인)", e.args[0]); sys.exit(1)

openai.api_key = OPENAI_API_KEY

# Pinecone 인스턴스 생성
pc = Pinecone(api_key=PINECONE_API_KEY)

# env 문자열을 region / cloud 로 분해 (us-east-1-aws → us-east-1 + aws)
*region, cloud = PINECONE_ENV.split("-")
REGION = "-".join(region)   # us-east-1
CLOUD  = cloud              # aws

INDEX  = "demo-index"
DIM    = 1536

# ──────── 인덱스 생성 / 재사용 ────────
def wait_ready(name):
    while True:
        state = pc.describe_index(name).status.state
        if state == "Ready":
            return
        log.info("   ↳ index status = %s … 대기 중", state)
        time.sleep(2)

if INDEX not in pc.list_indexes().names():
    log.info("새 인덱스 생성: %s", INDEX)
    pc.create_index(
        name=INDEX,
        dimension=DIM,
        metric="cosine",
        spec=ServerlessSpec(cloud=CLOUD, region=REGION),
    )
    wait_ready(INDEX)
else:
    log.info("기존 인덱스 재사용: %s", INDEX)

index = pc.Index(INDEX)

# ──────── 데이터 업서트 ────────
DOCS = [
    "쿠팡은 한국 최대의 전자상거래 기업이다.",
    "파인콘은 벡터 데이터베이스 서비스다.",
    "오픈AI는 GPT-4o 모델을 발표했다.",
    "서울의 여름은 덥고 습하다.",
    "벡터 검색은 의미 기반 유사도를 계산한다.",
]

def embed(texts):
    resp = openai.embeddings.create(
        model="text-embedding-3-small",
        input=texts,
    )
    return [d.embedding for d in resp.data]

log.info("문서 %d개 임베딩 → Pinecone 업서트", len(DOCS))
vecs = embed(DOCS)
index.upsert(
    vectors=[(f"id-{i}", v, {"text": DOCS[i]}) for i, v in enumerate(vecs)]
)

# ──────── 질의 ────────
QUESTION = "유사도 검색을 위한 데이터베이스"
log.info("쿼리: “%s”", QUESTION)
q_vec = embed([QUESTION])[0]

res = index.query(vector=q_vec, top_k=3, include_metadata=True)
log.info("결과 (Top-3):")
for rnk, m in enumerate(res.matches, 1):
    log.info(" %d. %s (score=%.4f)", rnk, m.metadata["text"], m.score)

log.info("완료 ✅")

 

 

반응형

'Programming > LLM RAG' 카테고리의 다른 글

vector db  (1) 2025.06.14
LangChain/LangGraph  (0) 2025.06.13
TensorRT-LLM  (1) 2025.06.13
SGLang  (0) 2025.06.13
vLLM  (0) 2025.06.12

LangChain 개요

  • LangChain은 단순한 “추론(inference) 엔진”을 넘어 LLM 애플리케이션을 짜는 데 필요한 거의 모든 구성 요소를 모아놓은 프레임워크입니다.

 

  • 추론 파이프라인을 단계별로 나눠(입력→검색→결합→생성→후처리) 관리하기 쉽게 해 줍니다.
  • 벡터 DB 통합도 플러그인처럼 끼워 쓰는 수준으로 제공해, FAISS·Pinecone·Weaviate·pgvector 등과 바로 연결할 수 있습니다.

 

사용자 규모 (GitHub Stars 기준)

 

vLLM과의 차이점

vLLM이 “고성능 텍스트 생성”에 집중한 반면, LangChain은 그 앞단·옆단을 모두 지원해 줍니다.

벡터 DB(RAG)·도구 호출·에이전트 지원

vLLM은 "성성만" 잘함

langChain은 오히려 자체 추론엔진 없음(백엔드에 vLLM·OpenAI·LLama·TensorRT 등 연결)

 

Transformer + FastAPI와의 차이점

 

  • Transformer+FastAPI:
    • 모델 불러오고, POST /generate 엔드포인트 만들어서, 분절된 코드를 직접 연결해야 함.
    • 검색(RAG)·메모리·툴 호출 같은 부가 기능은 모두 “맨땅에 헤딩”으로 처음부터 구현.
  • LangChain:
    • PromptTemplate, Retriever, Chain, Agent 클래스로 “블록 쌓듯” 조합만 하면 끝.
    • 코드량 절감과 유지보수성이 월등히 높아집니다.

주요장점

 

  • Prompt 템플릿 관리
    • 변수 바인딩, 다국어, 조건부 로직 처리까지 내장
  • 체인(Chain) 단위 워크플로우
    • 검색(Retrieval) → 요약(Summarization) → 생성(Generation) 과정을 모듈화
  • 벡터 DB 통합
    • FAISS·Pinecone·Weaviate·pgvector 등과 커넥터 제공
    • 유사도 검색 결과를 자동으로 프롬프트에 결합
  • 에이전트(Agent) 프레임워크
    • 외부 API 호출, 계산 툴, 웹 스크래핑까지 “도구(tool)”로 래핑
    • 모델이 상황에 따라 적절한 도구를 호출하도록 제어
  • 메모리·대화 관리
    • 대화형 챗봇에 필요한 세션 관리, 요약, 장기 메모리 등 지원
  • 로깅·디버깅·모니터링
    • 실행 트레이스, 토큰 사용량, 체인 단계별 출력 로그
  • 플러그인 에코시스템
    • 커스텀 컴포넌트, UI 통합, 클라우드 배포 옵션 등 풍부

 

 

LangChain이 없으면 불편한점

  • 반복 코드: prompt 작성·변경할 때마다 엔드투엔드 코드 전부 수정
  • 유사도 검색: 벡터 DB 연결·검색→프롬프트 결합 로직 직접 구현
  • 도구 호출 관리: OpenAI 함수 호출, 외부 API 체계적인 에러 핸들링 모두 수작업
  • 메모리 관리: 대화 컨텍스트 쌓기·요약·회수 로직 직접 구현
  • 디버깅 어려움: 어느 단계에서 뭘 잘못했는지 추적하기 어려움

→ 결과적으로 개발 속도 저하, 유지보수 부담 증가, 기능 확장 난이도 상승이라는 비용을 치러야 합니다.

 

LangGraph

langChain이 일종의 직선적인 체인구조라면 LangGraph는 Airflow처럼 Dag으로 분기/관리해줄 수 있게 해줌

langChain회사에서 2023년말 2024년초에 발표

반응형

'Programming > LLM RAG' 카테고리의 다른 글

vector db  (1) 2025.06.14
Pinecone  (0) 2025.06.13
TensorRT-LLM  (1) 2025.06.13
SGLang  (0) 2025.06.13
vLLM  (0) 2025.06.12

특징

 

TensorRT-LLM은 NVIDIA가 공식으로 오픈소스화한 프로젝트입니다.

오직 NVIDIA GPU + TensorRT 런타임 환경에서만 동작합니다.

 

장점

 

  • 최고 수준의 추론 성능
    • 낮은 지연(latency)·높은 처리량(throughput)
  • 퀀타이제이션·메모리 최적화
    • FP16, INT8 변환으로 VRAM 사용량 절감
  • 상용 GPU 활용 극대화
    • NVIDIA 드라이버·TensorRT 직접 제어

 

단점

 

  • vLLM은 pip install vllm만으로 시작할 수 있고, GPU가 없어도 CPU 모드로 바로 돌려볼 수 있습니다.
  • TensorRT-LLM은 CUDA, TensorRT SDK 버전 호환성, 빌드·변환 스크립트 디버깅 등을 거쳐야 합니다.
    • 모델변환도 한번 해줘야함
  • vLLM은 동적 배칭(dynamic batching), 토크나이저 변경, 파이프라인 훅(hook) 삽입 등 개발 중에 코드 수정만으로 바로 반영됩니다.
  • TensorRT-LLM은 변환된 엔진(.plan)이 고정 그래프(graph) 형태라, 모델 구조나 토크나이저를 바꾸면 다시 변환해야 합니다.
  • TensorRT-LLM 전용
    • 오직 NVIDIA GPU + TensorRT 런타임 환경에서만 동작합니다.
  • vLLM은 범용
    • NVIDIA GPU는 물론, AMD GPU (ROCm), 심지어 CPU만 있어도 구동 가능합니다.
    • 다양한 환경에서 “동작 여부 확인” → “간단 성능 테스트” → “프로덕션 전환” 워크플로우를 지원합니다.

 

따라서

 

  • vLLM으로 빠르게 기능 개발하고,
  • 안정화되면 TensorRT-LLM으로 전환해 최종 성능을 극대화

 

 

실습해본 경험

TensorRT-LLM설치

설치하는것 자체가 c++ compiler, NVCC, MPI등 여러 의존성설치 문제가 있었고 쉽지 않았다.

설치후에는 라마7b모델 받아서 모델변환하고 엔진빌드하고 서버띄운다음에 테스트하면 됐다.

모델변환은 아마 허깅페이스의 저장포맷(체크포인트)을 TensorRT용으로 바꾸는거고

엔진빌드는 커널단위로 컴파일하는걸 포함해서 빌드하는걸 말하는듯하다.

 

라마7b모델받기

이거 받을때도 허깅페이스에서 권한요청해서 메일로 승인받고서야 git clone으로 받을수 있었다. 승인은 1시간내로 금방 되긴함

mkdir -p ~/models && cd ~/models
git lfs install
git clone https://huggingface.co/meta-llama/Llama-2-7b-hf

모델변환

cd ~/workspace/TensorRT-LLM/examples/models/core/llama

python3 convert_checkpoint.py \
  --model_dir ~/models/Llama-2-7b-hf \
  --output_dir ~/workspace/TensorRT-LLM/trt_llama2_7b_ckpt_int8 \
  --dtype float16 \
  --use_weight_only \
  --weight_only_precision int8 \
  --per_channel \
  --calib_dataset wikitext \
  --calib_size 100

내 그래픽카드가 8GB짜리라서 int8로 추가로 줄이는 작업이 들어갔다.

엔진빌드

trtllm-build \
  --checkpoint_dir trt_llama2_7b_ckpt_int8 \
  --gemm_plugin auto \
  --output_dir trt_llama2_7b_engine_int8_small \
  --max_seq_len 2048 \
  --max_batch_size 1 \
  --paged_state enable

추론서버 띄우기

trtllm-serve serve trt_llama2_7b_engine_int8_small \
  --tokenizer ~/models/Llama-2-7b-hf \
  --host 0.0.0.0 \
  --port 8002 \
  --max_batch_size 1 \
  --max_seq_len 1024

테스트

curl http://localhost:8002/v1/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "trt_llama2_7b_engine_int8_small",
    "prompt": "안녕, 너 이름이 뭐야?",
    "max_tokens": 128
  }'

 

 

반응형

'Programming > LLM RAG' 카테고리의 다른 글

vector db  (1) 2025.06.14
Pinecone  (0) 2025.06.13
LangChain/LangGraph  (0) 2025.06.13
SGLang  (0) 2025.06.13
vLLM  (0) 2025.06.12

개요

sglang은 왜써요?
- vLLM은 기본적으로 local Hugging face모델을 위한 인퍼런스 엔진
- SGLang은 --providoer openai같은 옵션 한줄로 바로 OpenAI API엔드포인트를 띄울 수 있음
-- 로컬모델/OpenAI등을 동시에 서빙하거나 조건부로 라우팅하는것도 CLI/설정만으로 처리가능

 

실습

도커로 추론엔진 실행

docker run --gpus all \
  -p 8001:8001 \
  -v ~/.cache/huggingface:/root/.cache/huggingface \
  --ipc=host \
  lmsysorg/sglang:latest \
  python3 -m sglang.launch_server \
    --model-path gpt2 \
    --host 0.0.0.0 \
    --port 8001 \
    --device cuda

 

동작테스트

curl -X POST http://localhost:8001/generate \
  -H "Content-Type: application/json" \
  -d '{"prompt":"테스트 중입니다:","max_new_tokens":20}'

 

결과

sevity@DESKTOP-7500F:~$ curl -X POST http://localhost:8001/generate \
  -H "Content-Type: application/json" \
  -d '{"text":"테스트 중입니다:","sampling_params":{"max_new_tokens":20}}'
  
{"text":"더 고 중입니다. �","meta_info":{"id":"e01db0f5a42f48d99e02e9d2bcf29216","finish_reason":{"type":"length","length":20},"prompt_tokens":20,"completion_tokens":20,"cached_tokens":0,"e2e_latency":0.3301219940185547}}
sevity@DESKTOP-7500F:~$
반응형

'Programming > LLM RAG' 카테고리의 다른 글

vector db  (1) 2025.06.14
Pinecone  (0) 2025.06.13
LangChain/LangGraph  (0) 2025.06.13
TensorRT-LLM  (1) 2025.06.13
vLLM  (0) 2025.06.12

 

 

서론

요청량이 많지 않고, 단순히 “모델 하나 띄워서 한두 개의 요청만 처리”한다면 transformers + FastAPI(또는 Flask) 정도면 충분

  • 여기서 “모델 띄워주는 역할”은 Hugging Face의 transformers 라이브러리가 담당

예시

# main.py
from fastapi import FastAPI
from transformers import pipeline

app = FastAPI()

# 1) transformers 파이프라인으로 모델 로드
generator = pipeline(
    "text-generation",
    model="gpt2",            # 원하는 모델 지정
    device=0                  # GPU가 있다면 0, CPU만 있으면 -1
)

@app.post("/generate")
async def generate(payload: dict):
    prompt = payload["prompt"]
    # 2) transformers로 텍스트 생성
    outputs = generator(prompt, max_new_tokens=50)
    return {"choices": outputs}

 

또는 OpenAI 등 외부 API 사용 시:

  • 자체 GPU 없이 “OpenAI API”나 “Anthropic API”처럼 원격으로 모델을 호출한다면 vLLM은 필요 없다.

 

vLLM

  • vLLM이 빛을 발하는 순간:
    1. 자체 GPU를 보유하고 있고,
    2. 높은 동시 처리량(수십·수백 TPS)과
    3. 낮은 지연(Latency)이 요구될 때
    4. 동적 배칭, 요청 스케줄링, 스트리밍 같은 최적화 로직을
      직접 구현하지 않고 바로 활용하고 싶을 때

이런 조건이 모두 맞아떨어질 때 vLLM이 “생산(Production)급”으로 가치를 발휘합니다.

 
 
 
반응형

'Programming > LLM RAG' 카테고리의 다른 글

vector db  (1) 2025.06.14
Pinecone  (0) 2025.06.13
LangChain/LangGraph  (0) 2025.06.13
TensorRT-LLM  (1) 2025.06.13
SGLang  (0) 2025.06.13

subscribeOn

이건 스레드풀(스케줄러) 바꿔줄때 쓰는건데 여러번 해도 코드기준 처음지정해준걸로 고정된다.

Flux.interval(Duration.ofSeconds(10))
    .map(…)
    .subscribeOn(Schedulers.elastic())     // A
    .map(…)
    .subscribeOn(Schedulers.parallel())    // B
    .subscribe();

A로 고정, B는 무시

 

만약 중간중간에 스레드풀을 바꾸고 싶다면 publishOn을 써야한다.

Flux.interval(Duration.ofSeconds(10))
    // (1) 최초 ticker 신호 발행: Reactor 내장 타이머 스케줄러 (예: parallel())
    .publishOn(Schedulers.boundedElastic())
    // (2) 이제부터 아래 연산(map, flatMap 등)을 boundedElastic 스레드에서 실행
    .map(ignore -> loadWidgetPerformanceByPcidData())
    .publishOn(Schedulers.parallel())
    // (3) 여기 아래 연산은 parallel() 스레드에서 실행
    .map(result -> {
        // 예: 결과를 DB에 저장하거나 metrics를 찍는 작업
        recordMetric(result);
        return result;
    })
    .subscribe();
반응형

'Programming > SpringBoot' 카테고리의 다른 글

WebSocket  (1) 2025.05.22
Spring에서 graphQL적용하기  (0) 2023.10.13
Spring에서 gRPC연동하기  (1) 2023.10.11
maven dependency  (0) 2023.10.11
Spring Boot에서 endpoint접근을 http에서 https로 변경하기  (0) 2023.10.09

 

Reactor Context:  “리액터 체인 전체가 공유하는, 키-값 형태의 작은 Map”

 

  • ThreadLocal처럼 코드를 통해 값을 전달하지 않고도 다운스트림(아래쪽) 연산자들이 값을 꺼내 쓸 수 있음
  • 하지만 쓰레드에 묶이지 않고 Reactive 시퀀스와 함께 이동하므로, 쓰레드가 바뀌어도 그대로 보존됨

 

 

Mono<String> pipeline =
    Mono.just("payload")
        // ── 여기까지는 일반 Mono ──
        .flatMap(data -> Mono.deferContextual(ctx ->
            // Context 에 담긴 userId 꺼내서 활용
            Mono.just("User " + ctx.get("userId") + " processed " + data)
        ))
        // ── contextWrite 는 이 지점부터 downstream 에 적용 ──
        .contextWrite(ctx -> ctx.put("userId", "alice123"));

위처럼 사용한다. deferContextual대신에 subscriberContext써도 된다.

 

 

Flux.just(...)
    .doOnNext(...)         // (1) 데이터 신호 흐를 때 requestId 읽기
    .map(...)              // (2) 다른 연산자
    .contextWrite(...)     // (3) 구독 직전 Context 설정
.subscribe()              // (4) 구독 신호 발생 → (3) → (2) → (1) → 소스
// A. 올바른 예 – 읽는 쪽보다 "아래"에 contextWrite
Mono.deferContextual(ctx -> Mono.just(ctx.get("key")))
    .contextWrite(Context.of("key", "v"));  // ✔

// B. 잘못된 예 – contextWrite를 먼저 써버림
Mono<String> wrong =
    Mono.just("x")
        .contextWrite(Context.of("key", "v"))  // 여기선 아직 값 읽지 않음
        .flatMap(v -> Mono.deferContextual(ctx -> Mono.just(ctx.get("key"))));
// → NoSuchElementException (key를 못 찾음)

 

위 부분이 무지하게 햇갈렸다. .contextWrite()가 map에 insert하는건데.. 체인상 가장 나중에 해줘야 동작하고 이전에 해주면 동작안한다. data흐름과 호출흐름이 반대라서 그런거 같은데 recursive의 원리를 생각해보면 될듯

 

ThreadLocal과의 차이

엄청 헷갈리지만 contextWrite()가 체인 출구쪽에 기록해줘야 함에 비해서 이건 체인 입구쪽에 set해줘야 제대로 읽힌다.

근데 React에서는 스레드 변경가능성을 고려해야하므로 어차피 안쓰는게 좋음

 

타이밍 비교

 

  ThreadLocal Reactor  Context
세팅 시점 체인(흐름) 입구 에서 set() 체인 출구(끝) 에서 .contextWrite()
전달 범위 “같은 스레드” 에서만 유지 “Reactive 시그널” 과 함께 끝까지 전파
정리 시점 처리 후 remove() 반드시 필요 불변 객체라, 별도 정리 불필요
import reactor.core.publisher.Mono;

import java.util.UUID;

public class ThreadLocalExample {
    // ① ThreadLocal 선언
    private static final ThreadLocal<String> REQUEST_ID = new ThreadLocal<>();

    public Mono<String> process(String input) {
        // ② 체인 입구에서 set()
        REQUEST_ID.set(UUID.randomUUID().toString());

        return Mono.just(input)
            // ③ map 내부에서 읽기
            .map(v -> "ThreadLocal → requestId=" 
                        + REQUEST_ID.get() 
                        + ", payload=" + v)
            // ④ 체인 종료 직전에 반드시 remove()
            .doFinally(sig -> REQUEST_ID.remove());
    }

    public static void main(String[] args) {
        new ThreadLocalExample()
            .process("Hello")
            .subscribe(System.out::println);
    }
}

ThreadLocal예시

 

import reactor.core.publisher.Mono;
import reactor.util.context.Context;

import java.time.Duration;
import java.util.UUID;

public class ReactorContextExample {

    public Mono<String> process(String input) {
        return Mono.just(input)
            // ① 실제 읽는 부분(deferContextual 또는 subscriberContext)
            .flatMap(v -> Mono.deferContextual(ctx ->
                Mono.just("ReactorContext → requestId=" 
                          + ctx.get("requestId") 
                          + ", payload=" + v)))
            // ② 체인 “출구” 에서 contextWrite
            .contextWrite(ctx -> ctx.put("requestId", UUID.randomUUID().toString()));
    }

    public static void main(String[] args) {
        new ReactorContextExample()
            .process("Hello")
            .subscribe(System.out::println);
    }
}

React Context예시

반응형

'Programming > JAVA' 카테고리의 다른 글

java generic  (0) 2025.05.27
reactor #1  (1) 2024.01.01
BiFunction, Function을 사용한 함수형 프로그래밍  (0) 2024.01.01
java Optional  (1) 2023.11.04
java enum  (0) 2023.11.03

클래스 레벨이 있고 메소드 레벨이 있다.

클래스레벨은 List같은 자료구조만 써도 익숙하니까 다음처럼 간단히 짚고 넘어가자.

public class MyStack<T> {
    // 클래스 전체에서 T를 사용할 수 있다
    private final List<T> elements = new ArrayList<>();
    public void push(T element) { … }
    public T pop() { … }
}

 

MyStack<T>에서 <T>는 Type Parameters 선언이라고 불린다.

 

근데 class는 제네릭이 아니면서 메소드 하나만 제네릭으로 만들경우는 다음처럼 타입선언을 왼쪽에 해줘야 한다.

private <T, R> Mono<CommonDto> executeWithMetrics(
    AdsEndpoints endpoint,
    R request,
    Mono<T> operation) { … }

<T, R> 부분을 이야기 하는건데 언뜻 보면 되게 헷갈리는데, 컴파일러에게 T와 R이라는 제네릭 타입을 쓸거야.. 라고 선언하는 부분이라고 보면 된다.

 

반응형

'Programming > JAVA' 카테고리의 다른 글

Reactor Context  (0) 2025.05.27
reactor #1  (1) 2024.01.01
BiFunction, Function을 사용한 함수형 프로그래밍  (0) 2024.01.01
java Optional  (1) 2023.11.04
java enum  (0) 2023.11.03

특징

제네릭

Go는 원래 제네릭을 지원하지 않았는데, Go 1.18부터 타입 매개변수(type parameters), 즉 제네릭을 도입했습니다.

 

try-catch가 없다.

Rest Server 구현

FastAPI등에 해당하는 별도 프레임웍없이도 go자체적으로 강력한 api서버기능 제공(net/http)

그러나 Gin이라고 해서 FastAPI에 해당하는 프레임웍도 존재

프레임워크 언어 스타일 특징
Spring Boot Java/Kotlin 풀스택·엔터프라이즈급 DI, AOP, 방대한 스타터·생태계, 설정 중심
FastAPI Python 경량·비동기 마이크로서비스 Pydantic 기반 타입 검사, 자동 문서화(OpenAPI)
Express Node.js 경량 마이크로프레임워크 최소 기능 제공, 미들웨어 체인, JS 생태계
Gin Go 경량 마이크로프레임워크 Go 링거 net/http 위에 빠른 라우터, 미들웨어

 

 

async/await나 webflux등의 코딩 없이도 자체적으로 go루틴으로 분기해줘서 강력한 비동기 지원(개발자 편함)

반응형

'Programming' 카테고리의 다른 글

window에서 vscode로 원격 linux에 대한 ssh 개발환경 설정하기  (1) 2024.07.20
yaml  (0) 2024.03.02
디자인패턴  (0) 2023.08.17
라즈베리파이 초기 세팅  (1) 2023.01.20
STL lower_bound, upper_bound  (0) 2020.04.12

+ Recent posts