[아키텍처] TypeScript에 대한 고민
# 30년차 개발자가 TypeScript를 버린 이유
> "타입 선언 파일 4개를 만들면서 '이게 맞나?' 싶었습니다."
---
## 들어가며
COBOL부터 시작해서 VB, Java, C#, 그리고 최근의 TypeScript까지 — 기술 트렌드의 흥망성쇠를 모두 지켜봤습니다.
그런 제가 최근 TypeScript를 포기하고, 많은 분들이 "구시대적"이라 부르는 저장 프로시저(Stored Procedure) 중심 아키텍처로 돌아갔습니다.
미친 짓일까요? 아니면, 30년의 경험이 알려주는 본질로의 회귀일까요?
---
## 문제의 시작: 4개의 똑같은 정의
어느 날, 신입 개발자가 물었습니다.
> "선배님, User_Name 필드 하나 추가하는데 왜 파일 4개를 수정해야 하나요?"
저는 대답하려다 멈췄습니다. 왜냐하면, 저도 그 이유를 납득할 수 없었기 때문입니다.
```
1. Database: VARCHAR(50) NOT NULL
2. Backend: public string UserName { get; set; }
3. API Spec: type: string, maxLength: 50
4. Frontend: interface IUser { userName: string }
```
본질(데이터)은 하나인데, 그걸 설명하는 껍데기(Interface)가 4개입니다.
저는 이것을 "다중 발화의 위기(Crisis of Multiple Mouths)"라고 부르기로 했습니다.
---
## 역사는 반복된다: CORBA의 망령
90년대 후반, CORBA와 SOAP/WSDL이 있었습니다. 통신을 위해 IDL(Interface Definition Language)로 거대한 명세서를 작성하고, Stub/Skeleton 코드를 생성해야 했죠.
결과는? 기술 종속, 변경의 경직성, 그리고 결국 도태.
2010년대, JSON과 REST가 승리한 이유는 단 하나였습니다: 단순함. 복잡한 타입 정의 없이 { "name": "홍길동" } 이렇게 보내면 끝이었습니다.
그런데 지금 우리는 뭘 하고 있나요?
```typescript
interface IUser {
id: number;
name: string;
email: string;
// ... 50줄 더
}
type UserDTO = Pick<IUser, 'name' | 'email'>;
type UserResponse = Omit<IUser, 'password'>;
// 대체 이게 뭡니까?
```
JSON 위에 다시 WSDL을 짜고 있는 겁니다.
TypeScript는 JSON의 장점인 유연함을 스스로 거세하고 있습니다. 이건 기술적 진보가 아니라 퇴행(Regression)입니다.
---
## 해결책: Single-Mouth Architecture (SMA)
고민 끝에 저는 새로운 방법론을 정립했습니다.
핵심 원칙: "입은 하나면 족하다 (One Mouth is Enough)"
```
┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐
│ CLIENT │ │ MIDDLEWARE │ │ DATABASE │
│ (멍청한 UI)│────▶│ (로직 없음) │────▶│ (단일 창구) │
│ │◀────│ │◀────│ USP_* = 모든 로직 │
└─────────────┘ └─────────────┘ └─────────────────────┘
```
### 원칙 1: 데이터 주권은 DB에게
데이터의 타입, 길이, 제약조건을 정의할 권한은 오직 데이터베이스만 가집니다. 소스 코드는 데이터를 정의하는 주체가 아니라, 데이터가 흐르는 파이프일 뿐입니다.
### 원칙 2: 네이밍이 곧 타입이다
타입 선언 파일 대신, 의미론적 명명 규칙을 사용합니다.
| 접미어 | 의미 | 자동 동작 |
|--------|------|-----------|
| _DT | 날짜 | DatePicker 렌더링 |
| _AMT | 금액 | 천 단위 콤마, 우측 정렬 |
| _CNT | 개수 | 정수만 허용 |
| Is_ | Boolean | Checkbox 렌더링 |
User_NM을 보면 누구나 "문자열, 이름"임을 압니다. .d.ts 파일을 뒤질 필요가 없습니다.
### 원칙 3: 예외 주권도 DB에게
```sql
-- DB에서 구체적인 에러 메시지 생성
THROW 51100, N'잔액이 500원 부족합니다. 현재 잔액: 1,500원', 1;
```
이 메시지가 Backend를 거쳐 Frontend까지 그대로 전달됩니다. 중간에 "다시 시도해 주세요" 같은 쓸모없는 메시지로 변환되지 않습니다.
---
## AI 시대, SMA가 빛나는 이유
ChatGPT, Claude, Copilot... AI가 코드를 분석하려면 관련 코드를 Context Window에 올려야 합니다.
기존 방식:
```
Entity.cs + DTO.cs + Controller.cs + Service.cs +
Interface.cs + Repository.cs + *.d.ts = 15,000 토큰
```
SMA 방식:
```
USP_UserGet.sql + AutoForm.tsx = 4,500 토큰
```
70% 감소. 같은 비용으로 3배 더 많은 로직을 AI에게 보여줄 수 있습니다.
토큰이 줄면:
- API 비용 절감
- AI의 Attention 집중 → 환각(Hallucination) 감소
- 더 정확한 코드 생성
---
## "그래도 타입 안전성이..."
이 질문을 수백 번 받았습니다. 제 대답은 이렇습니다:
1. 컴파일 에러 ≠ 프로그램 무결성: 타입이 맞아도 로직이 틀리면 망합니다. 치명적 버그의 80%는 로직 오류입니다.
2. DB가 이미 검증합니다: MSSQL, Oracle은 이미 강력한 타입 검증을 수행합니다. 애플리케이션에서 다시 검증하는 건 중복입니다.
3. 런타임 방어가 현실적입니다: 실제 데이터는 런타임에 들어옵니다. 컴파일 타임에 모든 케이스를 예측하는 건 환상입니다.
---
## 결론: 본질을 직시하라
30년간 수많은 기술이 왔다 갔습니다. 살아남은 것들의 공통점은 단순함이었습니다.
TypeScript가 나쁜 기술이라는 게 아닙니다. 다만, "이게 정말 필요한가?"를 질문해야 합니다.
> "코드는 사라지지만, 데이터는 남는다."
개발자는 형식을 맞추는 타이피스트가 아니라, 문제를 해결하는 설계자입니다. 화려한 프레임워크 뒤에 숨지 말고, 본질을 직시하세요.
---
## 더 알아보기
- GitHub: [AletheiaJung/Single-Mouth-Architecture](https://github.com/AletheiaJung/Single-Mouth-Architecture)
- WhitePaper: 전체 기술 백서 (한국어/영어)
- 샘플 코드: MSSQL + C# + React 참조 구현
피드백과 토론을 환영합니다. 댓글로 의견 남겨주세요!
단, 이 글은 단지 소개의 글입니다. 지금의 아키텍쳐아니라면 뭐하자는 거지?
부족하지만 나름 고민하여 답을 찾고자 하였으니 먼저 https://github.com/AletheiaJung/Single-Mouth-Architecture/blob/main/WhitePaper_v2.md 읽고 의견을 주시면 감사하겠습니다.
---
#SMA #SingleMouthArchitecture #TypeScript #StoredProcedure #아키텍처 #개발철학 #AI시대