최근 React 및 Next.js 생태계에서 악용 가능성이 매우 높은 치명적인 보안 취약점이 발견되어 전 세계 웹·클라우드 인프라 운영자들에게 즉각적인 대응이 요구되고 있다.


이번 취약점은 보안 등급 최고 수준인 이른바 “만점(perfect ten)”으로 평가될 만큼 심각하며, 최소한의 공격 노력만으로도 서버를 원격에서 장악할 수 있다는 점에서 큰 충격을 주고 있다.

 

해당 취약점은 “React2Shell”로 명명되었으며, React 프레임워크 자체의 결함(CVE-2025-55182)과 이를 기반으로 하는 Next.js 환경의 연쇄 취약점(CVE-2025-66478)을 포함한다. React는 전 세계 웹사이트의 약 6%, 클라우드 환경의 약 39%에서 사용되고 있고, Next.js를 포함한 다양한 현대 웹 프레임워크의 핵심 기반 기술로 활용되고 있기 때문에 이번 사안의 파급력은 매우 크다.

 

문제의 근본 원인은 React Server Components(RSC) 내부에서 사용되는 Flight 프로토콜의 역직렬화 처리 방식에 있다. Wiz 보안 연구진에 따르면, 기본 설정 상태의 React·Next.js 서버에서는 입력에 대한 검증이 충분하지 않아, 공격자가 조작한 페이로드가 서버 측에서 그대로 역직렬화되어 실행될 수 있다. 이는 말 그대로 원격 코드 실행(Remote Code Execution)으로 이어지는 구조다.

 

악용 방식은 매우 단순하다. 공격자는 인증 없이도 취약한 서버에 특수하게 구성된 HTTP 요청 단 한 번을 보내는 것만으로 공격을 성공시킬 수 있다. Wiz 연구진은 이미 높은 성공률을 보이는 개념증명(PoC) 익스플로잇을 확보했으며, 내부 테스트 결과 거의 실패 없이 서버 침해가 가능했다고 밝혔다. 특히 많은 Next.js 서버들이 클라우드 환경에서 공용 인터넷에 그대로 노출되어 있어 실제 공격 가능성은 매우 높다고 평가된다.

 

이 취약점은 웹 서비스 자체뿐 아니라 프라이빗 및 퍼블릭 클라우드 인프라 전반에 연쇄적인 피해를 일으킬 수 있다는 점에서 위험성이 크다. 공격이 완전히 원격으로 이루어지고 인증조차 필요 없기 때문에, 패치가 적용되지 않은 서버는 자동화된 대규모 공격의 표적이 될 가능성이 높다.

 

React 개발팀은 이러한 React2Shell 공격을 완화하기 위해 보다 엄격한 검증과 안전한 역직렬화 절차를 도입한 업데이트를 이미 배포했다. 이에 따라 프레임워크 유지관리자, 호스팅 플랫폼, 클라우드 서비스 제공업체는 즉시 관련 패치를 적용해야 하며, 이를 방치할 경우 사용자와 시스템 전체가 심각한 보안 위험에 노출될 수 있다. 참고로 Google은 자사의 Compute Engine 기본 OS 이미지가 해당 취약점의 영향을 받지 않는다고 공식 발표했다.

 

이번 사태는 널리 사용되는 현대 웹 기술이라 하더라도, 서버 사이드 실행 구조와 직결되는 영역에서는 단 하나의 설계 결함이 치명적인 결과로 이어질 수 있다는 점을 다시 한번 상기시키는 사례로 평가되고 있다.

 

 

 

 

 

 

 

 

 

 


The Complete Backend Development Tech Stack

Core Programming Languages
├── JavaScript/Node.js (Runtime)
├── Python
├── Java
├── Go
└── C# (.NET)

Backend Frameworks
├── Node.js Ecosystem
│   ├── Express.js
│   ├── NestJS
│   ├── Fastify
│   └── Koa
├── Python Ecosystem
│   ├── Django & Django REST Framework
│   ├── FastAPI
│   ├── Flask
│   └── Pyramid
├── Java Ecosystem
│   ├── Spring Boot
│   ├── Micronaut
│   └── Quarkus
├── Go Ecosystem
│   ├── Gin
│   ├── Echo
│   └── Fiber
└── C# Ecosystem
    ├── ASP.NET Core
    └── Nancy FX

API Development & Architecture
├── API Paradigms
│   ├── RESTful APIs
│   ├── GraphQL (Apollo, Hasura)
│   ├── gRPC
│   └── WebSocket & Real-time APIs
├── API Documentation
│   ├── OpenAPI/Swagger
│   ├── Postman Collections
│   └── GraphQL Playground
└── API Security
    ├── Rate Limiting
    ├── Input Validation
    ├── API Versioning
    └── CORS Configuration

Databases & Data Storage
├── SQL Databases
│   ├── PostgreSQL
│   ├── MySQL
│   ├── SQL Server
│   └── SQLite (Development)
├── NoSQL Databases
│   ├── MongoDB
│   ├── Redis (Caching & Sessions)
│   ├── Cassandra
│   └── DynamoDB
├── ORMs & Query Builders
│   ├── Prisma, Sequelize, TypeORM
│   ├── SQLAlchemy, Django ORM
│   ├── Hibernate (Java)
│   └── Entity Framework (.NET)
└── Data Caching
    ├── Redis, Memcached
    ├── CDN Integration
    ├── Database Query Caching
    └── In-Memory Caching

Authentication & Authorization
├── Authentication Methods
│   ├── JWT (JSON Web Tokens)
│   ├── OAuth 2.0 & OpenID Connect
│   ├── Session-Based Authentication
│   └── API Keys
├── Identity Providers
│   ├── Auth0
│   ├── AWS Cognito
│   ├── Firebase Auth
│   └── Okta
└── Security Practices
    ├── Password Hashing (bcrypt)
    ├── SSL/TLS Encryption
    ├── CSRF Protection
    └── Security Headers

Message Brokers & Background Jobs
├── Message Queues
│   ├── RabbitMQ
│   ├── Apache Kafka
│   ├── AWS SQS
│   └── Redis Pub/Sub
├── Background Processing
│   ├── Celery (Python)
│   ├── Bull Queue (Node.js)
│   ├── Sidekiq (Ruby)
│   └── Hangfire (.NET)
└── Event-Driven Architecture
    ├── Event Sourcing
    ├── CQRS Pattern
    ├── Domain-Driven Design
    └── Microservices Communication

Cloud Platforms & Infrastructure
├── Major Cloud Providers
│   ├── AWS (EC2, Lambda, RDS, S3)
│   ├── Google Cloud Platform
│   ├── Microsoft Azure
│   └── DigitalOcean
├── Serverless Computing
│   ├── AWS Lambda
│   ├── Google Cloud Functions
│   ├── Azure Functions
│   └── Vercel/Netlify Functions
└── Cloud Services
    ├── Object Storage (S3, Cloud Storage)
    ├── Managed Databases (RDS, Cloud SQL)
    ├── CDN
    ├── Container Services

Containerization & Orchestration
├── Containerization
│   ├── Docker
│   ├── Docker Compose
│   └── Best Practices
├── Orchestration
│   ├── Kubernetes
│   ├── Docker Swarm
│   ├── AWS ECS
│   └── Managed Kubernetes
└── Package Management
    ├── Helm Charts
    ├── Docker Registries
    └── Infrastructure Templates

DevOps & CI/CD
├── Infrastructure as Code
│   ├── Terraform
│   ├── AWS CloudFormation
│   ├── Pulumi
│   └── Ansible
├── CI/CD Pipelines
│   ├── GitHub Actions
│   ├── GitLab CI/CD
│   ├── Jenkins
│   └── CircleCI
└── Monitoring & Observability

Testing Strategies
├── Testing Pyramid
├── Test Doubles
└── Performance Testing

Development Best Practices
├── Code Quality
├── Design Patterns
└── Architecture Patterns

Grab your Backend Development eBook with Projects here: codewithdhanian.gumroad.com/l/juuzy




백엔드 개발 전체 기술 스택 요약

1. 핵심 프로그래밍 언어

JavaScript (Node.js)

Python

Java

Go

C# (.NET)



---

2.  백엔드 프레임워크

Node.js → Express.js, NestJS, Fastify, Koa

Python → Django, FastAPI, Flask

Java → Spring Boot, Micronaut, Quarkus

Go → Gin, Echo, Fiber

C# → ASP.NET Core



---

3.  API 개발 및 아키텍처

REST, GraphQL, gRPC, WebSocket

문서화: Swagger / Postman / GraphQL Playground

보안: Rate Limiting, Input Validation, CORS 설정 등



---

4.  데이터베이스 & 저장소

SQL: PostgreSQL, MySQL, SQL Server

NoSQL: MongoDB, Redis, Cassandra

ORMs: Prisma, Sequelize, SQLAlchemy, Hibernate

캐싱: Redis, CDN, In-memory caching



---

5. 인증 및 인가

방식: JWT, OAuth 2.0, 세션 기반

서비스: Auth0, AWS Cognito, Firebase Auth

보안 실천: 비밀번호 해시, SSL/TLS, CSRF 방지



---

6.  메시지 브로커 & 백그라운드 작업

Queue: RabbitMQ, Kafka, AWS SQS

백그라운드 작업: Celery, Bull, Sidekiq

패턴: Event Sourcing, CQRS, DDD



---

7.  클라우드 & 인프라

플랫폼: AWS, GCP, Azure

서버리스: AWS Lambda, Cloud Functions

서비스: S3, RDS, CDN, Managed DBs



---

8.  컨테이너 & 오케스트레이션

Docker, Kubernetes, AWS ECS

Helm, Terraform 등으로 배포 자동화



---

9.  DevOps & CI/CD

IaC: Terraform, Ansible

CI/CD: GitHub Actions, GitLab CI, Jenkins

모니터링: Prometheus, Grafana, ELK Stack



---

10.  테스트 & 품질 관리

단위 테스트, 통합 테스트, 성능 테스트

코드 품질, 디자인 패턴, 클린 아키텍처

출처: CodeWithDhanian — “Complete Backend Development eBook with Projects”

codewithdhanian.gumroad.com/l/juuzy



 
HTML 코드는 jspreadsheet과 jsuites 라이브러리를 불러와서 간단한 엑셀 스타일의 웹 스프레드시트를 생성하는 예제입니다.
 
아래 예시는 초기 데이터/컬럼 타입 지정 + 자동 저장(로컬스토리지) + 수동 저장·불러오기·초기화 버튼까지 모두 갖춘 통합 HTML입니다. 그대로 붙여넣어 실행하시면 됩니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8" />
  <title>jspreadsheet LocalStorage Demo</title>

  <!-- libs -->
  <script src="https://jspreadsheet.com/v11/jspreadsheet.js"></script>
  <script src="https://jsuites.net/v5/jsuites.js"></script>
  <link rel="stylesheet" href="https://jsuites.net/v5/jsuites.css" />
  <link rel="stylesheet" href="https://jspreadsheet.com/v11/jspreadsheet.css" />

  <!-- icons (툴바 아이콘용) -->
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons" />

  <style>
    body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 24px; }
    .actions { display:flex; gap:8px; margin-bottom:12px; flex-wrap: wrap; }
    .actions button {
      padding: 8px 12px; border: 1px solid #ddd; border-radius: 8px; background: #fff; cursor: pointer;
    }
    .actions button:hover { background:#f6f6f6; }
    #status { font-size:12px; color:#666; margin-left: 6px; }
  </style>
</head>
<body>
  <h1>JSpreadsheet + LocalStorage 예제</h1>

  <div class="actions">
    <button id="saveBtn">수동 저장</button>
    <button id="loadBtn">불러오기</button>
    <button id="clearBtn">로컬스토리지 초기화</button>
    <span id="status"></span>
  </div>

  <div id="spreadsheet"></div>

  <script>
    // ====== 라이선스 키 (테스트 키: 하루만 유효) ======
    jspreadsheet.setLicense('OWMzYWFkOTc3ZGQ2ODg0NWIwYTkyNTE3MmQ5NmNiZGY4ZGEzNjkwZTVlMTA4NjZmNTg5MzQzMDMxNmVjZWM4Mzc0ZGNjMjI5Y2NiMWMxMzIwNjdkNjJiNGJiZWY4MGJhOTJjNWY0OTNkN2QzOTNiZmVlODg1OGVhNDAwNTMyOTQsZXlKamJHbGxiblJKWkNJNklpSXNJbTVoYldVaU9pSktjM0J5WldGa2MyaGxaWFFpTENKa1lYUmxJam94TnpVNE1EY3lNekl6TENKa2IyMWhhVzRpT2xzaWFuTndjbVZoWkhOb1pXVjBMbU52YlNJc0ltTnZaR1Z6WVc1a1ltOTRMbWx2SWl3aWFuTm9aV3hzTG01bGRDSXNJbU56WWk1aGNIQWlMQ0p6ZEdGamEySnNhWFI2TG1sdklpd2lkMlZpWTI5dWRHRnBibVZ5TG1sdklpd2lkMlZpSWl3aWJHOWpZV3hvYjNOMElsMHNJbkJzWVc0aU9pSXpOQ0lzSW5OamIzQmxJanBiSW5ZM0lpd2lkamdpTENKMk9TSXNJbll4TUNJc0luWXhNU0lzSW1Ob1lYSjBjeUlzSW1admNtMXpJaXdpWm05eWJYVnNZU0lzSW5CaGNuTmxjaUlzSW5KbGJtUmxjaUlzSW1OdmJXMWxiblJ6SWl3aWFuMXdiM0owWlhJaUxDSmlZWElpTENKMllXeHBaR0YwYVc5dWN5SXNJbk5sWVhKamFDSXNJbkJ5YVc1MElpd2ljMmhsWlhSeklpd2lZMnhwWlc1MElpd2ljMlZ5ZG1WeUlpd2ljMmhoY0dWeklpd2labTl5YldGMElsMHNJbVJsYlc4aU9uUnlkV1Y5');

    // ====== 설정 ======
    const STORAGE_KEY = 'jspreadsheet-demo-v1';
    const statusEl = document.getElementById('status');
    const spreadsheetEl = document.getElementById('spreadsheet');

    // 초기 데이터(스토리지에 없을 때만 사용)
    const defaultSheet = {
      minDimensions: [6, 10],
      data: [
        ['이름', '나이', '점수', '등록일', '분류', '비고'],
        ['철수', 20, 85, '2025-09-15', 'A', '우수'],
        ['영희', 22, 90, '2025-09-16', 'S', '장학생'],
        ['민수', 21, 77, '2025-09-12', 'B', '보통'],
      ],
      columns: [
        { type: 'text', title: '이름', width: 120 },
        { type: 'numeric', title: '나이', width: 80, mask:'#,##0' },
        { type: 'numeric', title: '점수', width: 80, mask:'#,##0' },
        { type: 'calendar', title: '등록일', width: 120, options: { format:'YYYY-MM-DD' } },
        { type: 'dropdown', title: '분류', width: 90, source: ['S','A','B','C'] },
        { type: 'text', title: '비고', width: 160 },
      ],
    };

    // ====== 유틸 ======
    const setStatus = (msg) => {
      statusEl.textContent = msg;
      if (!msg) return;
      // 2초 후 상태 문구 자동 지움
      setTimeout(() => { if (statusEl.textContent === msg) statusEl.textContent = ''; }, 2000);
    };

    // 디바운스 저장 (변경 잦을 때 과도 저장 방지)
    let saveTimer = null;
    const debouncedSave = (fn, delay = 500) => {
      clearTimeout(saveTimer);
      saveTimer = setTimeout(fn, delay);
    };

    // ====== 초기 로드: 로컬스토리지 → 시트 ======
    function loadFromStorageOrDefault() {
      const saved = localStorage.getItem(STORAGE_KEY);
      if (saved) {
        try {
          const parsed = JSON.parse(saved);
          return parsed; // worksheets 배열 형태 기대
        } catch(e) {
          console.warn('저장된 데이터를 파싱할 수 없어 기본값으로 초기화합니다.', e);
        }
      }
      return [defaultSheet];
    }

    // ====== 스프레드시트 생성 ======
    let jss = jspreadsheet(spreadsheetEl, {
      tabs: true,
      toolbar: true,
      worksheets: loadFromStorageOrDefault(),
      // 변경 시 자동 저장
      onchange: function() {
        debouncedSave(() => saveToStorage(true), 600);
      },
      onpaste: function() {
        debouncedSave(() => saveToStorage(true), 600);
      },
      // 시트 추가/삭제도 저장
      oninsertrow: () => debouncedSave(() => saveToStorage(true), 600),
      oninsertcolumn: () => debouncedSave(() => saveToStorage(true), 600),
      ondeleterow: () => debouncedSave(() => saveToStorage(true), 600),
      ondeletecolumn: () => debouncedSave(() => saveToStorage(true), 600),
      oncreateworksheet: () => debouncedSave(() => saveToStorage(true), 600),
      ondeleteworksheet: () => debouncedSave(() => saveToStorage(true), 600),
    });

    // ====== 저장 로직 ======
    function collectWorksheetsAsJson() {
      // v11에서는 인스턴스가 배열처럼 동작 (워크시트 접근)
      // 각 워크시트의 구조를 getJson()으로 수집
      const arr = [];
      const count = jss.worksheets ? jss.worksheets.length : (jss.length || 1);
      for (let i = 0; i < count; i++) {
        const ws = jss.worksheets ? jss.worksheets[i] : jss[i] || jss;
        // getJson()은 데이터/열 정의/너비 등 구성을 포함
        // 환경에 따라 getJson() 대신 { data: ws.getData(), columns: ws.options.columns } 형태로 수집할 수도 있습니다.
        if (ws && typeof ws.getJson === 'function') {
          arr.push(ws.getJson());
        } else {
          // 폴백
          arr.push({
            data: ws.getData ? ws.getData() : [],
            columns: ws.options?.columns || [],
            minDimensions: ws.options?.minDimensions || [6,10]
          });
        }
      }
      return arr;
    }

    function saveToStorage(showStatus = false) {
      try {
        const json = collectWorksheetsAsJson();
        localStorage.setItem(STORAGE_KEY, JSON.stringify(json));
        if (showStatus) setStatus('자동 저장 완료');
      } catch(e) {
        console.error('저장 실패', e);
        if (showStatus) setStatus('저장 실패');
      }
    }

    // ====== 불러오기 로직 ======
    function reloadFromStorage() {
      const saved = localStorage.getItem(STORAGE_KEY);
      if (!saved) {
        setStatus('저장된 데이터가 없습니다.');
        return;
      }
      try {
        const worksheets = JSON.parse(saved);
        // 전체 리셋 후 다시 생성
        spreadsheetEl.innerHTML = '';
        jss = jspreadsheet(spreadsheetEl, {
          tabs: true,
          toolbar: true,
          worksheets,
          onchange: () => debouncedSave(() => saveToStorage(true), 600),
        });
        setStatus('불러오기 완료');
      } catch(e) {
        console.error('불러오기 실패', e);
        setStatus('불러오기 실패');
      }
    }

    // ====== 초기화 로직 ======
    function clearStorageAndReset() {
      localStorage.removeItem(STORAGE_KEY);
      spreadsheetEl.innerHTML = '';
      jss = jspreadsheet(spreadsheetEl, {
        tabs: true,
        toolbar: true,
        worksheets: [defaultSheet],
        onchange: () => debouncedSave(() => saveToStorage(true), 600),
      });
      setStatus('로컬스토리지 초기화 및 기본 데이터로 복원');
    }

    // ====== 버튼 바인딩 ======
    document.getElementById('saveBtn').addEventListener('click', () => {
      saveToStorage(false);
      setStatus('수동 저장 완료');
    });
    document.getElementById('loadBtn').addEventListener('click', () => reloadFromStorage());
    document.getElementById('clearBtn').addEventListener('click', () => clearStorageAndReset());

    // 페이지 진입 시 한 번 저장(구성 고정화)
    saveToStorage(false);
  </script>
</body>
</html>

 
 

어떻게 동작하나요?

  • 셀을 편집하면 디바운스(0.6초) 후 자동 저장됩니다.
  • 상단 버튼으로 수동 저장/불러오기/초기화가 가능합니다.
  • 저장 포맷은 로컬스토리지의 jspreadsheet-demo-v1 키에 워크시트 배열(JSON) 형태로 보관됩니다.

 
 
 
 
 
 
 
 
 
 

 

 

팀 위키에 바로 붙여넣어 쓸 수 있는 Markdown 문서 버전 입니다.

🔐 비밀번호 해시 가이드 (2025)

팀 서비스 보안을 위한 비밀번호 해싱 알고리즘 및 파라미터 권장안입니다.

1. 현재 권장 알고리즘

  • 기본 권장: Argon2id (PHC 우승, RFC 9106 표준)
  • 대안: bcrypt (여전히 안전하지만 72바이트 길이 제한 있음)
  • 금지: SHA-256/MD5 단독 사용 (빠른 해시는 레인보우 테이블에 취약)

2. Salt & Pepper

  • Salt
    • 사용자별 랜덤(≥16바이트)
    • 해시와 함께 DB에 저장
    • 목적: 레인보우 테이블 무력화
  • Pepper
    • 서비스 전역 비밀 키
    • HSM/환경 변수에 보관
    • DB 유출 시 추가 방어

3. Argon2id 파라미터 캘리브레이션

목표: 해시 1회당 100~250ms 지연
방법: m(메모리)을 먼저 올리고, t(반복횟수)로 미세조정, p는 CPU 코어 상황에 맞춰 설정.

일반 서버 (8코어, 중간 RAM)

목표 지연                               m (MiB)                                t             p                         비고

~100ms 96–128 2 4 기본 수준
~200ms 128–192 3 4 권장 시작점
~300ms 192–256 3 4–6 고강도 인증에 적합

메모리 제약 환경 (서버리스/저사양)

목표 지연                             m (MiB)                          t                       p                            비고

~100ms 32–64 3–4 2–3 메모리 낮추고 반복↑
~200ms 64–96 3–4 3 서버리스 고려
~300ms 96–128 3–4 3–4 고비용 경로만 적용

고강도 보안 (관리자/금융)

목표 지연                           m (MiB)                              t                      p                          비고

≥300ms 256–512 3–4 4–8 2FA/레이트리밋 병행

4. 구현 예시

Go

import (
  "crypto/rand"
  "encoding/base64"
  "golang.org/x/crypto/argon2"
)

params := struct {
  Memory      uint32
  Iterations  uint32
  Parallelism uint8
  SaltLen     uint32
  KeyLen      uint32
}{131072, 3, 4, 16, 32}

salt := make([]byte, params.SaltLen)
rand.Read(salt)

hash := argon2.IDKey([]byte(password), salt,
  params.Iterations, params.Memory, params.Parallelism, params.KeyLen)

encoded := "$argon2id$v=19$m=131072,t=3,p=4$" +
  base64.RawStdEncoding.EncodeToString(salt) + "$" +
  base64.RawStdEncoding.EncodeToString(hash)

Node.js

import argon2 from "argon2";

const hash = await argon2.hash(password, {
  type: argon2.argon2id,
  timeCost: 3,
  memoryCost: 128 * 1024,
  parallelism: 4,
  hashLength: 32,
  saltLength: 16,
});
const ok = await argon2.verify(hash, input);

 

5. 운영 체크리스트

  • 레이트 리미트 + 랜덤 지연 (타이밍 분석 방지)
  • 유출 비밀번호 대조 (가입/변경 시 HIBP 등)
  • 비밀번호 매니저 사용 권장
  • 유니코드 정규화(NFC)
  • Constant-Time 비교 사용
  • 재해시 정책: bcrypt → Argon2id 마이그레이션 시 로그인 성공 후 즉시 재해시

6. 권위 자료

실무 권장 파라미터 (2025 기본값)
m=131072 (128 MiB), t=3, p=4, salt=16B, key=32B

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CRA(Create React App) 프로젝트를 Next.js로 전환하면, 다음과 같은 변화(결과)가 생깁니다:

 

1. 기능과 아키텍처의 변화

항목                              CRA (Create React App)                                             Next.js

 

렌더링 방식 CSR 중심 (클라이언트 렌더링) CSR + SSR + SSG + ISR (다양한 렌더링 지원)
라우팅 수동 (react-router-dom 필요) 자동 파일 기반 라우팅
코드 스플리팅 기본 제공 더 정교하게 자동 분할
이미지 최적화 직접 처리해야 함 next/image로 최적화 내장
SEO 최적화 제한적 (CSR은 SEO에 불리) SSR/SSG로 SEO 친화적
빌드 결과물 정적 번들만 생성 정적/동적 혼합 가능
API 라우팅 외부 백엔드 필요 pages/api 디렉터리로 간단한 백엔드 내장 가능
 

2. 개발 경험과 생산성의 변화

항목                                             CRA                                                  Next.js

 

설정 필요성 거의 없음 기본은 쉬우나 SSR 등 학습 필요
배포 방식 정적 배포 위주 정적/동적 모두 유연 (Vercel 최적화)
학습 난이도 비교적 낮음 렌더링 전략 이해 필요
커뮤니티/생태계 여전히 존재 급성장, 사실상 React의 공식 후계자 위치
 

3. 실제 코드 측면의 변화 예시

라우팅

tsx

// CRA
import { BrowserRouter, Route } from 'react-router-dom';

<BrowserRouter>
  <Route path="/about" element={<About />} />
</BrowserRouter>

// Next.js
// pages/about.tsx 만 만들면 자동 라우팅됨

 

데이터 패칭

tsx

// CRA
useEffect(() => {
  fetch('/api/data').then(...)
}, []);

// Next.js (SSR)
export async function getServerSideProps() {
  const res = await fetch(...);
  const data = await res.json();
  return { props: { data } };
}

 

4. 예상되는 효과

장점

  • SEO, 속도, 사용자 경험 향상
  • 백엔드(API) 기능 내장 가능
  • 유지보수성과 확장성 증가
  • 서버/정적/클라이언트 렌더링 전략 자유롭게 혼합 가능

고려사항

  • 렌더링 전략, 파일 구조에 대한 학습 필요
  • SSR 환경에서의 빌드/배포 흐름 이해 필요
  • 기존 CRA 전용 코드(react-router 등)는 재작성 필요

CRA → Next.js 전환은 단순한 프레임워크 교체가 아니라 아키텍처의 패러다임 전환입니다. 하지만 한 번 익숙해지면 더 강력한 기능과 성능, SEO 혜택을 얻을 수 있습니다.

 

 

 

CRA → Next.js 변환 체크리스트 와 CRA 프로젝트를 Next.js로 마이그레이션하는 실제 절차와 코드 예시 도 제공해 주세요.

 

CRA → Next.js 변환 체크리스트

1. 프로젝트 구조 점검

  •  src/ 디렉터리에 있는 모든 컴포넌트, 페이지, 이미지 등의 구조 파악
  •  react-router-dom 등 CRA 전용 라이브러리 사용 여부 확인
  •  index.html 안의 meta, title 등 문서 설정 확인

2. 기능 분류 및 전략 설정

  •  각 페이지가 CSR/SSR/SSG 중 어떤 방식이 적합한지 파악
  •  동적 라우팅이 필요한 경우 URL 구조 확인
  •  API 서버가 있는 경우 → Next.js의 API routes로 이전 가능한지 확인

3. 전환 준비

  •  react-scripts 제거
  •  next, react, react-dom 설치
  •  ESLint, TypeScript 등 기존 개발 도구 연동 여부 파악
  •  public/ 폴더 정리 및 재배치

CRA → Next.js 마이그레이션 절차 + 코드 예시

 

1.프로젝트 초기화

bash

# 새 Next.js 프로젝트 생성
npx create-next-app@latest my-next-app
cd my-next-app

 

혹은 기존 CRA 프로젝트에 적용하려면:

npm uninstall react-scripts
npm install next

 

package.json 수정:

"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start"
}

 

2.폴더 구조 변경

CRA:
src/
 ├── App.js
 ├── index.js
 └── components/

Next.js:
pages/
 ├── index.tsx        ← 기존의 App.js 내용
 └── about.tsx        ← 새 페이지는 파일 기반
components/
public/               ← 정적 파일 유지 (이미지, 영상 등)

 

3.라우팅 변경

CRA (React Router 기반) tsx

<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/about" element={<About />} />
  </Routes>
</BrowserRouter>

 

Next.js (파일 기반 자동 라우팅)

  • pages/index.tsx  /
  • pages/about.tsx  /about

별도 라우터 불필요. Link 컴포넌트만 필요:

import Link from 'next/link';

<Link href="/about">About</Link>

 

4.HTML, Head 설정

CRA 

html

<!-- public/index.html -->
<title>My CRA App</title>
<meta name="description" content="..." />

 

Next.js

tsx

// pages/_document.tsx 또는 개별 페이지에서
import Head from 'next/head';

<Head>
  <title>My Next App</title>
  <meta name="description" content="..." />
</Head>

 

5.API 호출 (선택적으로 SSR 적용)

CRA

useEffect(() => {
  fetch('/api/posts').then(res => res.json()).then(setData);
}, []);

 

Next.js

export async function getServerSideProps() {
  const res = await fetch('https://api.example.com/posts');
  const data = await res.json();
  return { props: { data } };
}

 

6.환경변수 사용법 변경

  • CRA: .env에서 REACT_APP_ 접두사 필요
  • Next.js: NEXT_PUBLIC_ 접두사로 변경
  • env
# CRA
REACT_APP_API_URL=https://api.example.com

# Next.js
NEXT_PUBLIC_API_URL=https://api.example.com

 

접근 시: ts

process.env.NEXT_PUBLIC_API_URL

 

7.CSS 적용 방식 확인

  • CRA의 index.css, App.css → Next.js에서는 pages/_app.tsx에 적용
// pages/_app.tsx
import '../styles/globals.css'

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />
}

 

8.Static Assets 이전

  • CRA: public/assets/img.jpg
  • Next.js: 동일하게 사용 가능 (/assets/img.jpg)

9.react-router-dom 제거 (선택사항)

npm uninstall react-router-dom

 

파일 기반 라우팅으로 대체되므로 더 이상 필요하지 않음.

10.서버 배포 방식 전환 고려 (선택)

  • 정적 사이트: next export로 export 후 정적 호스팅 가능
  • 서버 기반: next build && next start로 SSR 제공
  • Vercel, Netlify, Cloudflare Pages, AWS Amplify 등 지원

 

예시 구조

 
my-next-app/
├── components/
│   └── Navbar.tsx
├── pages/
│   ├── index.tsx
│   ├── about.tsx
│   └── api/
│       └── hello.ts     // API route 예시
├── public/
│   └── images/
├── styles/
│   └── globals.css
├── tsconfig.json
└── package.json

 

 

질문:

 React → Next.js 구조 변화와 CRA 프로젝트 → Next.js 의 구조변화 차이점은?

 

응답:

실제로 CRA → Next.js 전환과 React → Next.js 전환은 매우 유사해 보일 수 있지만, 의미 있는 차이점들이 있습니다. 아래에서 그 차이를 명확하게 정리해드릴게요.

 

CRA → Next.js vs 일반 React → Next.js 전환의 핵심 차이점

구분                          CRA → Next.js                                                                           일반 React → Next.js

 

기반 구조 create-react-app으로 생성된 프로젝트 (webpack, Babel, ESLint 등 구성됨) 직접 설정한 React 프로젝트이거나 임의의 구조
도구 체인 CRA에서 제공하는 기본 툴셋 (react-scripts) 사용 Webpack, Babel 등을 직접 설정하거나 vite 등 다른 도구 사용 가능
빌드/런처 CRA의 react-scripts에 의존 직접 설정한 webpack-dev-server, vite, parcel 
제거/변환 요소 CRA 전용 설정(예: react-scripts, .env 접두사 REACT_APP_, public/index.html 등) 제거 필요 일반 React에서는 해당 설정들이 없거나 자유롭게 구성되어 있어 단순 변환
환경변수 구조 CRA: REACT_APP_ → Next: NEXT_PUBLIC_ 자유롭게 설정한 경우, 일치 여부에 따라 재설정 필요
페이지 진입점 CRA는 index.js 하나에서 App.js를 렌더링 Next.js는 파일 기반 라우팅에 맞춰 여러 pages/ 구성
정적 HTML 처리 CRA는 public/index.html 사용 Next.js는 _document.tsx, _app.tsx, Head 구성 요소 사용
 

좀 더 직관적인 예시 비교

CRA → Next.js

// CRA
// src/index.js
ReactDOM.render(<App />, document.getElementById('root'));

// CRA는 react-scripts가 모든 설정을 숨기고 있음
// public/index.html에 직접 접근하여 HTML 구조 구성

// Next.js 전환 시:
- react-scripts 제거
- index.html → pages/_document.tsx로 분리
- App.js → pages/index.tsx
- 라우팅 재작성

 

일반 React → Next.js

// 일반 React 프로젝트
- 웹팩이나 Vite로 구성됨
- 설정이 직접적으로 노출됨
- HTML 템플릿, Babel 설정 등도 직접 관리

// Next.js 전환 시:
- Webpack 설정 제거 또는 통합
- Vite → Next로 교체
- 라우팅만 pages 기반으로 맞추면 비교적 간단

 

정리: 무엇이 중요한가?

질문                                                           CRA → Next.js                                                    React → Next.js

 

react-scripts 제거 필요? ✅ 반드시 필요 ❌ 없음
기존 환경변수 이름 강제 접두사 존재?  REACT_APP_  NEXT_PUBLIC_ 변경 필요 ❓ 상황에 따라 다름
라우팅 방식 전환  react-router-dom 제거 ✅ 보통 제거하지만 자유도 있음
webpack 설정 이관 문제 ❌ CRA는 설정 숨겨져 있어 이관 거의 없음 ✅ 직접 만든 설정은 마이그레이션 고려 필요
전환 난이도 보통~높음 (CRA 특성 제거 필요) 보통 (자유로운 구조일수록 쉬움)
 

요약

- CRA → Next.js: CRA 특유의 "숨겨진 설정"과 "react-scripts" 체인을 해체하고 Next.js의 구조로 "탈바꿈"해야 하는 포맷 전환입니다.
- React → Next.js: 사용자가 원하는 설정으로 만든 React 프로젝트에서 Next.js 구조로 "기능 확장"하는 개념에 가깝습니다. 설정 마이그레이션이 주요 포인트입니다.
→ 결국 CRA는 "자동화된 틀" 위에서 개발한 것이기 때문에, 그것을 걷어내고 Next.js에 맞춰 재조립해야 한다는 점에서 더 명확하고 특수한 마이그레이션입니다.

 

 

질문:

CRA → Next.js 전환 자동 스크립트 (Bash 또는 Node) 와

react-router-dom 사용 시 → pages 기반 자동 변환기 도 제공해 주세요.

 

응답:

1. CRA → Next.js 전환 자동 스크립트 (Bash 기반)

이 스크립트는 CRA 기반 프로젝트에서 불필요한 의존성을 제거하고, Next.js 구조로 초기 전환을 자동화합니다.

cra-to-next.sh 예시 스크립트

#!/bin/bash

echo "🚀 CRA → Next.js 변환 스크립트 시작..."

# 1. CRA 전용 패키지 제거
echo "📦 CRA 패키지 제거 중..."
npm uninstall react-scripts

# 2. Next.js 의존성 설치
echo "📦 Next.js 패키지 설치 중..."
npm install next react react-dom

# 3. 기본 next 설정 추가
echo "🛠 package.json 수정 중..."
npx json -I -f package.json -e '
this.scripts={
  "dev": "next dev",
  "build": "next build",
  "start": "next start"
}'

# 4. 디렉토리 구조 변경
mkdir -p pages
mv src/App.js pages/index.js 2>/dev/null
mv src/App.tsx pages/index.tsx 2>/dev/null
rm -rf src/index.js src/index.tsx

# 5. 기본 _app.js 추가
cat <<EOF > pages/_app.js
import '../styles.css';

export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}
EOF

# 6. public/index.html 제거 안내
if [ -f "public/index.html" ]; then
  echo "⚠️ public/index.html은 Next.js에서 사용되지 않으므로 삭제해 주세요."
fi

echo "✅ 변환 완료! dev 서버는 'npm run dev'로 실행하세요."

 

npx json 명령을 사용하므로 npm install -g json 또는 npx json 사용을 권장합니다.

 

2. react-router-dom  pages/ 기반 자동 변환기 (Node CLI 버전)

src/App.js 또는 src/routes.js 내 라우팅을 분석하고, 각 컴포넌트 파일을 pages/로 자동 복사/이동합니다.

convert-router-to-pages.js

#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

// 예시 라우팅 파일
const routerFile = path.join(__dirname, 'src', 'App.js'); // 또는 routes.js
const pagesDir = path.join(__dirname, 'pages');

if (!fs.existsSync(pagesDir)) {
  fs.mkdirSync(pagesDir);
}

// 정규식 기반 라우팅 파싱
const content = fs.readFileSync(routerFile, 'utf-8');
const routeRegex = /<Route path="([^"]+)" element={<([^ />]+)[^>]*>} ?\/?>/g;

let match;
while ((match = routeRegex.exec(content)) !== null) {
  const routePath = match[1];      // "/about"
  const componentName = match[2];  // About

  const srcFile = path.join(__dirname, 'src', 'components', `${componentName}.js`);
  const destPath = routePath === "/" ? "index" : routePath.replace(/^\/+/, "");
  const destFile = path.join(pagesDir, `${destPath}.js`);

  if (fs.existsSync(srcFile)) {
    const raw = fs.readFileSync(srcFile, 'utf-8');
    fs.writeFileSync(destFile, raw);
    console.log(`✅ ${componentName} → pages/${destPath}.js`);
  } else {
    console.warn(`❌ 컴포넌트 파일을 찾을 수 없음: ${componentName}`);
  }
}

 

사용 전제

  • 라우팅 구조가 다음과 유사해야 합니다:
<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/about" element={<About />} />
</Routes>

 

컴포넌트는 src/components/에 있어야 합니다.

 

결과 예시

이전 구조:
src/
 ├── App.js
 └── components/
     ├── Home.js
     └── About.js

전환 후:
pages/
 ├── index.js      ← Home.js 내용
 └── about.js      ← About.js 내용

 

 

 

 

보완 및 추가된 내용:

  • 비디오 로딩이 끝날 때까지 로딩 스피너 표시 (UX 개선)
  • 비디오 파일이 없거나 로드 실패 시 폴백 이미지 표시 (에러 처리)
  • 스타일 개선 (조금 더 깔끔한 디자인을 위해 세부적 스타일링 추가)
  • 타입 안정성 확보 (PropTypes 추가)
  • 유지보수 및 가독성 향상 (리팩토링)

 

src/components/VideoBackground.jsx

import React, { useState } from 'react';
import PropTypes from 'prop-types';

const VideoBackground = ({ videoSrc, fallbackImage, overlayText }) => {
  const [isVideoLoaded, setIsVideoLoaded] = useState(false);
  const [isError, setIsError] = useState(false);

  return (
    <div className="relative w-full h-screen overflow-hidden">
      {!isVideoLoaded && !isError && (
        <div className="absolute inset-0 bg-black flex items-center justify-center z-20">
          <div className="loader animate-spin rounded-full h-12 w-12 border-t-4 border-white"></div>
        </div>
      )}

      {isError ? (
        <img
          src={fallbackImage}
          alt="Background fallback"
          className="absolute top-0 left-0 w-full h-full object-cover z-0"
        />
      ) : (
        <video
          autoPlay
          loop
          muted
          playsInline
          className={`absolute top-0 left-0 w-full h-full object-cover z-0 transition-opacity duration-1000 ${isVideoLoaded ? 'opacity-100' : 'opacity-0'}`}
          onLoadedData={() => setIsVideoLoaded(true)}
          onError={() => setIsError(true)}
        >
          <source src={videoSrc} type="video/mp4" />
          브라우저가 비디오를 지원하지 않습니다.
        </video>
      )}

      <div className="absolute inset-0 z-10 flex items-center justify-center bg-black bg-opacity-50 text-white">
        <h1 className="text-4xl md:text-5xl font-bold shadow-lg">
          {overlayText}
        </h1>
      </div>
    </div>
  );
};

VideoBackground.propTypes = {
  videoSrc: PropTypes.string.isRequired,
  fallbackImage: PropTypes.string.isRequired,
  overlayText: PropTypes.string,
};

VideoBackground.defaultProps = {
  overlayText: '안녕하세요 반갑습니다!',
};

export default VideoBackground;

 

사용 예시 (src/App.jsx에 적용하기)

import React from 'react';
import VideoBackground from './components/VideoBackground';
import { motion, useScroll } from 'framer-motion';
import Header from './components/Header';
import Hero from './components/Hero';
import About from './components/About';
import ServicesSection from './components/ServicesSection';
import StatsSection from './components/StatsSection';
import ProjectGallery from './components/ProjectGallery';
import BlogSlider from './components/BlogSlider';
import SimpleCounter from './components/SimpleCounter';
import SimpleTodo from './components/SimpleTodo';
import SimpleCalculator from './components/SimpleCalculator';
import ThreeDPortfolio from './components/ThreeDPortfolio';
import AvatarPortfolio from './components/AvatarPortfolio';
import ParticlePortfolio from './components/ParticlePortfolio';
import Contact from './components/Contact';

function App() {
  const { scrollYProgress } = useScroll();

  return (
    <>
      <motion.div
        id="scroll-indicator"
        style={{
          scaleX: scrollYProgress,
          position: 'fixed',
          top: 0,
          left: 0,
          right: 0,
          height: '10px',
          backgroundColor: '#ff0088',
          zIndex: 9999,
          transformOrigin: '0% 50%',
        }}
      />

      <div style={{ minHeight: '200vh' }}>
        <VideoBackground
          videoSrc="/videos/intro.mp4"
          fallbackImage="/images/fallback.jpg"
          overlayText="환영합니다! 멋진 페이지에 오신 걸 환영해요!"
        />
        <Header />
        <Hero />
        <About />
        <ServicesSection />
        <StatsSection />
        <ProjectGallery />
        <BlogSlider />
        <SimpleCounter />
        <SimpleTodo />
        <SimpleCalculator />
        <ThreeDPortfolio />
        <AvatarPortfolio />
        <ParticlePortfolio />
        <Contact />
      </div>
    </>
  );
}

export default App;

 

Tailwind CSS 스타일링 추가하기 (tailwind.config.js에 다음을 추가)

 

// tailwind.config.js
module.exports = {
  // 생략
  theme: {
    extend: {
      animation: {
        spin: 'spin 1s linear infinite',
      },
      keyframes: {
        spin: {
          to: { transform: 'rotate(360deg)' },
        },
      },
    },
  },
};

 

추가 설명:

  • 로딩 스피너: 동영상이 로딩되는 동안 사용자가 지루하지 않도록 UX 개선.
  • 폴백 이미지: 영상이 로드되지 않거나 파일이 존재하지 않을 경우를 대비해 이미지 제공으로 오류 화면 방지.
  • Props 활용: VideoBackground 컴포넌트를 재사용 가능하게 만들어 다양한 영상 및 텍스트 지원 가능.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

질문 요약:

프론트엔드가 카카오 로그인 버튼을 클릭하면 카카오 서버에서 사용자를 인증한 후, 인가 코드(code)를 프론트엔드의 리다이렉트 URI로 보내줍니다.
프론트엔드는 받은 인가 코드를 다시 백엔드 서버에 전달하고, 백엔드 서버는 이 코드로 카카오 서버와 통신하여 액세스 토큰을 받아오는 방식입니다.

이때, 카카오 개발자 콘솔에 등록한 리다이렉트 URI가 프론트엔드와 백엔드에서 사용하는 URI가 동일해야 하는지 여부를 질문하신 것으로 보입니다.

 

정확한 답변:

프론트엔드와 백엔드가 사용하는 리다이렉트 URI는 다를 수 있습니다.

카카오 로그인 프로세스에서 사용하는 인가 코드(authorization code) 방식의 일반적인 흐름은 다음과 같습니다.

  1. 프론트엔드 → 카카오 로그인 요청 (인가 요청)
  2. 카카오 로그인 후 → 프론트엔드의 리다이렉트 URI로 code 반환
  3. 프론트엔드가 받은 인가 코드를 백엔드로 전달
  4. 백엔드 서버 → 카카오 서버에 액세스 토큰 요청
    • 이때 사용하는 리다이렉트 URI는 백엔드 서버가 카카오에 등록된 리다이렉트 URI를 그대로 명시해야 합니다.
    • 카카오 서버는 등록된 리다이렉트 URI와 일치하는지 검증합니다.
    중요: 이 단계에서 사용하는 리다이렉트 URI는 프론트에서 인가 코드를 받을 때 사용한 URI와 반드시 동일하게 등록된 값이어야 합니다.
    → 프론트에서 사용한 리다이렉트 URI와 카카오 개발자 콘솔에 등록된 리다이렉트 URI가 동일해야 합니다. (매우 중요)

하지만 서버가 자체적으로 다시 리다이렉트 URI를 받아서 처리하는 것이 아니라 프론트에서 받은 인가 코드를 서버로 전달하는 방식으로 처리할 경우,
백엔드 서버 자체에서 별도의 리다이렉트 URI 엔드포인트를 열 필요는 없습니다.
(즉, 백엔드가 인가 코드를 직접 받는 게 아니라 프론트엔드를 거쳐 전달받기 때문)


깔끔한 정리:

  • 프론트엔드에서 카카오로부터 인가 코드를 받을 때 사용하는 리다이렉트 URI는 반드시 카카오 개발자 콘솔에 등록된 것과 일치해야 합니다.
  • 백엔드가 카카오 서버에서 토큰을 요청할 때 넘겨주는 리다이렉트 URI 값은 프론트엔드에서 사용했던 그 URI와 반드시 같아야 합니다. (즉, 카카오 개발자 콘솔에 등록한 동일한 URI)
  • 다만 백엔드 자체가 직접 카카오에서 인가 코드를 받는 것이 아니기 때문에, 백엔드가 따로 리다이렉트 URI를 직접 핸들링하는 주소를 만들 필요는 없습니다.

결론적으로,
카카오 개발자 콘솔에는 프론트엔드가 사용하는 리다이렉트 URI만 등록되어 있으면 됩니다. 백엔드는 그 URI를 요청 시 값으로만 사용합니다.


예시로 정리하면:

이 구조로 하면 명확하게 구분되어 잘 작동합니다.

도움이 되었으면 좋겠습니다! 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

오버레이킷(OverlayKit)은 React에서 복잡한 UI 오버레이를 보다 선언적이고 간결하게 관리할 수 있게 도와주는 라이브러리입니다.
다양한 모달(Modal), 팝업(Popup), 드롭다운(Dropdown), 툴팁(Tooltip) 같은 컴포넌트를 쉽게 관리하고 상태를 단순화하는 데 중점을 둡니다.


1. 오버레이킷(OverlayKit)이란 무엇인가요?

오버레이킷(OverlayKit)은 React 애플리케이션에서 오버레이 UI 요소(모달, 드롭다운, 툴팁 등)의 상태와 관리를 선언적(Declarative)으로 처리할 수 있도록 지원하는 라이브러리입니다. 특히 복잡한 오버레이 UI의 상태 관리와 동작 제어를 깔끔하게 추상화하여 쉽게 다룰 수 있게 합니다.

선언적(Declarative)이란, UI 상태를 직접 명령형 코드로 조작하는 것이 아니라 상태에 따라 자동으로 렌더링되도록 정의하는 방식입니다.

즉, 오버레이킷은 UI의 가독성, 유지보수성, 코드 명료성을 높이는 데 초점을 맞춘 라이브러리입니다.


2. 왜 오버레이킷이 필요할까요?

기존 React에서 복잡한 오버레이 컴포넌트를 관리할 때의 문제점은 다음과 같습니다.

기존 오버레이 관리의 문제점

  • 상태 관리 복잡성
    여러 개의 모달이나 팝업이 중첩되거나 동시에 나타날 때, useState로만 관리하기 어렵습니다.
  • 컴포넌트 중복
    오버레이 컴포넌트가 반복적으로 코드에 등장하여 중복 코드가 많아집니다.
  • 코드 가독성 저하
    상태 로직과 UI 렌더링이 뒤섞여 코드가 복잡해지고 유지보수가 어렵습니다.
  • 콜백 및 prop-drilling 증가
    오버레이의 상태를 관리하기 위해 props로 상태나 이벤트를 전달하거나 콜백을 반복적으로 작성해야 합니다.

이러한 문제로 인해 상태 및 UI의 복잡성이 급증하고 생산성 저하로 이어집니다.

오버레이킷은 이러한 문제를 해결하기 위해 개발된 라이브러리입니다.


3. 오버레이킷의 핵심 기능과 장점은 무엇인가요?

오버레이킷의 주요 핵심 기능과 장점은 다음과 같습니다.

핵심 기능

  1. 선언적 오버레이 관리
    • 상태를 직접적으로 선언하여 오버레이 컴포넌트를 명료하게 관리합니다.
const overlay = useOverlay();

overlay.open(ModalComponent, { props });
overlay.close();

 

  1. 중첩 오버레이 및 우선순위 관리
    • 여러 오버레이가 중첩될 때 자동으로 Z-index 및 렌더링 순서를 관리합니다.
  2. 글로벌 오버레이 제어
    • 전역적으로 오버레이를 손쉽게 열거나 닫을 수 있습니다.
  3. 애니메이션 및 스타일링 지원
    • 손쉽게 애니메이션을 추가할 수 있으며 커스터마이징이 용이합니다.
  4. 유연한 컴포넌트 API
    • 커스터마이징 가능한 API를 통해 다양한 형태의 오버레이를 쉽게 구현할 수 있습니다.

장점

  • 단순하고 명료한 코드 작성
    • 선언적으로 UI를 관리하므로 코드 가독성과 유지보수가 쉬워집니다.
  • 빠른 개발 속도
    • 반복 작업을 최소화하여 생산성이 증가합니다.
  • 쉬운 상태 관리
    • 복잡한 UI 상태 로직이 단순화되어 디버깅이 쉬워집니다.
  • 재사용 가능한 코드 구조
    • 동일한 패턴을 반복하지 않고 간결한 코드로 다양한 컴포넌트를 다룰 수 있습니다.

4. 오버레이킷을 사용한 선언적 오버레이 관리 방법 (예시)

간단한 예시 코드입니다.

OverlayProvider로 루트 감싸기

import { OverlayProvider } from 'overlaykit';

const App = () => (
  <OverlayProvider>
    <MainApp />
  </OverlayProvider>
);

 

선언적으로 모달 열고 닫기

import { useOverlay } from 'overlaykit';
import Modal from './Modal';

const ExampleComponent = () => {
  const overlay = useOverlay();

  const handleOpenModal = () => {
    overlay.open(Modal, { title: 'Hello OverlayKit!' });
  };

  return (
    <button onClick={handleOpenModal}>
      모달 열기
    </button>
  );
};

 

위처럼 선언적으로 오버레이를 다룰 수 있어 코드가 매우 간결하고 명료해집니다.


정리

항목                                                      설명

 

오버레이킷 선언적 오버레이 관리 라이브러리
필요한 이유 복잡한 상태 관리, 중복 코드, 가독성 문제 해결
핵심기능 선언적 API, 중첩 및 전역 관리, 쉬운 애니메이션 지원
장점 코드 명료성, 생산성 향상, 쉬운 유지보수
 

오버레이킷을 이용하면 React 앱의 복잡한 오버레이 컴포넌트를 쉽고 직관적으로 다룰 수 있어 개발 효율과 코드의 품질을 크게 향상시킬 수 있습니다.

 

 

https://www.npmjs.com/package/@ilokesto/grunfeld

 

@ilokesto/grunfeld

Language : [영어](./EN_README.md) | 한국어. Latest version: 1.0.0, last published: 17 days ago. Start using @ilokesto/grunfeld in your project by running `npm i @ilokesto/grunfeld`. There are no other projects in the npm registry using @ilokesto/grunf

www.npmjs.com

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

전반코드

 

구조요약

 

 

런타임 예제 결과

 

타입 디버깅: ts-toolbelt 사용

 

 

  • F.Parameters<T>: 함수의 인자 타입 추출
  • F.Return<T>: 함수의 반환 타입 추출
  • 디버깅 시 각 단계의 타입을 비교하기 좋습니다

 

2. npm publish 가능한 라이브러리 구조화 (index.ts, types.ts, tests/) 과 실제 프로젝트에 통합하는 샘플 리포지토리 확장 

아래는 TypeScript 기반 migration-pipeline 유틸리티를 npm publish 가능한 구조로 정리한 라이브러리 템플릿과, 이를 실제 프로젝트에 통합하는 샘플 리포지토리 구성입니다. tsconfig, package.json, tests, dist, src 폴더까지 포함해 실제 배포도 가능한 구조입니다.

 

 

src/types.ts

 

src/compose.ts

 

src/index.ts

 

test/compose.test.ts (Vitest or Jest 기반)

 

package.json

 

tsconfig.json

 

npm publish 준비

npm install
npm run build   # dist/ 생성
npm publish --access public

 

2. 실제 프로젝트에서 사용 예시 (my-app/)

npm install migration-pipeline

 

 

추가: 타입 디버깅 도구 (ts-toolbelt)

npm install --save-dev ts-toolbelt

 

 

 

깃허브 리포지토리 예시명

https://github.com/your-username/migration-pipeline

 

 

자바스크립트에 정적 타입 문법을 추가한 ‘타입스크립트’가 네이티브 언어로 전환된다.

타입스크립트 수석 설계자인 아네르스 하일스베르 마이크로소프트 테크니컬 펠로우는 지난 11일 블로그를 통해 타입스크립트 성능을 근본적으로 개선하기 위해 컴파일러와 도구의 네이티브 이식 작업을 시작했다고 발표했다.

그는 “타입스크립트의 핵심 가치 제안은 뛰어난 개발자 경험”이라며 “코드베이스가 커질수록 타입스크리트 자체의 가치는 커지지만 이경우 가장 큰 코드베이스까지 확장할 수 없었다”고 설명했다.

그는 “대규모 프로젝트에서 작업하는 개발자는 긴 로드 및 확인 시간을 경험하고, 합리적인 편집기 시작 시간과 소스코드 전체 보기 중에서 선택해야 한다”며 “개발자는 자신있게 변수 이름을 바꾸고, 특정 함수에 대한 모든 참조를 찾고, 코드베이스를 쉽게 탐색하고, 지연 없이 모든 작업을 수행할 수 있을 때 좋아한다”고 덧붙였다.

그에 따르면, 마이크로소프트는 타입스크립트 컴파일러 도구의 네이티브 포팅 작업을 시작했다.

기계어 수준의 언어로 작성해 코드편집기에서 시작 시간을 크게 개선하고, 빌드 시간을 10배 단축하며, 메모리 사용량을 상당히 줄일 수 있게 된다고 안데르스 하일스버그는 설명했다. 그는 현재 코드베이스를 포팅해 2025년 중반까지 명령줄 유형 검사가 가능한 네이티브 구현의 미리보기를 선보일 것으로 예상했다. 연말까지 프로젝트를 위한 완벽한 기능을 갖춘 솔루션과 언어 서비스를 제공할 예정이라고 덧붙였다.

새로운 타입스크립트 컴파일러와 도구는 구글에서 개발한 프로그래밍 언어 ‘고(Go)’로 만들어진다. 마이크로소프트는 고 코드로 이뤄진 새로운 작업 리포지토리를 공유했다.

마이크로소프트는 현재의 자바스크립트 기반의 타입스크립트 5.8 버전과 곧 출시될 5.9 버전까지 기존 코드베이스를 유지하고, 타입스크립트 6 버전에서 향후 네이티브 코드베이스에 맞춰 일부 지원 중단과 중단 변경 사항을 도입한다. 새로운 네이티브 컴파일러와 도구로 이식된 버전은 타입스크립트7으로 불린다. 고 코드베이스 기반인 타입스크립트7 버전이 현재의 수준과 동등해지면 출시될 예정이다. 타입스크립트7 이후 성숙도가 충분히 올라갈 때까지 자바스크립트 코드베이스의 6.X 버전을 유지한다고 한다.

타입스크립트는 자바스크립트 엔진과 언어를 사용하면서 객체지향언어처럼 정적 타입을 활용할 수 있다. 2012년부터 만들어지기 시작해 2014년 1.0 버전으로 오픈소스로 공개됐다.

타입스크립트는 웹 언어로 클라이언트와 서버 애플리케이션을 개발할 수 있어 큰 인기를 끌고 있다. 하지만 코드 규모가 커지면 편집기 고급 기능을 활용해 작업할 때 전반적인 속도가 느려지는 문제가 있다.

특히 최근 들어 생성형 인공지능(AI) 기반의 코드 어시스턴트 기능을 코드 편집기에서 적극 활용하게 되면서 타입스크립트의 문제점이 커졌다.

일례로 비주얼스튜디오코드(VS코드)는 단순한 에디터면서 신택스 지정, 코드 자동완성, 코드 추천 등의 인텔리전스 기능을 확장 설치로 이용할 수 있다. 여기에 깃허브 코파일럿, 커서 등 다양한 생성형 AI 기반 코드 어시스턴트 기능도 붙여 이용할 수 있다.

VS코드에서 AI 기능을 이용하려면 프로그래밍 언어별 ‘랭귀지서버(LS)’를 연결해 언어 서비스를 받아야 한다. 편집기와 LS 간 정보 교환에 활용되는 프로토콜이 ‘랭귀지서버프로토콜(LSP)’이다. 타입스크립트도 LS와 LSP를 활용해 AI 보조 기능을 이용할 수 있다.

그러나 타입스크립트의 경우 AI 기능을 이용할 때마다 LS에서 자바스크립트 코드 전체를 읽고 컴파일하게 돼 긴 코드베이스 환경에서 AI 기능이 빠르게 작동하기 힘들다.

아네르스 하일스베르가 네이티브 전환 계획을 밝히며 편집기 성능과 AI 도구를 언급한 이유다. 만약 자바스크립트 대신 기계어에 가까운 언어로 타입스크립트 백엔드를 대체하면 대규모 코드베이스에서 나타난 문제점을 해결할 수 있다.

타입스크립트 코드베이스 로드 성능 비교 그에 의하면, VS코드에서 네이티브 타입스크립트를 활용할 경우 전체 프로젝트를 로드하는 데 걸리는 시간이 9.6초에서 1.2초로 줄어든다. 깃허브의 150만5000라인 규모의 코드베이스를 VS코드에서 이용할 때 현재 77.8초에서 7.5초로 10배 이상 로드 성능이 빨라진다.

하일스베르는 “모든 언어 서비스 작업(완성 목록, 빠른 정보, 정의로 이동, 모든 참조 찾기)에 대한 편집기 응답성도 상당한 속도 향상을 보일 것”이라며 “다른 언어와 구현을 더 잘 일치시키기 위해 오랜 인프라 작업 항목인 LSP로 이동할 것”이라고 밝혔다.

C# 창시자의 ‘고’ 채택에 커뮤니티는 “왜?”

타입스크립트에 고 백엔드를 도입한다는 발표 후 반응이 폭발했다. 각종 커뮤니티 게시판의 관련 포스트와 토론 스레드에 ‘불’ 이모지가 연이어 붙었다.

반응은 세갈래로 나뉜다. 일단 타입스크립트의 편집기 성능이 획기적으로 개선된다는 점에서 환영하는 입장이다.

다음은 왜 ‘고’를 백엔드 언어로 택했느냐는 반응이다. 이는 다시 ‘왜 러스트가 아니냐’와 ‘왜 C#이 아니냐’로 나눠진다.

특히 C#의 창시자인 아네르스 하일스베르가 ‘고’를 택했다고 발표했다는 것 자체에 실망감을 표한 반응이 다수를 이뤘다. 지난 수년 사이 마이크로소프트의 닷넷 플랫폼 기반 프로그래밍 언어 투자가 축소되고, 커뮤니티도 방치되고 있다는 불만이 누적돼왔다. 커뮤니티 내부의 불만이 쌓여있던 와중에 C# 닷넷의 창시자가 경쟁 플랫폼을 선택했다고 하자 불만이 격하게 표출된 것이다.

마이크로소프트 타입스크립트팀의 라이언 카바노프는 깃허브 F&Q에서 왜 ‘고’를 선택했는지 설명했다. 그는 “의미론과 코드 구조 측면에서 새로운 코드베이스를 가능한 한 호환되게 유지해야 한다는 것이 가장 중요한 측면”이라며 “구조적으로 유사한 코드베이스를 허용하는 언어는 두 코드베이스 간 변경 사항을 쉽게 이식할 수 있기 때문에 코드를 변경하는 모든 사람에게 상당한 이점을 제공한다”고 밝혔다.

이어 “고는 관용적인 언어로 타입스크립트 코드베이스의 기존 코딩 패턴과 매우 유사해 이식 작업이 훨씬 더 수월하다”며 “또한 고는 전체 코드베이스가 메모리 관리에 지속적으로 관여할 필요없이 메모리 레이아웃과 할당을 탁월하게 제어한다”고 덧붙였다.

타입스크립트의 네이티브 이식에서 여러 언어 가운데 고가 가장 목표 달성에 유리하고 성능 개선에서 우월했다는 것이다.

C# 창시자의 설명 “C#도 좋지만 호환성, 메모리 관리, 그래프 처리 때문에 고 선택”

이후에도 유사한 질문과 불만제기가 이어지자 아네르스 하일스베르가 직접 해명했다.

그는 “고로 이식하기로 한 결정은 실용적인 엔지니어링 선택”이라며 “우리의 초점은 사용된 언어와 관계없이 최상의 결과를 달성하는 것이었다”고 밝혔다. 이어 “타입스크립트 컴파일러의 고로 이동은 기존 자바스크립트 기반 코드베이스와 구조적 호환성, 메모리 관리의 용이성, 복잡한 그래프 처리 등을 효율적으로 관리할 수 있는 능력 같은 특정 기술적 요구사항의 영향 때문”이라며 “수많은 언어를 평가하고 C#을 포함한 여러 프로토타입을 만든 후 고가 최적의 선택으로 결정된 것”이라고 했다.

그러면서 “C#에서 컴파일러를 처음부터 재설계할 수 있고 효과도 있었을 것”이라며 “하지만 이것은 컴파일러 재설계가 아니었고, 타입스크립트에서 고로 이동은 훨씬 더 자동화가 가능했으며, 매핑에서 일대일로 더 많이 이뤄졌다”고 덧붙였다.

또한 “이 결정이 C#과 닷넷에 대한 우리의 깊고 지속적인 투자를 약화시키지 않는다”며 “마이크로소프트의 서비스와 제품 대부분은 타의 추종을 불허하는 생산성, 강력한 생태계, 강력한 확장성으로 인해 C#과 닷넷에 크게 의존하며, C#은 빠르고 유지 관리 가능하며 확장 가능한 개발을 요구하는 시나리오에서 뛰어나고 중요한 시스템과 수많은 내부 및 외부 마이크로소프트 솔루션을 구동한다”고 강조했다.

그는 이번 선택이 정치적 고민보다 철저한 실용주의에 입각해 이뤄졌다는 점을 밝혔다. 마이크로소프트가 내부 정치적 토론에서 닷넷과 C#을 포기한 게 아니란 것이다.

그는 “현실적으로 보면, 마이크로소프트가 고를 사용해 타입스크립트 컴파일러를 작성하는 건 몇년 전만 해도 불가능하거나 상상조차 할 수 없었다”며 “지난 수십년 간 마이크로소프트는 오픈소스 소프트웨어에 대한 강력하고 지속적인 헌신을 보였으며 무엇보다 개발자 생산성과 커뮤니티 협업을 우선시했다”고 설명했다.

이어 “당사의 목표는 내부 정치나 좁은 제약에 얽매이지 않고 개발자에게 최상의 도구를 제공하는 것”이라며 “각 특정 작업에 적합한 도구를 선택할 수 있는 이런 자유는 궁극적으로 전체 개발자 커뮤니티에 이롭게 작용해 혁신, 효율성, 개선된 결과를 촉진한다”고 강조했다.

타입스크립트에 대한 마이크로소프트의 결정에 너무 많은 토론이 진행되자 깃허브 F&Q 페이지의 댓글 기능은 중단됐다. 래딧, 해커뉴스 등에선 여전히 이번 타입스크립트 네이티브 전환에 대한 결렬한 토론이 이어지고 있다.

 

글. 바이라인네트워크 <김우용 기자>yong2@byline.network 

 

AI 겸용으로 타입스크립트 속도가 10배 빨라진다고 하는데 그 구체적인 내용은 무엇인가요?

 

응답:

이번 타입스크립트 네이티브 전환 소식에서 "속도 10배 향상" 이라는 말이 어떻게 가능한지를 구체적으로 분석해보면 **핵심은 "컴파일러와 언어 서비스의 네이티브 포팅"**에 있습니다. 요약해서 정리하면 다음과 같은 구체적인 기술적 이유로 설명됩니다:


1. 왜 10배 빠른가?

(1) 자바스크립트 한계:

  • 현재 **타입스크립트 컴파일러(tsc)**와 **언어 서비스 (Language Server, LS)**는 **자바스크립트(혹은 타입스크립트 자신)**로 작성되어 있습니다.
  • 브라우저 기반 JS 엔진의 특성상 메모리, 실행 속도, 대규모 그래프 탐색에 한계가 있어,
    • **대규모 코드베이스(수십만 ~ 수백만 라인)**에서 매우 느림.
    • 특히 코드 자동 완성, 참조 찾기, 리팩토링 등이 심각하게 느려짐.

(2) 네이티브 전환의 효과:

  • Go 언어로 포팅하면서 네이티브 수준의 성능이 가능해짐.
  • 기계어에 가까운 최적화된 코드로 실행 → 자바스크립트 런타임을 거치지 않음.
  • 메모리 사용량 최적화, GC 간섭 최소화, 직접 메모리 관리 가능.
  • 특히 복잡한 타입 관계와 대규모 의존 그래프 처리 속도가 비약적으로 개선됨.

2. 정량적 성능 향상 데이터

항목                                                                                                                 기존 타입스크립트 (JS 기반)     네이티브 포팅 (Go 기반)

 

VSCode 전체 프로젝트 로드 시간 9.6초 1.2초
150만 라인 규모 깃허브 코드베이스 로드 시간 77.8초 7.5초
  • 10배 이상 빠른 초기 로딩 성능.
  • 메모리 사용량도 크게 감소 (구체 수치는 아직 공개 전).

3. 어디서 성능 차이가 나는가?

기능                                                                                                개선 효과

 

초기 프로젝트 로드 (Parsing & Graph 생성) 대형 프로젝트 열 때 지연 없이 로드 가능
타입 검사 (Type Checking) 코드 변경 시 빠른 타입 확인, 빌드 대기 시간 단축
코드 자동 완성 (IntelliSense) AI 보조 기능, 자동 완성 등 즉각 반응
참조 찾기 (Find References) 수백만 라인에서도 빠르게 참조 찾기 가능
변수/함수 이름 변경 (Rename) 대규모 프로젝트에서도 딜레이 없는 리팩토링 수행 가능
코드 탐색 (Go to Definition) 즉각적인 심볼 이동, 정의 보기 등 코드 네비게이션 성능

4. 왜 특히 AI 코드 보조에서 중요한가?

  • 최근 Copilot, Cursor 등 AI 어시스턴트 타입스크립트 코드베이스 언어 서버로 접근하는데,
  • 매 요청마다 전체 타입 그래프/의존성 분석이 필요하기 때문에 지연이 발생.
  • 네이티브 타입스크립트는 AI 요청에 대한 응답 시간을 획기적으로 단축 → AI 코딩 경험 품질 대폭 상승.

5. 마지막, 왜 Go인가?

  • 기존 TS 코드베이스와 코드 구조가 유사 → 포팅이 쉬움.
  • 메모리 관리와 성능 Rust, C++ 만큼 복잡하지 않으면서도 충분히 빠름.
  • 내부에서 복잡한 타입 그래프와 의존성 처리, 메모리 효율적 관리가 쉬움.
  • 대량 병렬 처리, 스레드 관리, 네트워크 대응도 유리.

결론

측면                                                  기대 효과

 

빌드 시간 10배 빠름 (수십 초 → 수 초)
메모리 사용량 감소 (대규모 프로젝트에서도 저사양 장비 가능)
AI 보조 속도 AI 기반 코드 자동완성, 추천이 실시간에 가깝게 가능
편집기 반응성 대형 코드베이스에서도 지연 없는 코딩
리팩토링 도구 즉각적인 대규모 리팩토링 (변수/함수명 일괄 변경 등)

요약하면, 타입스크립트 네이티브 전환으로 가장 크게 바뀌는 것은 "대형 코드베이스에서의 생산성"과 "AI 보조 개발 환경"입니다. 10배 빠른 편집기 반응성, 빌드 시간 단축, AI 보조 코드의 실시간 피드백이 가장 눈에 띄는 변화죠.

 

 

질문:VS Code 에서 타입스크립트 네이티브 전환효과를 볼려면 어떻게 해야하는가요?

응답:

1. 네이티브 타입스크립트 전환 적용 일정 (예상)

버전                                    주요 특징                                                                                                           출시 시기 (예상)

 

TypeScript 5.9 기존 JS 기반, 마지막 안정적 유지 버전 2024년 상반기 (곧 출시)
TypeScript 6.x JS 기반 유지 + 일부 기능 제한/이식 작업 시작 2024년 하반기
TypeScript 7.0 Go 기반 네이티브 타입스크립트 첫 프리뷰 (커맨드라인 타입 검사 가능) 2025년 중반 (미리보기)
TypeScript 7.x VS Code 통합 & 언어 서비스 제공 (완전 전환) 2025년 말 ~ 이후

즉, VS Code 편집기 내에서 네이티브 타입스크립트 효과 직접 체감 가능한 시점은 2025년 후반 이후로 예상됩니다.


2. VS Code 사용자 입장에서 전환 효과 보려면?

(1) 자동 적용 방식 (예정)

  • 현재처럼 **VS Code가 내장한 TypeScript Language Server (TSLS)**가 버전 업되면서 자동으로 네이티브 타입스크립트로 전환됩니다.
  • 사용자가 별도로 Go 기반 타입스크립트를 설치하지 않아도 VS Code 업데이트만으로 사용 가능.
  • 마치 VS Code가 내장하는 타입스크립트 버전이 자동 업그레이드되는 것과 같은 방식.

결론: VS Code만 최신 버전으로 유지하면 자동 적용될 예정.


(2) 직접 적용 및 테스트 방식 (초기 단계)

  • TypeScript 7.0 미리보기(프리뷰) 버전이 출시되면,
    • 초기에는 **명령어 기반 tsc (컴파일러)**로 제공.
    • VS Code 언어 서버와 연결된 공식 릴리스는 이후 제공.
  • 따라서 2025년 초반에는 직접 tsc 명령어로 CLI 상에서 테스트 가능,
    • VS Code 통합 언어 서비스(LSP) 적용은 후속 릴리스에서 체감 가능.

결론: 2025년 중반에 CLI, 2025년 말쯤 VS Code 언어 서비스로 본격 적용 예상.


3. 향후 준비 및 설정 방법

시기                              준비/설정 방법

 

현재~2024년 기존 TypeScript 버전 사용. 프로젝트의 ts 버전 맞춰 사용.
2025년 초반 TypeScript 7.x 프리뷰 나오면 CLI로 테스트. (tsc 명령어로)
2025년 후반~ VS Code 업그레이드 시 자동 내장. 빠른 언어 서비스 사용.
원하는 경우 수동 설정 특정 프로젝트에 직접 네이티브 TS 연결 (예상): tsdk 경로 설정. 예: typescript.tsdk를 새로운 네이티브 타입스크립트 SDK로 변경.
 
// settings.json (VSCode 사용자 설정 예시)
{
  "typescript.tsdk": "./node_modules/typescript" // 향후 네이티브 SDK 경로 가능성
}

 

 

4. 언제 효과를 바로 보게 될까?

체감 가능한 기능                                                     언제 가능?                                                   설명

 

빠른 코드 로드 (대규모 프로젝트) 2025년 말 예상 VSCode에서 대규모 프로젝트 즉시 열림
빠른 코드 자동완성/참조 찾기 2025년 말 예상 AI 보조, Copilot, Cursor 사용 시 즉각 반응
빠른 타입 검사 (tsc 빌드) 2025년 중반 (CLI) CLI 빌드 및 검사 10배 속도 (미리보기로)
AI 보조 속도 개선 (Copilot, Cursor) 2025년 말 예상 AI 어시스턴트가 LSP 통해 실시간 반응
메모리 사용량 감소 2025년 말~이후 대규모 코드에서도 VSCode 느려지지 않음

5. 현재 할 수 있는 준비

  • 2025년까지는 기존 타입스크립트 5.x, 6.x 버전을 사용해야 합니다.
  • 현재 할 수 있는 준비:
    • 코드베이스 정리 (타입 체크/타입 최적화).
    • ESM (모듈화), strict 모드 채택 (미래 호환성).
    • VS Code 최신 버전 유지 (자동 적용을 위해).
    • 대규모 프로젝트에서 타입스크립트 느린 현상 모니터링 → 전환 시 개선 여부 확인 준비.

정리

질문                                                                                                                 답변

 

VS Code에서 언제 네이티브 TS 사용 가능? 2025년 말 이후 VSCode 업그레이드로 자동 적용
직접 사용할 수 있는 시점? 2025년 중반 CLI로 미리보기, 이후 언어 서버 통합
설정해야 할 것? 향후 VSCode typescript.tsdk로 경로 지정 가능성
현재 할 일? 기존 타입스크립트 최적화, 모듈화, strict 모드 준비
체감 가능한 효과? 대규모 프로젝트에서 빠른 로드, AI 보조 속도, 메모리 개선

 

 

 

 

 

 

 

 

 

 

 

+ Recent posts