TS: ํ”„๋กœ์ ํŠธ ์ดˆ๊ธฐ ์„ค์ •

2025. 7. 3. 19:19ใ†Front-end/TypeScript

๋ฐ˜์‘ํ˜•

[ ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ ]

๋ชฉ์ฐจ

1. ํ”„๋กœ์ ํŠธ์— ts ์„ค์น˜ ๋ฐ ์ดˆ๊ธฐํ™”

2. ํ’€์Šคํƒ ํ”„๋กœ์ ํŠธ ์„ค์ •ํ•˜๊ธฐ

3. ํ…Œ์ŠคํŠธ ์„ค์ •ํ•˜๊ธฐ


1. ํ”„๋กœ์ ํŠธ์— ts ์„ค์น˜ ๋ฐ ์ดˆ๊ธฐํ™”

ํ•™์Šต์šฉ ํ”„๋กœ์ ํŠธ ํด๋”์— ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์ดˆ๊ธฐํ™”ํ•ด๋ณด์ž.

 

์„ค์น˜

npm install -D typescript

node_module ํด๋”๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๋‹ค

 

** ๊ทธ๋™์•ˆ --save-dev(์•ฝ์นญ : -D)์˜ ์˜๋ฏธ๋ฅผ ์ž˜ ๋ชฐ๋ž๋Š”๋ฐ ์ด๋ฒˆ์— ์งš๊ณ  ๋„˜์–ด๊ฐ€๋ดค๋‹ค.

์ด๊ฑด ์„ค์น˜ํ•˜๋Š” ํŒจํ‚ค์ง€๋ฅผ ๊ฐœ๋ฐœ(Development) ์˜์กด์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•œ๋‹ค๋Š” ์˜๋ฏธ๋กœ,

ํ”„๋กœ์ ํŠธ๋ฅผ NPM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋ฐฐํฌํ•  ๋•Œ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

  • ๊ฐœ๋ฐœํ•  ๋•Œ๋งŒ ํ•„์š”ํ•œ ํˆด(๋Ÿฐํƒ€์ž„ ์‹œ ํ•„์š” ์—†์Œ)

+ ์ตœ๊ทผ npm ๋ฒ„์ „(6 ์ด์ƒ)์—์„œ๋Š” ์œ„ ํ‚ค์›Œ๋“œ๋Š” ์ƒ๋žต ๊ฐ€๋Šฅํ•œ ๊ธฐ๋ณธ๊ฐ’์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

 

์ดˆ๊ธฐํ™”

npx tsc --init

์œ„์™€ ๊ฐ™์ด ์ดˆ๊ธฐํ™”๋ฅผ ํ•˜๋ฉด tsconfig.json ํŒŒ์ผ์ด ์ถ”๊ฐ€๋กœ ์ƒ์„ฑ๋œ๋‹ค.

 

tsconfig.json ํŒŒ์ผ์„ ๋ณด๋ฉด ์ฃผ์„์ด ์ฐธ ๋งŽ์€๋ฐ ์ฃผ์„๋“ค์„ ์ œ์™ธํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋‚จ๋Š”๋‹ค.

{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
  • "target": "es2016"
    ํ”„๋กœ์ ํŠธ์˜ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ECMAScript 2016 ๋ฌธ๋ฒ•์œผ๋กœ ์ปดํŒŒ์ผํ•œ๋‹ค.
  • "module": "commonjs"
    ์ปดํŒŒ์ผ๋œ JS ์ฝ”๋“œ์—์„œ ์–ด๋–ค ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ• ์ง€ ์ •์˜ํ•˜๋Š” ์˜ต์…˜์œผ๋กœ, "commonjs" ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ECMAScript ๋ชจ๋“ˆ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. next.js๊ฐ™์€ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด "commonjs"๊ฐ€ ์•„๋‹Œ "esnext"๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.
  • "esModuleInterop": true
    ECMAScript ๋ชจ๋“ˆ ์™ธ์˜ ์ž„ํฌํŠธ๋œ ๋ชจ๋“ˆ๋“ค์˜ ํ‘œ์ค€์„ ์ผ์น˜์‹œํ‚จ๋‹ค.
  • "forceConsistentCasingInFileNames": true
    ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ณ„ํ•˜๋Š” ํŒŒ์ผ ์‹œ์Šคํ…œ ์ง€์› ์˜ต์…˜์ด๋‹ค.
  • "strict": true
    ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ ์šฉํ•˜๋ผ๋Š” ์„ค์ •์ด๋‹ค. (ํƒ€์ž… ๋ช…์‹œ, ํƒ€์ž… ์ถ”๋ก ์ด any์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ, ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ฐ˜๋“œ์‹œ ์ดˆ๊ธฐํ™” ๋“ฑ๋“ฑ)
  • "skipLibCheck": true
    ์˜ค๋ฅ˜๊ฐ€ ์—†๋Š” ํ˜•์‹ ์ •์˜ ํŒŒ์ผ๋“ค์„ ์„ค์น˜ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์—ฌ, ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํ˜•์‹ ์ •์˜ ํŒŒ์ผ์„ ๋‹ค์‹œ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š๋Š”๋‹ค. -> ์ปดํŒŒ์ผ๋Ÿฌ ๋™์ž‘ ์†๋„๊ฐ€ ์กฐ๊ธˆ ๋นจ๋ผ์ง„๋‹ค.

 

์•„๋ž˜์™€ ๊ฐ™์€ ์„ค์ •์„ compilerOptions์— ์ถ”๊ฐ€ํ•ด๋ณด์ž

"rootDir": "./src",		// src ํด๋”๋ฅผ ๋ฃจํŠธ ๊ฒฝ๋กœ๋กœ ์ง€์ •
"outDir": "./dist"		// ์ปดํŒŒ์ผ๋œ ํŒŒ์ผ์„ dist ํด๋”์— ์ €์žฅํ•˜๋„๋ก ์ง€์‹œ

 

 

์ด์ œ src ํด๋”์— index.ts๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์ปดํŒŒ์ผ ํ•˜๋ฉด dist ํด๋”์—์„œ ์ปดํŒŒ์ผ๋œ ํŒŒ์ผ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

// src/index.ts
console.log("Hello World!");

 

์ปดํŒŒ์ผ

npx tsc

 

// dist/index.ts
"use strict";
console.log("Hello, TypeScript!");

 

 

 


2. ํ’€์Šคํƒ ํ”„๋กœ์ ํŠธ ์„ค์ •ํ•˜๊ธฐ

ํ”„๋ก ํŠธ์šฉ, ๋ฐฑ์šฉ tsconfig ํŒŒ์ผ์„ ๊ฐ๊ฐ ๋งŒ๋“ค๊ณ  composite์œผ๋กœ ๊ณต์œ ๋œ ์˜์กด์„ฑ์„ ๋ถˆ๋Ÿฌ์™€๋ณด์ž.

Node.js์™€ ๋ธŒ๋ผ์šฐ์ € ๋ชจ๋‘ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜์ง€๋งŒ, ์ˆ˜ํ–‰ํ•˜๋Š” ์—ญํ• ์ด ๋งŽ์ด ๋‹ค๋ฅด๋‹ค.

 

๋ธŒ๋ผ์šฐ์ € ๋ฐ–์—์„œ JavaScript๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“  ํ™˜๊ฒฝ(runtime)์ธ Node.js ์ฝ”๋“œ๋ฅผ ์˜ˆ์‹œ๋กœ ๋ณด์ž.

const http = require('http');

const hostname = '127.0.0.1';
const port = process.env.PORT || 3000;

const server = http.createServer((req, res) => {
	res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Hello World');
});

server.listen(port, hostname, () => {
	console.log(`Server running at http://${hostname}:${port}/`);
});

 

์ด์–ด์„œ ํ™”๋ฉด์— ์›น์‚ฌ์ดํŠธ๋ฅผ ๊ทธ๋ ค์ฃผ๋Š” ํ™˜๊ฒฝ์ธ ๋ธŒ๋ผ์šฐ์ € ์ฝ”๋“œ๋ฅผ ๋ณด์ž.

import {msg} from `./msg.js`;

document.querySelector('button')?.addEventListener("click", () => {
	console.log(msg);
});

 

 

๋‘˜๋‹ค ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋กœ ์ž‘์„ฑ๋˜์ง€๋งŒ ๋‹ค๋ฅธ ์ ์ด ๋งŽ์•„, ํ•œ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ์ ํŠธ๋กœ ์ง€์›ํ•˜๊ธฐ๋Š” ์–ด๋ ต๋‹ค.

๋”ฐ๋ผ์„œ ํ’€์Šคํƒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌํ˜„์„ ์œ„ํ•ด์„œ๋Š” ๊ฐ ์Šคํƒ์„ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ์„ค์ • ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

 

๋ฐฑ์—”๋“œ์˜ ๊ตฌํ˜„๊ณผ ์„ค์ •์€ server๋ผ๋Š” ์ƒˆ ํด๋”๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ž‘์„ฑํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์„œ๋ฒ„์šฉ tsconfig.json ํŒŒ์ผ ๋‚ด์šฉ์„ ํ™•์ธํ•ด๋ณด์ž.

npm install -D express

 

{
    "compilerOptions": {
        "target": "ESNext",
        "lib": ["ESNext"],
        "module": "commonjs",
        "rootDir": "./",
        "outDir": "../dist/server",
        "moduleResolution": "node",
        "types": ["node"],
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true
    }
}

 

 

 

์ด๋•Œ node๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๋Š” ์—๋Ÿฌ๊ฐ€ ๋œฐ ์ˆ˜ ์žˆ๋Š”๋ฐ, @types/node๋ฅผ ์„ค์น˜ํ•ด์„œ ํ•ด๊ฒฐํ•ด์ฃผ๋ฉด ๋œ๋‹ค

https://ldd6cr-adness.tistory.com/325

 

@types : JS ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ TS ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ

๋ชฉ์ฐจ1. DefinitelyTyped๋ž€?1. DefinitelyTyped๋ž€?ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํƒ€์ž… ์„ ์–ธ ํŒŒ์ผ(.d.ts)์„ ๋ชจ์•„๋‘” ์˜คํ”ˆ์†Œ์Šค ์ €์žฅ์†Œ์ด๋‹ค. https://github.com/DefinitelyTyped/DefinitelyTyped G

ldd6cr-adness.tistory.com

 

 

server ํด๋”์— ์ด์–ด์„œ ๊ฐ„๋‹จํ•œ index.ts ํŒŒ์ผ์„ ์ž‘์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•ด์ฃผ๋ฉด dist์— ์‹คํ–‰ํŒŒ์ผ์ด ์ƒ์„ฑ๋œ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

// server/index.ts
console.log('Server running...');

 

์‹คํ–‰

npx tsc -p server/tsconfig.json

 

 

 

ํ”„๋ก ํŠธ์™€ ๋ฐฑ์˜ tsconfig.json์„ ๊ฐ๊ฐ ์ž‘์„ฑํ•ด๋ดค๋Š”๋ฐ, ์œ„์—์„œ๋Š” ๊ฐ ํด๋”์— tsconfig.json์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ํŒŒ์ผ์„ ์ž‘์„ฑํ–ˆ์ง€๋งŒ,

๋‘˜๋‹ค ๋ฃจํŠธ์— ์ž‘์„ฑํ•˜๋Š” ๋Œ€์‹  ์ด๋ฆ„์„ tsconfig.server.json ๊ณผ tsconfig.client.json๊ณผ ๊ฐ™์ด ๋ฐ”๊ฟ”์„œ ์ €์žฅํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

 

ํ˜น์€ ๋‘ ์„ค์ • ํŒŒ์ผ์ด ์˜์กด์„ฑ์„ ๊ณต์œ ํ•ด์•ผํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์ด ๋•Œ๋Š” client, server ํด๋”์™€ ๊ฐ™์€ ์œ„์น˜์— shared ํด๋”๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ ์•ˆ์— tsconfig.json์„ ์ž‘์„ฑํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

// shared/tsconfig.json

{
	"compilerOptions": {
    	"composite": true,
        "target": "ESNext",
        "module": "ESNext",
        "rootDir": "../shared/",
        "outDir": "../dist/shared",
        "moduleResolution": "Node",
        "types": [],
        "declaration": true,
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true
    },
}
  • "composite": true  =>  ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๊ฐ€ ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค
  • "declaration": true  =>  ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๊ฐ€ ํ˜•์‹ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ์—์„œ d.ts ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค.

์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ์˜ ์„ค์ • ํŒŒ์ผ์€ ์•„๋ž˜ ํ–‰์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ณต์œ ๋œ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

{
	"compilerOptions": {
    // ...
    },
    "references": [
    	{
        	"path": "../shared/tsconfig.json"
        }
    ]
}

 

 

 

 

 

 

 

 

 

 

์ฐธ๊ณ 

๋”๋ณด๊ธฐ
๋ฐ˜์‘ํ˜•