[as] feat: 설치인가 서비스 구현

This commit is contained in:
2026-02-25 17:10:56 +09:00
parent 947751431e
commit 6e7b3dd539
22 changed files with 6701 additions and 963 deletions
+189 -30
View File
@@ -15,46 +15,131 @@ Next.js 애플리케이션 with FSD(Feature Sliced Design) 아키텍처
## 프로젝트 구조 (FSD)
이 프로젝트는 **Feature-Sliced Design v2.1**을 따르며, 계층적 아키텍처로 구성되어 있습니다.
```
as/
├── app/ # Next.js App Router (라우팅)
│ ├── layout.tsx
│ ├── page.tsx
│ ├── globals.css
│ └── providers.tsx
├── shared/ # 공통 코드 레이어
│ ├── api/ # API 클라이언트 설정
│ ├── config/ # 환경 설정
│ ├── lib/ # 유틸리티 라이브러리
│ ├── types/ # 공통 타입 정의
│ └── ui/ # 공통 UI 컴포넌트
├── entities/ # 비즈니스 엔티티
├── features/ # 비즈니스 기능
└── widgets/ # 복합 UI 블록
├── app/ # App 레이어 (Next.js App Router)
│ ├── (routes)/ # 라우트 구조
│ ├── layout.tsx # 루트 레이아웃
│ ├── page.tsx # 홈 페이지
│ ├── globals.css # 글로벌 스타일
│ └── providers.tsx # 전역 providers
│
├── widgets/ # Widgets 레이어
│ └── [widget-name]/ # 큰 독립적 UI 블록 (여러 페이지에서 재사용)
│ ├── ui/
│ ├── model/
│ └── index.ts
│
├── features/ # Features 레이어
│ └── [feature-name]/ # 사용자 상호작용 기능 (여러 페이지에서 재사용)
│ ├── ui/
│ ├── api/
│ ├── model/
│ └── index.ts
│
├── entities/ # Entities 레이어
│ └── [entity-name]/ # 비즈니스 엔티티 (User, Product 등)
│ ├── model/
│ ├── api/
│ ├── ui/
│ └── index.ts
│
└── shared/ # Shared 레이어
├── ui/ # UI Kit (비즈니스 로직 없는 공통 컴포넌트)
├── api/ # API 클라이언트 설정
├── lib/ # 내부 라이브러리 (dates, colors 등)
├── config/ # 환경 설정, feature flags
├── types/ # 공통 타입 정의
└── routes/ # 라우트 상수
```
### 계층 구조 이해하기
FSD는 **3단계 계층**으로 구성됩니다:
1. **Layers (레이어)**: 책임과 의존성에 따른 수평적 분리 (app, pages, widgets, features, entities, shared)
2. **Slices (슬라이스)**: 비즈니스 도메인에 따른 수직적 분리 (user, product, auth-login 등)
3. **Segments (세그먼트)**: 기술적 목적에 따른 분리 (ui, api, model, lib 등)
> 📚 각 레이어의 자세한 설명은 해당 폴더의 README.md를 참고하세요.
## FSD 레이어 설명
### 1. Shared
- 프로젝트 전체에서 재사용되는 코드
- 비즈니스 로직 없음
- API 클라이언트, 유틸리티, UI 컴포넌트 등
FSD는 계층적 아키텍처로, 각 레이어는 책임의 범위와 의존성의 정도에 따라 구분됩니다. 7개의 표준화된 레이어가 있으며, 프로젝트에 필요한 레이어만 사용하면 됩니다.
### 2. Entities
- 비즈니스 엔티티 (예: User, Product, Order)
- 엔티티 모델, 타입, API 호출
### 레이어 계층 구조 (위에서 아래로)
### 3. Features
- 사용자 시나리오와 기능 (예: 로그인, 상품 검색)
- 한 가지 기능에 집중
```
app/ ↑ 가장 높은 책임, 가장 많은 의존성
pages/ |
widgets/ |
features/ |
entities/ |
shared/ ↓ 가장 낮은 책임, 의존성 없음
```
### 4. Widgets
- 여러 features와 entities를 조합한 복잡한 UI 블록
- 독립적으로 작동 가능한 UI 컴포넌트
### 1. App
- **목적**: 앱 전체에 영향을 주는 기술적/비즈니스적 사항
- **내용**: Context providers, 글로벌 스타일, 스토어 설정, 라우터 설정, 애널리틱스
- **특징**: 슬라이스가 없고 세그먼트로만 구성
- **의존성**: 모든 하위 레이어 사용 가능
### 5. App
- Next.js App Router
- 라우팅 및 전역 providers 설정
### 2. Pages (app 디렉토리)
- **목적**: 웹사이트나 애플리케이션을 구성하는 페이지/화면
- **내용**: 페이지 UI, 로딩 상태, 에러 바운더리, 데이터 fetching
- **특징**: 한 페이지당 한 슬라이스 (유사한 페이지는 그룹화 가능)
- **의존성**: `widgets`, `features`, `entities`, `shared` 사용 가능
> 💡 **FSD v2.1 권장사항**: "pages-first" 접근 방식을 따라, 재사용되지 않는 큰 UI 블록과 비즈니스 로직은 페이지 슬라이스에 유지하세요.
### 3. Widgets
- **목적**: 큰 규모의 독립적인 UI 블록
- **내용**: 여러 features와 entities를 조합한 복합 UI
- **사용 시기**: 여러 페이지에서 재사용되거나, 페이지에 여러 개의 큰 독립적 블록이 있을 때
- **의존성**: `features`, `entities`, `shared` 사용 가능 (다른 `widgets` 불가)
### 4. Features
- **목적**: 사용자가 수행하는 주요 상호작용과 비즈니스 기능
- **내용**: 사용자 시나리오 (예: 로그인, 상품 검색, 댓글 작성)
- **사용 시기**: 여러 페이지에서 재사용되는 기능
- **의존성**: `entities`, `shared` 사용 가능 (다른 `features` 불가)
### 5. Entities
- **목적**: 비즈니스가 다루는 실제 개념 (User, Product, Order 등)
- **내용**: 데이터 모델, 타입, API 요청, 엔티티의 시각적 표현
- **특징**: 비즈니스 용어로 명명
- **의존성**: 다른 `entities`, `shared` 사용 가능
### 6. Shared
- **목적**: 애플리케이션의 기반 제공
- **내용**: API 클라이언트, UI Kit, 유틸리티 라이브러리, 글로벌 설정
- **특징**: 비즈니스 로직 없음, 슬라이스가 없고 세그먼트로만 구성
- **의존성**: 외부 라이브러리만 사용 가능 (다른 레이어 불가)
## 레이어 간 Import 규칙
> **핵심 규칙**: 슬라이스 내의 모듈(파일)은 **오직 하위 레이어**에 있는 다른 슬라이스만 import할 수 있습니다.
예시:
- `features/auth-login/ui/form.tsx`는 `entities/user`와 `shared/ui`를 import 가능
- 하지만 다른 `features/post-create`나 상위 레이어인 `widgets`는 import 불가
- 같은 슬라이스 내부(`features/auth-login/`)의 다른 파일들은 자유롭게 import 가능
## Public API 규칙
> **슬라이스 외부의 모듈은 슬라이스의 Public API만 참조할 수 있으며, 내부 파일 구조에 직접 접근할 수 없습니다.**
모든 슬라이스(및 슬라이스가 없는 레이어의 세그먼트)는 반드시 `index.ts`를 통해 Public API를 정의해야 합니다.
```typescript
// ✅ 올바른 import
import { LoginForm } from 'features/auth-login';
// ❌ 잘못된 import (내부 구조 직접 접근)
import { LoginForm } from 'features/auth-login/ui/login-form';
```
## 시작하기
@@ -80,6 +165,69 @@ npm start
NEXT_PUBLIC_API_URL=http://localhost:3000/api
```
## FSD 핵심 규칙
### 1. Import 규칙
> **슬라이스 내의 모듈(파일)은 오직 하위 레이어에 있는 슬라이스만 import할 수 있습니다.**
```typescript
// ✅ 올바른 import (하위 레이어)
// features/auth-login/ui/form.tsx
import { User } from 'entities/user';
import { Button } from 'shared/ui/button';
// ❌ 잘못된 import (같은 레이어)
// features/auth-login/ui/form.tsx
import { PostForm } from 'features/post-create'; // 금지!
// ❌ 잘못된 import (상위 레이어)
// features/auth-login/ui/form.tsx
import { Header } from 'widgets/header'; // 금지!
```
### 2. Public API 규칙
> **슬라이스 외부에서는 Public API(index.ts)를 통해서만 접근해야 합니다.**
```typescript
// ✅ 올바른 import (Public API 사용)
import { LoginForm } from 'features/auth-login';
// ❌ 잘못된 import (내부 구조 직접 접근)
import { LoginForm } from 'features/auth-login/ui/login-form';
```
**Public API 작성 시 주의사항**:
- 와일드카드 re-export(`export * from`) 사용 지양
- 필요한 것만 명시적으로 export
- 슬라이스의 인터페이스를 명확하게 표현
```typescript
// ❌ 나쁜 예시
export * from './ui/Comment';
export * from './model/comments';
// ✅ 좋은 예시
export { Comment } from './ui/comment';
export { CommentForm } from './ui/comment-form';
export { useComments } from './model/use-comments';
export type { Comment, CommentFormData } from './model/types';
```
### 3. 슬라이스 독립성
- **Zero Coupling**: 같은 레이어의 슬라이스들은 서로 독립적이어야 합니다
- **High Cohesion**: 슬라이스는 주요 목표와 관련된 대부분의 코드를 포함해야 합니다
- 예외: Entities 레이어에서 필요한 경우 `@x` 표기법으로 cross-import 가능
### 4. 세그먼트 명명 규칙
세그먼트 이름은 **목적**을 설명해야 하며, **본질**을 설명하면 안 됩니다:
- ❌ **나쁜 이름**: `components`, `hooks`, `types` (무엇인지만 설명)
- ✅ **좋은 이름**: `ui`, `api`, `model`, `lib` (왜 있는지 설명)
## 코드 규칙
- TypeScript 사용 (strict mode)
@@ -87,3 +235,14 @@ NEXT_PUBLIC_API_URL=http://localhost:3000/api
- Named exports 선호
- Tailwind CSS 사용
- ESLint + Prettier 적용
- Public API는 명시적으로 정의 (와일드카드 export 지양)
## 아키텍처 린팅
코드베이스의 FSD 규칙 준수를 자동으로 검증하려면 [Steiger](https://github.com/feature-sliced/steiger)를 사용하세요.
```bash
# Steiger 설치 및 실행
npm install -D @feature-sliced/steiger
npx steiger src
```
+169
View File
@@ -0,0 +1,169 @@
# App Layer
**App**은 애플리케이션 전체에 영향을 미치는 기술적, 비즈니스적 사항을 다루는 최상위 레이어입니다.
## 목적
- 애플리케이션의 진입점(entrypoint) 제공
- 전역 Context Providers 설정
- 라우터 구성
- 글로벌 스타일 정의
- 전역 상태 저장소 설정
- 애널리틱스 및 모니터링 설정
## 특징
- **슬라이스 없음**: App 레이어는 Shared처럼 슬라이스가 없고 세그먼트로만 구성됩니다
- **전체 앱 관심사**: 특정 비즈니스 도메인이 아닌 앱 전체와 관련된 코드만 포함
- **최상위 레이어**: 모든 하위 레이어의 모듈을 자유롭게 import 가능
## 구조 (Next.js App Router)
Next.js를 사용하는 경우, App 레이어는 주로 `app/` 디렉토리로 표현됩니다:
```
app/
├── (routes)/ # 라우트 그룹 및 페이지
│ ├── (auth)/
│ │ ├── login/
│ │ │ └── page.tsx
│ │ └── register/
│ │ └── page.tsx
│ └── (main)/
│ ├── dashboard/
│ │ └── page.tsx
│ └── settings/
│ └── page.tsx
├── layout.tsx # 루트 레이아웃
├── page.tsx # 홈 페이지
├── globals.css # 글로벌 스타일
├── providers.tsx # 전역 Providers 설정
└── error.tsx # 글로벌 에러 핸들러
```
### 일반적인 FSD 세그먼트 구조
FSD 표준 세그먼트를 사용하는 경우:
```
app/
├── entrypoint/ # 애플리케이션 진입점 (프레임워크별)
│ └── index.tsx
├── providers/ # Context Providers
│ ├── query-provider.tsx
│ ├── theme-provider.tsx
│ └── index.tsx
├── styles/ # 글로벌 스타일
│ ├── globals.css
│ └── theme.css
├── store/ # 글로벌 상태 저장소 설정
│ └── index.ts
└── routes/ # 라우터 설정
└── index.tsx
```
## 예시
### Next.js Providers 설정
```typescript
// app/providers.tsx
'use client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ThemeProvider } from 'next-themes';
import { useState } from 'react';
export function Providers({ children }: { children: React.ReactNode }) {
const [queryClient] = useState(() => new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000,
},
},
}));
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
</QueryClientProvider>
);
}
// app/layout.tsx
import { Providers } from './providers';
import './globals.css';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ko">
<body>
<Providers>
{children}
</Providers>
</body>
</html>
);
}
```
### 글로벌 설정
```typescript
// app/config/analytics.ts
export function initAnalytics() {
if (typeof window !== 'undefined') {
// 애널리틱스 초기화
}
}
// app/config/monitoring.ts
export function initMonitoring() {
// 에러 모니터링 설정
}
```
## Next.js App Router와 FSD
Next.js의 `app/` 디렉토리는 FSD의 **App 레이어**와 **Pages 레이어**를 동시에 담당합니다:
- **루트 레벨 파일들** (`layout.tsx`, `providers.tsx`, `globals.css`): App 레이어
- **라우트 폴더들** (`dashboard/`, `login/` 등): Pages 레이어
각 페이지별 비즈니스 로직은:
- 재사용되지 않는 UI는 페이지 슬라이스(`app/dashboard/` 등) 안에 유지
- 재사용되는 기능은 `features/` 레이어로 분리
- 여러 페이지에서 재사용되는 큰 UI 블록은 `widgets/` 레이어로 분리
## 레이어 의존성 규칙
✅ **허용되는 의존성**:
- 모든 하위 레이어 (`pages`, `widgets`, `features`, `entities`, `shared`)
- 같은 `app` 레이어 내의 다른 세그먼트
- 외부 라이브러리
❌ **금지된 의존성**:
- 없음 (App은 최상위 레이어)
## 주의사항
1. **비대화 방지**: App 레이어가 너무 커지면 관리가 어려워집니다. 대부분의 로직은 하위 레이어에 배치하세요
2. **전역 관심사만**: 특정 페이지나 기능에만 관련된 코드는 해당 레이어로 이동
3. **라우터 레벨 로직**: 라우터 및 서버 레벨 로직은 이 레이어에 유지
4. **Processes 레이어 사용 지양**: Processes 레이어는 deprecated되었으므로 해당 로직은 `app`이나 `features`에 배치
## FSD v2.1 권장사항
최신 FSD 버전(v2.1)은 **"pages-first"** 접근 방식을 권장합니다:
- 더 많은 코드를 페이지 슬라이스에 유지
- 큰 UI 블록과 재사용되지 않는 비즈니스 로직은 즉시 추출하지 말고 페이지에 보관
- 실제로 재사용이 필요할 때만 `features`나 `widgets`로 분리
이 접근 방식은 과도한 추상화를 방지하고 코드를 더 쉽게 탐색할 수 있게 합니다.
+86 -15
View File
@@ -1,43 +1,114 @@
# Entities Layer
비즈니스 엔티티를 정의하는 레이어입니다.
**Entities**는 프로젝트가 다루는 실제 비즈니스 개념을 나타내는 레이어입니다. 비즈니스에서 제품을 설명할 때 사용하는 용어들(예: User, Product, Order)이 주로 엔티티가 됩니다.
## 목적
- 비즈니스 엔티티의 데이터 모델 및 타입 정의
- 엔티티 관련 API 요청 함수 관리
- 엔티티의 시각적 표현 제공 (재사용 가능한 UI)
- 여러 페이지에서 동일한 외관을 재사용할 수 있도록 지원
## 구조
각 엔티티는 다음 구조를 따릅니다:
각 엔티티 슬라이스는 다음 세그먼트로 구성됩니다:
```
entities/
└── [entity-name]/
├── api/ # API 호출 함수
├── model/ # 상태 관리 (zustand)
├── types/ # 타입 정의
├── ui/ # UI 컴포넌트 (선택적)
├── model/ # 데이터 저장소, 검증 스키마, 상태 관리
├── api/ # 엔티티 관련 API 요청 함수
├── ui/ # 엔티티 시각적 표현 (선택적)
├── lib/ # 엔티티 관련 유틸리티 (선택적)
├── @x/ # 다른 엔티티로부터의 cross-import용 Public API (선택적)
└── index.ts # Public API
```
### 세그먼트 설명
- **model**: 데이터 모델, 타입 정의, 상태 저장소 (Zustand 등)
- **api**: 백엔드 API 호출 함수
- **ui**: 엔티티를 표시하는 UI 컴포넌트 (완전한 UI 블록이 아니라 재사용 가능한 표현)
- **lib**: 엔티티 관련 유틸리티 함수
- **@x**: 다른 엔티티가 이 엔티티를 import할 때 사용하는 명시적 cross-import API
- **index.ts**: 슬라이스의 Public API (외부에서 사용할 수 있는 것만 export)
## 예시
```typescript
// entities/user/types/index.ts
// entities/user/model/user.ts
export interface User {
id: string;
name: string;
email: string;
role: 'admin' | 'user';
}
// entities/user/api/index.ts
// entities/user/api/get-user.ts
import type { User } from '../model/user';
export async function getUser(id: string): Promise<User> {
// API 호출
const response = await fetch(`/api/users/${id}`);
return response.json();
}
// entities/user/ui/user-card.tsx
import type { User } from '../model/user';
interface UserCardProps {
user: User;
onClick?: () => void;
}
export function UserCard({ user, onClick }: UserCardProps) {
return (
<div onClick={onClick}>
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
);
}
// entities/user/index.ts
export { type User } from "./types";
export { getUser } from "./api";
export { type User } from './model/user';
export { getUser } from './api/get-user';
export { UserCard } from './ui/user-card';
```
## 규칙
## 엔티티 간 관계
1. 엔티티는 다른 엔티티에 의존할 수 있습니다
2. Features나 Widgets에 의존하면 안 됩니다
3. 비즈니스 로직은 최소화하고 데이터 관리에 집중합니다
엔티티가 서로 연결되어 있을 때는 `@x` 표기법을 사용하여 명시적으로 cross-import를 관리하는 것이 권장됩니다:
```typescript
// entities/artist/model/artist.ts
import type { Song } from 'entities/song/@x/artist';
export interface Artist {
name: string;
songs: Array<Song>;
}
// entities/song/@x/artist.ts
export type { Song } from '../model/song';
```
> `@x` 폴더를 사용하면 엔티티 간 연결을 명확하게 만들어 함께 리팩터링이 필요한 코드를 쉽게 찾을 수 있습니다.
## 레이어 의존성 규칙
✅ **허용되는 의존성**:
- `shared` 레이어의 모듈
- 같은 엔티티 슬라이스 내의 다른 세그먼트
- 다른 엔티티 슬라이스 (필요한 경우, `@x` 표기법 권장)
❌ **금지된 의존성**:
- `features` 레이어
- `widgets` 레이어
- `pages` 레이어
- `app` 레이어
## 주의사항
1. **UI 컴포넌트는 완전한 비즈니스 로직을 포함하지 않음**: UI는 주로 props나 slots를 통해 다양한 비즈니스 로직을 연결할 수 있도록 설계
2. **엔티티 간 비즈니스 로직은 상위 레이어에**: 엔티티 간 상호작용의 비즈니스 로직은 Features나 Pages 레이어에서 처리
3. **데이터 관리에 집중**: 복잡한 비즈니스 로직보다는 데이터 모델, 검증, 저장에 집중
+23
View File
@@ -0,0 +1,23 @@
export { instlSncnService } from "./instl-sncn-service-impl";
export {
instlSncnKeys,
useListPageLoadCnfm,
useRegistPageLoadCnfm,
useViewPageLoadCnfm,
useSelectInstlCnfmListCnt,
useSelectInstlCnfmList,
useSelectInstlCnfmDtl,
useInsertInstlCnfm,
useMergeInstlCnfm,
useDeleteInstlCnfm,
useUpdatePrgrsSttusCnfm,
useSaveInstlCnfmPrgrsStts,
useSaveInstlCnfmSanctnPrgrsStts,
useInsertInstlCnfmSpl,
useSelectEssntlInstlCnfmAtchFileList,
useSelectInstlCnfmExmntFile,
useSelectInstlCnfmEtcFile,
useSelectInstlCnfmSpl,
useSelectInstlCnfmExmntResult,
useSelectInstlCnfmOpinionList,
} from "./queries";
@@ -0,0 +1,222 @@
import { apiClient } from "@/shared/api";
import type {
InstlSncnService,
FnrscVO,
ListPageResult,
RegistPageData,
ViewPageData,
SplmntRqst,
} from "../model";
class InstlSncnServiceImpl implements InstlSncnService {
async selectInstlCnfmListCount(vo: FnrscVO): Promise<number> {
const response = await apiClient.get<{ count: number }>(
"/fnrsc/cnfm/list/count",
{ params: vo }
);
return response.data.count;
}
async selectInstlCnfmList(vo: FnrscVO): Promise<FnrscVO[]> {
const response = await apiClient.get<FnrscVO[]>("/fnrsc/cnfm/list", {
params: vo,
});
return response.data;
}
async listPageLoadCnfm(vo: FnrscVO): Promise<ListPageResult> {
const response = await apiClient.get<ListPageResult>(
"/fnrsc/cnfm/list/pageLoad.do",
{
params: {
...vo,
pageIndex: vo.pageIndex || 1,
recordCountPerPage: vo.recordCountPerPage || 10,
pageSize: vo.pageSize || 10,
},
}
);
return response.data;
}
async registPageLoadCnfm(vo: FnrscVO): Promise<RegistPageData> {
const response = await apiClient.get<RegistPageData>(
"/fnrsc/cnfm/regist/pageLoad.do",
{
params: vo,
}
);
return response.data;
}
async insertInstlCnfm(vo: FnrscVO, files?: File[]): Promise<void> {
const formData = new FormData();
Object.entries(vo).forEach(([key, value]) => {
if (value !== undefined && value !== null) {
if (typeof value === "object") {
formData.append(key, JSON.stringify(value));
} else {
formData.append(key, String(value));
}
}
});
if (files && files.length > 0) {
files.forEach((file) => {
formData.append("uploadFile", file);
});
}
await apiClient.post("/fnrsc/cnfm/regist/insertFnrscCnfm.do", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
}
async mergeInstlCnfm(vo: FnrscVO, files?: File[]): Promise<void> {
const formData = new FormData();
Object.entries(vo).forEach(([key, value]) => {
if (value !== undefined && value !== null) {
if (typeof value === "object") {
formData.append(key, JSON.stringify(value));
} else {
formData.append(key, String(value));
}
}
});
if (files && files.length > 0) {
files.forEach((file) => {
formData.append("uploadFile", file);
});
}
await apiClient.post("/fnrsc/cnfm/regist/mergeFnrscCnfm.do", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
}
async selectInstlCnfmDetail(vo: FnrscVO): Promise<FnrscVO> {
const response = await apiClient.get<FnrscVO>("/fnrsc/cnfm/detail", {
params: vo,
});
return response.data;
}
async viewPageLoadCnfm(vo: FnrscVO): Promise<ViewPageData> {
const response = await apiClient.get<ViewPageData>(
"/fnrsc/cnfm/view/pageLoad.do",
{
params: vo,
}
);
return response.data;
}
async updateProgrsSttusCnfm(vo: FnrscVO): Promise<void> {
await apiClient.post("/fnrsc/cnfm/update/updateProgrsSttus.do", vo);
}
async saveInstlCnfmProgrsSttus(vo: FnrscVO, file?: File): Promise<void> {
const formData = new FormData();
Object.entries(vo).forEach(([key, value]) => {
if (value !== undefined && value !== null) {
formData.append(key, String(value));
}
});
if (file) {
formData.append("uploadFile", file);
}
await apiClient.post(
"/fnrsc/cnfm/update/saveProgrsSttus.do",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
},
}
);
}
async saveInstlCnfmSanctnProgrsSttus(vo: FnrscVO): Promise<void> {
await apiClient.post(
"/fnrsc/cnfm/update/saveInstlCnfmSanctnProgrsSttus.do",
vo
);
}
async deleteInstlCnfm(vo: FnrscVO): Promise<void> {
await apiClient.post("/fnrsc/cnfm/regist/deleteInstlCnfm.do", vo);
}
async selectEssntlInstlCnfmAtchFileList(vo: FnrscVO): Promise<FnrscVO[]> {
const response = await apiClient.get<FnrscVO[]>(
"/fnrsc/cnfm/files/essential",
{ params: vo }
);
return response.data;
}
async selectInstlCnfmExmntFile(vo: FnrscVO): Promise<FnrscVO[]> {
const response = await apiClient.get<FnrscVO[]>(
"/fnrsc/cnfm/files/examination",
{ params: vo }
);
return response.data;
}
async selectInstlCnfmEtcFile(vo: FnrscVO): Promise<FnrscVO[]> {
const response = await apiClient.get<FnrscVO[]>("/fnrsc/cnfm/files/etc", {
params: vo,
});
return response.data;
}
async selectInstlCnfmSanctnManage(
vo: FnrscVO
): Promise<Record<string, unknown>> {
const response = await apiClient.get<Record<string, unknown>>(
"/fnrsc/cnfm/sanction/manage",
{ params: vo }
);
return response.data;
}
async insertInstlCnfmSpl(vo: FnrscVO): Promise<void> {
await apiClient.post("/fnrsc/cnfm/update/insertInstlCnfmSpl.do", vo);
}
async selectInstlCnfmSpl(vo: FnrscVO): Promise<SplmntRqst | null> {
const response = await apiClient.get<SplmntRqst | null>(
"/fnrsc/cnfm/supplement",
{ params: vo }
);
return response.data;
}
async selectInstlCnfmExmntResult(vo: FnrscVO): Promise<FnrscVO[]> {
const response = await apiClient.get<FnrscVO[]>(
"/fnrsc/cnfm/examination/result",
{ params: vo }
);
return response.data;
}
async selectInstlCnfmOpinionList(vo: FnrscVO): Promise<FnrscVO[]> {
const response = await apiClient.get<FnrscVO[]>(
"/fnrsc/cnfm/opinion/list",
{ params: vo }
);
return response.data;
}
}
export const instlSncnService = new InstlSncnServiceImpl();
+312
View File
@@ -0,0 +1,312 @@
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { instlSncnService } from "./instl-sncn-service-impl";
import type { FnrscVO } from "../model";
export const instlSncnKeys = {
all: ["instl-sncn"] as const,
lists: () => [...instlSncnKeys.all, "list"] as const,
list: (vo: FnrscVO) => [...instlSncnKeys.lists(), vo] as const,
dtls: () => [...instlSncnKeys.all, "dtl"] as const,
dtl: (instlCnfmDocNo: string) =>
[...instlSncnKeys.dtls(), instlCnfmDocNo] as const,
registPage: (jobSeSp: string) =>
[...instlSncnKeys.all, "regist-page", jobSeSp] as const,
viewPage: (instlCnfmDocNo: string) =>
[...instlSncnKeys.all, "view-page", instlCnfmDocNo] as const,
};
/**
* 설치인가 목록 페이지 로드 (카운트 + 목록 + 페이지네이션)
*/
export function useListPageLoadCnfm(vo: FnrscVO) {
return useQuery({
queryKey: instlSncnKeys.list(vo),
queryFn: () => instlSncnService.listPageLoadCnfm(vo),
});
}
/**
* 설치인가 등록 페이지 로드 (체크리스트 + 필수첨부파일)
*/
export function useRegistPageLoadCnfm(vo: FnrscVO) {
return useQuery({
queryKey: instlSncnKeys.registPage(vo.jobSeSp || ""),
queryFn: () => instlSncnService.registPageLoadCnfm(vo),
enabled: !!vo.jobSeSp,
});
}
/**
* 설치인가 상세/수정 페이지 로드
*/
export function useViewPageLoadCnfm(vo: FnrscVO) {
return useQuery({
queryKey: instlSncnKeys.viewPage(vo.instlCnfmDocNo || ""),
queryFn: () => instlSncnService.viewPageLoadCnfm(vo),
enabled: !!vo.instlCnfmDocNo,
});
}
/**
* 설치인가 목록 카운트 조회
*/
export function useSelectInstlCnfmListCnt(vo: FnrscVO) {
return useQuery({
queryKey: [...instlSncnKeys.lists(), "count", vo],
queryFn: () => instlSncnService.selectInstlCnfmListCount(vo),
});
}
/**
* 설치인가 목록 조회
*/
export function useSelectInstlCnfmList(vo: FnrscVO) {
return useQuery({
queryKey: instlSncnKeys.list(vo),
queryFn: () => instlSncnService.selectInstlCnfmList(vo),
});
}
/**
* 설치인가 상세 조회
*/
export function useSelectInstlCnfmDtl(vo: FnrscVO) {
return useQuery({
queryKey: instlSncnKeys.dtl(vo.instlCnfmDocNo || ""),
queryFn: () => instlSncnService.selectInstlCnfmDetail(vo),
enabled: !!vo.instlCnfmDocNo,
});
}
/**
* 설치인가 신규 등록
*/
export function useInsertInstlCnfm() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ vo, files }: { vo: FnrscVO; files?: File[] }) =>
instlSncnService.insertInstlCnfm(vo, files),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.lists(),
});
},
});
}
/**
* 설치인가 수정 (병합)
*/
export function useMergeInstlCnfm() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ vo, files }: { vo: FnrscVO; files?: File[] }) =>
instlSncnService.mergeInstlCnfm(vo, files),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.lists(),
});
if (variables.vo.instlCnfmDocNo) {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.dtl(variables.vo.instlCnfmDocNo),
});
queryClient.invalidateQueries({
queryKey: instlSncnKeys.viewPage(variables.vo.instlCnfmDocNo),
});
}
},
});
}
/**
* 설치인가 삭제
*/
export function useDeleteInstlCnfm() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (vo: FnrscVO) => instlSncnService.deleteInstlCnfm(vo),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.lists(),
});
},
});
}
/**
* 설치인가 진행상태 업데이트
*/
export function useUpdatePrgrsSttusCnfm() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (vo: FnrscVO) =>
instlSncnService.updateProgrsSttusCnfm(vo),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.lists(),
});
if (variables.instlCnfmDocNo) {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.dtl(variables.instlCnfmDocNo),
});
queryClient.invalidateQueries({
queryKey: instlSncnKeys.viewPage(variables.instlCnfmDocNo),
});
}
},
});
}
/**
* 설치인가 진행상태 저장 (검토의견 + 파일)
*/
export function useSaveInstlCnfmPrgrsStts() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ vo, file }: { vo: FnrscVO; file?: File }) =>
instlSncnService.saveInstlCnfmProgrsSttus(vo, file),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.lists(),
});
if (variables.vo.instlCnfmDocNo) {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.dtl(variables.vo.instlCnfmDocNo),
});
queryClient.invalidateQueries({
queryKey: instlSncnKeys.viewPage(variables.vo.instlCnfmDocNo),
});
}
},
});
}
/**
* 설치인가 기술검토 최종결재
*/
export function useSaveInstlCnfmSanctnPrgrsStts() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (vo: FnrscVO) =>
instlSncnService.saveInstlCnfmSanctnProgrsSttus(vo),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.lists(),
});
if (variables.instlCnfmDocNo) {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.dtl(variables.instlCnfmDocNo),
});
queryClient.invalidateQueries({
queryKey: instlSncnKeys.viewPage(variables.instlCnfmDocNo),
});
}
},
});
}
/**
* 설치인가 보완요청 등록
*/
export function useInsertInstlCnfmSpl() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (vo: FnrscVO) => instlSncnService.insertInstlCnfmSpl(vo),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.lists(),
});
if (variables.instlCnfmDocNo) {
queryClient.invalidateQueries({
queryKey: instlSncnKeys.dtl(variables.instlCnfmDocNo),
});
queryClient.invalidateQueries({
queryKey: instlSncnKeys.viewPage(variables.instlCnfmDocNo),
});
}
},
});
}
/**
* 설치인가 필수 첨부파일 목록 조회
*/
export function useSelectEssntlInstlCnfmAtchFileList(vo: FnrscVO) {
return useQuery({
queryKey: [...instlSncnKeys.all, "essential-files", vo.instlCnfmDocNo],
queryFn: () => instlSncnService.selectEssntlInstlCnfmAtchFileList(vo),
enabled: !!vo.instlCnfmDocNo,
});
}
/**
* 설치인가 검토의견 첨부파일 조회
*/
export function useSelectInstlCnfmExmntFile(vo: FnrscVO) {
return useQuery({
queryKey: [
...instlSncnKeys.all,
"exmnt-files",
vo.instlCnfmDocNo,
vo.exmntOpinionSeqNo,
],
queryFn: () => instlSncnService.selectInstlCnfmExmntFile(vo),
enabled: !!vo.instlCnfmDocNo && !!vo.exmntOpinionSeqNo,
});
}
/**
* 설치인가 기타 첨부파일 조회
*/
export function useSelectInstlCnfmEtcFile(vo: FnrscVO) {
return useQuery({
queryKey: [...instlSncnKeys.all, "etc-files", vo.instlCnfmDocNo],
queryFn: () => instlSncnService.selectInstlCnfmEtcFile(vo),
enabled: !!vo.instlCnfmDocNo,
});
}
/**
* 설치인가 보완요청 조회
*/
export function useSelectInstlCnfmSpl(vo: FnrscVO) {
return useQuery({
queryKey: [...instlSncnKeys.all, "supplement", vo.instlCnfmDocNo],
queryFn: () => instlSncnService.selectInstlCnfmSpl(vo),
enabled: !!vo.instlCnfmDocNo,
});
}
/**
* 설치인가 검토결과 조회
*/
export function useSelectInstlCnfmExmntResult(vo: FnrscVO) {
return useQuery({
queryKey: [
...instlSncnKeys.all,
"exmnt-result",
vo.instlCnfmDocNo,
vo.jobSe,
],
queryFn: () => instlSncnService.selectInstlCnfmExmntResult(vo),
enabled: !!vo.instlCnfmDocNo && !!vo.jobSe,
});
}
/**
* 설치인가 담당자 목록 조회
*/
export function useSelectInstlCnfmOpinionList(vo: FnrscVO) {
return useQuery({
queryKey: [...instlSncnKeys.all, "opinion-list", vo.instlCnfmDocNo],
queryFn: () => instlSncnService.selectInstlCnfmOpinionList(vo),
enabled: !!vo.instlCnfmDocNo,
});
}
+61
View File
@@ -0,0 +1,61 @@
export type {
PrgrsStts,
FnrscVO,
JobSeItem,
CeckVO,
AtchFile,
ExmntOpinion,
SplmntRqst,
ListPageResult,
RegistPageData,
ViewPageData,
InstlSncnService,
} from "./model";
export {
PRGRS_STTS_LABELS,
PRGRS_STTS_OPTIONS,
JOB_TYPE_CODE,
DEFAULT_PAGE_SIZE,
DEFAULT_RECORD_COUNT_PER_PAGE,
} from "./model";
export {
instlSncnService,
instlSncnKeys,
useListPageLoadCnfm,
useRegistPageLoadCnfm,
useViewPageLoadCnfm,
useSelectInstlCnfmListCnt,
useSelectInstlCnfmList,
useSelectInstlCnfmDtl,
useInsertInstlCnfm,
useMergeInstlCnfm,
useDeleteInstlCnfm,
useUpdatePrgrsSttusCnfm,
useSaveInstlCnfmPrgrsStts,
useSaveInstlCnfmSanctnPrgrsStts,
useInsertInstlCnfmSpl,
useSelectEssntlInstlCnfmAtchFileList,
useSelectInstlCnfmExmntFile,
useSelectInstlCnfmEtcFile,
useSelectInstlCnfmSpl,
useSelectInstlCnfmExmntResult,
useSelectInstlCnfmOpinionList,
} from "./api";
export {
fmtPrgrsStts,
fmtJobSeComma,
jobSeSpSummary,
parseJobSeSpArr,
fmtFileSize,
fmtDt,
vldtInstlSncnForm,
canAply,
canDel,
canMdfy,
canRqstSplmnt,
canAprv,
type VldtnErr,
} from "./lib";
+47
View File
@@ -0,0 +1,47 @@
import { PRGRS_STTS_LABELS, type PrgrsStts } from "../model";
export function fmtPrgrsStts(stts: PrgrsStts): string {
return PRGRS_STTS_LABELS[stts] || stts;
}
export function fmtJobSeComma(jobSe: string): string {
if (!jobSe) return "";
return jobSe.split("").join(",");
}
export function jobSeSpSummary(jobSeSp: string): string {
if (!jobSeSp) return "";
return jobSeSp.replace(/,/g, "");
}
export function parseJobSeSpArr(jobSeSp: string): string[] {
if (!jobSeSp) return [];
return jobSeSp.split(",").filter(Boolean);
}
export function fmtFileSize(bytes: number): string {
if (bytes === 0) return "0 Bytes";
const k = 1024;
const sizes = ["Bytes", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + " " + sizes[i];
}
export function fmtDt(dtString: string | undefined): string {
if (!dtString) return "-";
try {
const dt = new Date(dtString);
return new Intl.DateTimeFormat("ko-KR", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
}).format(dt);
} catch {
return dtString;
}
}
+18
View File
@@ -0,0 +1,18 @@
export {
fmtPrgrsStts,
fmtJobSeComma,
jobSeSpSummary,
parseJobSeSpArr,
fmtFileSize,
fmtDt,
} from "./format";
export {
vldtInstlSncnForm,
canAply,
canDel,
canMdfy,
canRqstSplmnt,
canAprv,
type VldtnErr,
} from "./validation";
@@ -0,0 +1,73 @@
import type { FnrscVO } from "../model";
export interface VldtnErr {
field: string;
message: string;
}
export function vldtInstlSncnForm(data: FnrscVO): VldtnErr[] {
const errors: VldtnErr[] = [];
if (!data.jobSe) {
errors.push({
field: "jobSe",
message: "업무구분을 선택해주세요.",
});
}
if (!data.bplcNm || data.bplcNm.trim() === "") {
errors.push({
field: "bplcNm",
message: "사업장명을 입력해주세요.",
});
}
if (!data.fcltNm || data.fcltNm.trim() === "") {
errors.push({
field: "fcltNm",
message: "시설명을 입력해주세요.",
});
}
return errors;
}
export function canAply(data: FnrscVO): boolean {
const errors = vldtInstlSncnForm(data);
return errors.length === 0;
}
export function canDel(
prgrsStts: string | undefined,
regId: string | undefined,
currentUsrId: string
): boolean {
return prgrsStts === "SV" && regId === currentUsrId;
}
export function canMdfy(
prgrsStts: string | undefined,
regId: string | undefined,
currentUsrId: string
): boolean {
return (
(prgrsStts === "SV" || prgrsStts === "SL") && regId === currentUsrId
);
}
export function canRqstSplmnt(
prgrsStts: string | undefined,
usrRole: string
): boolean {
return (
(prgrsStts === "ER" || prgrsStts === "PR") &&
(usrRole === "REVIEWER" || usrRole === "APPROVER")
);
}
export function canAprv(
prgrsStts: string | undefined,
usrRole: string
): boolean {
return prgrsStts === "PE" && usrRole === "APPROVER";
}
@@ -0,0 +1,30 @@
import type { PrgrsStts } from "./types";
export const PRGRS_STTS_LABELS: Record<PrgrsStts, string> = {
SV: "저장",
ST: "신청",
SL: "보완요청",
ER: "기술검토중",
EE: "기술검토완료",
PR: "환경청검토중",
PE: "환경청검토완료",
AP: "승인",
RJ: "반려",
} as const;
export const PRGRS_STTS_OPTIONS = [
{ value: "SV", label: "저장" },
{ value: "ST", label: "신청" },
{ value: "SL", label: "보완요청" },
{ value: "ER", label: "기술검토중" },
{ value: "EE", label: "기술검토완료" },
{ value: "PR", label: "환경청검토중" },
{ value: "PE", label: "환경청검토완료" },
{ value: "AP", label: "승인" },
{ value: "RJ", label: "반려" },
] as const;
export const JOB_TYPE_CODE = "FNR01" as const;
export const DEFAULT_PAGE_SIZE = 10 as const;
export const DEFAULT_RECORD_COUNT_PER_PAGE = 10 as const;
@@ -0,0 +1,22 @@
export type {
PrgrsStts,
FnrscVO,
JobSeItem,
CeckVO,
AtchFile,
ExmntOpinion,
SplmntRqst,
ListPageResult,
RegistPageData,
ViewPageData,
} from "./types";
export {
PRGRS_STTS_LABELS,
PRGRS_STTS_OPTIONS,
JOB_TYPE_CODE,
DEFAULT_PAGE_SIZE,
DEFAULT_RECORD_COUNT_PER_PAGE,
} from "./constants";
export type { InstlSncnService } from "./instl-sncn-service";
@@ -0,0 +1,151 @@
import type {
FnrscVO,
CeckVO,
AtchFile,
SplmntRqst,
ListPageResult,
RegistPageData,
ViewPageData,
} from "./types";
/**
* 설치인가 서비스 인터페이스
* Java CnfmService.java의 TypeScript 버전
*/
export interface InstlSncnService {
/**
* 설치인가 목록 카운트 조회
* @param vo 검색 조건
* @returns 목록 개수
*/
selectInstlCnfmListCount(vo: FnrscVO): Promise<number>;
/**
* 설치인가 목록 조회
* @param vo 검색 조건
* @returns 설치인가 목록
*/
selectInstlCnfmList(vo: FnrscVO): Promise<FnrscVO[]>;
/**
* 설치인가 목록 페이지 로드 (카운트 + 목록 + 페이지네이션)
* @param vo 검색 조건
* @returns 목록 페이지 데이터
*/
listPageLoadCnfm(vo: FnrscVO): Promise<ListPageResult>;
/**
* 설치인가 등록 페이지 로드 (체크리스트 + 필수첨부파일)
* @param vo jobSeSp 포함
* @returns 등록 페이지 데이터
*/
registPageLoadCnfm(vo: FnrscVO): Promise<RegistPageData>;
/**
* 설치인가 데이터 저장 (신규)
* @param vo 설치인가 VO
* @param files 첨부파일 목록
*/
insertInstlCnfm(vo: FnrscVO, files?: File[]): Promise<void>;
/**
* 설치인가 데이터 병합 (수정)
* @param vo 설치인가 VO
* @param files 첨부파일 목록
*/
mergeInstlCnfm(vo: FnrscVO, files?: File[]): Promise<void>;
/**
* 설치인가 상세 데이터 조회
* @param vo instlCnfmDocNo 포함
* @returns 설치인가 상세 정보
*/
selectInstlCnfmDetail(vo: FnrscVO): Promise<FnrscVO>;
/**
* 설치인가 상세/수정 페이지 로드
* @param vo instlCnfmDocNo 포함
* @returns 상세 페이지 데이터
*/
viewPageLoadCnfm(vo: FnrscVO): Promise<ViewPageData>;
/**
* 설치인가 진행상태 업데이트
* @param vo instlCnfmDocNo, progrsSttus 포함
*/
updateProgrsSttusCnfm(vo: FnrscVO): Promise<void>;
/**
* 설치인가 진행상태 저장 (검토의견 + 파일)
* @param vo instlCnfmDocNo, progrsSttus, exmntOpinionCn 포함
* @param file 첨부파일
*/
saveInstlCnfmProgrsSttus(vo: FnrscVO, file?: File): Promise<void>;
/**
* 설치인가 기술검토 최종결재
* @param vo instlCnfmDocNo, progrsSttus 포함
*/
saveInstlCnfmSanctnProgrsSttus(vo: FnrscVO): Promise<void>;
/**
* 설치인가 삭제
* @param vo instlCnfmDocNo 포함
*/
deleteInstlCnfm(vo: FnrscVO): Promise<void>;
/**
* 설치인가 신청 첨부파일 목록
* @param vo instlCnfmDocNo 포함
* @returns 필수 첨부파일 목록
*/
selectEssntlInstlCnfmAtchFileList(vo: FnrscVO): Promise<FnrscVO[]>;
/**
* 설치인가 의견 첨부파일
* @param vo instlCnfmDocNo, exmntOpinionSeqNo 포함
* @returns 검토의견 첨부파일 목록
*/
selectInstlCnfmExmntFile(vo: FnrscVO): Promise<FnrscVO[]>;
/**
* 설치인가 기타 첨부파일
* @param vo instlCnfmDocNo 포함
* @returns 기타 첨부파일 목록
*/
selectInstlCnfmEtcFile(vo: FnrscVO): Promise<FnrscVO[]>;
/**
* 설치인가 결재권자 조회
* @param vo instlCnfmDocNo, regId 포함
* @returns 결재권자 정보
*/
selectInstlCnfmSanctnManage(vo: FnrscVO): Promise<Record<string, unknown>>;
/**
* 설치인가 보완요청 등록
* @param vo instlCnfmDocNo, splCn 포함
*/
insertInstlCnfmSpl(vo: FnrscVO): Promise<void>;
/**
* 설치인가 보완요청 조회
* @param vo instlCnfmDocNo 포함
* @returns 보완요청 정보
*/
selectInstlCnfmSpl(vo: FnrscVO): Promise<SplmntRqst | null>;
/**
* 설치인가 검토결과 조회
* @param vo instlCnfmDocNo, jobSe 포함
* @returns 검토결과 목록
*/
selectInstlCnfmExmntResult(vo: FnrscVO): Promise<FnrscVO[]>;
/**
* 설치인가 담당자 정보 조회
* @param vo instlCnfmDocNo 포함
* @returns 담당자 목록
*/
selectInstlCnfmOpinionList(vo: FnrscVO): Promise<FnrscVO[]>;
}
+158
View File
@@ -0,0 +1,158 @@
export type PrgrsStts =
| "SV" // 저장
| "ST" // 신청
| "SL" // 보완요청
| "ER" // 기술검토
| "EE" // 기술검토완료
| "PR" // 환경청검토
| "PE" // 환경청검토완료
| "AP" // 승인
| "RJ"; // 반려
export interface FnrscVO {
fnrscDscssDocNo?: string;
instlCnfmDocNo?: string;
seqNo?: string;
yr?: string;
bzCd?: string;
bzNm?: string;
strtYr?: string;
edYr?: string;
dtlBzCd?: string;
untBzCd?: string;
rgnCd?: string;
rgnNm?: string;
rvbsnCd?: string;
adstDstrCd?: string;
adstDstrNm?: string;
bzSpec?: string;
aidRt?: string;
confBzCd?: string;
bzPd?: string;
bzCn?: string;
jobSe?: string;
jobSeSp?: string;
jobSeList?: Array<JobSeItem>;
jobSeNm?: string;
fcltyKnd?: string;
reusePrpos?: string;
progrsSttus?: PrgrsStts;
fileSeq?: number;
regId?: string;
regDt?: string;
udtId?: string;
udtDt?: string;
registMan?: string;
updtMan?: string;
registDe?: string;
updtDe?: string;
atchFileId?: string;
grpCd?: string;
bplcNm?: string;
fcltNm?: string;
lclgvrnmntNm?: string;
localCd?: string;
exmntOpinionSeqNo?: string;
exmntOpinionCn?: string;
scdExmntOpinionSeqNo?: string;
prmyExmntOpinionSeqNo?: string;
splCn?: string;
pageIndex?: number;
recordCountPerPage?: number;
pageSize?: number;
searchKeyword?: string;
searchCondition?: string;
}
export interface JobSeItem {
jobSeCd: string;
jobSeNm: string;
}
export interface CeckVO {
ceckSn: string;
ceckCn: string;
ceckResultAt?: "Y" | "N";
ceckResultCn?: string;
jobSe: string;
}
export interface AtchFile {
atchFileId: string;
fileSn: string;
fileStreCours: string;
streFileNm: string;
orignlFileNm: string;
fileExtsn: string;
fileMg: number;
fileType?: string;
essntlAt?: "Y" | "N";
}
export interface ExmntOpinion {
exmntOpinionSeqNo: string;
instlCnfmDocNo: string;
exmntOpinionCn: string;
exmntResultAt?: "Y" | "N";
atchFileList?: AtchFile[];
regId?: string;
regDt?: string;
}
export interface SplmntRqst {
splSeqNo: string;
instlCnfmDocNo: string;
splCn: string;
splDt?: string;
regId?: string;
regDt?: string;
}
export interface ListPageResult {
cnt: number;
list: FnrscVO[];
pageIndex: number;
lastPage: number;
paginationInfo: {
currentPageNo: number;
recordCountPerPage: number;
pageSize: number;
totalRecordCount: number;
lastPageNo: number;
};
searchVO: FnrscVO;
}
export interface RegistPageData {
ceckEssntlArr: Array<{
jobSeCd: string;
jobSeNm: string;
ceckForm1: CeckVO[];
essntlList: FnrscVO[];
}>;
jobSe: string;
jobSeSp: string;
grpCd: string;
adstDstrCd: string;
lclgvrnmntNm: string;
localCd: string;
}
export interface ViewPageData {
view: FnrscVO;
jobSeSp: string;
ceckEssntlArr: Array<{
jobSeCd: string;
jobSeNm: string;
ceckForm1: FnrscVO[];
essntlList: FnrscVO[];
}>;
prmyFileList: FnrscVO[];
scdFileList: FnrscVO[];
etcFileList: FnrscVO[];
grpCd: string;
usrId: string;
sanctnChk: Record<string, unknown>;
spl: SplmntRqst | null;
opinionList: FnrscVO[];
}
+107 -13
View File
@@ -1,36 +1,130 @@
# Features Layer
사용자 인터랙션과 비즈니스 기능을 구현하는 레이어입니다.
**Features**는 앱의 주요 사용자 상호작용과 기능을 구현하는 레이어입니다. 사용자가 실제로 수행하는 작업들로, 주로 비즈니스 엔티티와 관련이 있습니다.
## 목적
- 사용자가 중요하게 생각하는 주요 상호작용 구현
- 재사용 가능한 비즈니스 기능 제공
- 여러 페이지에서 사용되는 기능의 중복 제거
## Feature로 만들어야 하는 경우
> ⚠️ **중요**: 모든 것을 feature로 만들 필요는 없습니다.
Feature로 만드는 것이 좋은 지표:
- **여러 페이지에서 재사용됨**: 예를 들어, 여러 에디터가 있고 모두 댓글 기능이 있다면, 댓글은 재사용 가능한 feature입니다
- **중요한 비즈니스 기능**: 신규 프로젝트 참여자가 Features 폴더를 보고 앱의 주요 기능을 빠르게 파악할 수 있어야 합니다
Feature가 너무 많으면 중요한 기능이 묻히므로, 신규 참여자의 경험을 최적화하여 결정하세요.
## 구조
각 기능은 다음 구조를 따릅니다:
각 feature 슬라이스는 다음 세그먼트로 구성됩니다:
```
features/
└── [feature-name]/
├── api/ # API 호출 (선택적)
├── model/ # 상태 관리
├── ui/ # UI 컴포넌트
├── lib/ # 유틸리티 함수
├── ui/ # 상호작용을 수행하는 UI (폼, 버튼 등)
├── api/ # 액션 수행에 필요한 API 호출 (선택적)
├── model/ # 검증 및 내부 상태 관리 (선택적)
├── lib/ # 유틸리티 함수 (선택적)
├── config/ # feature flags (선택적)
└── index.ts # Public API
```
### 세그먼트 설명
- **ui**: 사용자 상호작용을 위한 UI 컴포넌트 (폼, 모달, 버튼 등)
- **api**: feature 실행에 필요한 API 요청 함수
- **model**: 폼 검증, 내부 상태, 비즈니스 로직
- **lib**: feature 내부에서만 사용되는 유틸리티
- **config**: feature flags, feature별 설정값
- **index.ts**: 슬라이스의 Public API (외부에서 사용할 수 있는 것만 export)
## 예시
```typescript
// features/auth-login/ui/login-form.tsx
import { useState } from 'react';
import { loginUser } from '../api/login-user';
import type { LoginCredentials } from '../model/types';
export function LoginForm() {
// 로그인 폼 UI
const [credentials, setCredentials] = useState<LoginCredentials>({
email: '',
password: ''
});
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
await loginUser(credentials);
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={credentials.email}
onChange={(e) => setCredentials({ ...credentials, email: e.target.value })}
/>
<input
type="password"
value={credentials.password}
onChange={(e) => setCredentials({ ...credentials, password: e.target.value })}
/>
<button type="submit">로그인</button>
</form>
);
}
// features/auth-login/api/login-user.ts
import type { LoginCredentials } from '../model/types';
export async function loginUser(credentials: LoginCredentials) {
const response = await fetch('/api/auth/login', {
method: 'POST',
body: JSON.stringify(credentials),
});
return response.json();
}
// features/auth-login/model/types.ts
export interface LoginCredentials {
email: string;
password: string;
}
// features/auth-login/index.ts
export { LoginForm } from "./ui/login-form";
export { LoginForm } from './ui/login-form';
export { loginUser } from './api/login-user';
export type { LoginCredentials } from './model/types';
```
## 규칙
## 레이어 의존성 규칙
1. 하나의 기능에만 집중합니다
2. Entities와 Shared에만 의존할 수 있습니다
3. 다른 Features에 직접 의존하면 안 됩니다
4. 재사용 가능한 기능으로 설계합니다
✅ **허용되는 의존성**:
- `shared` 레이어의 모듈
- `entities` 레이어의 모듈
- 같은 feature 슬라이스 내의 다른 세그먼트
❌ **금지된 의존성**:
- 다른 `features` 슬라이스 (feature 간 직접 의존 금지)
- `widgets` 레이어
- `pages` 레이어
- `app` 레이어
> 💡 **팁**: 여러 features가 공통 기능을 필요로 한다면, 그 기능을 `shared` 레이어로 이동시키거나 `entities` 레이어에서 관리하세요.
## 명명 규칙
- 소문자와 대시 사용: `auth-login`, `post-create`, `comment-edit`
- 동사 형태 권장: 사용자 액션을 나타내는 이름 사용
- 명확하고 구체적으로: 기능의 목적이 명확하게 드러나도록
## 주의사항
1. **하나의 기능에만 집중**: 각 feature는 단일 사용자 시나리오를 구현해야 합니다
2. **재사용성 고려**: 여러 페이지에서 사용될 수 있도록 설계
3. **독립성 유지**: 다른 features에 의존하지 않고 독립적으로 작동
4. **적절한 추상화**: 너무 많은 feature를 만들지 말고, 중요한 기능 위주로 구성
+3 -1
View File
@@ -6,7 +6,8 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"lint:fsd": "steiger ."
},
"dependencies": {
"@common/assets": "workspace:*",
@@ -28,6 +29,7 @@
"postcss": "^8.4.49",
"prettier": "^3.4.2",
"prettier-plugin-tailwindcss": "^0.6.11",
"steiger": "^0.5.11",
"tailwindcss": "^3.4.14",
"typescript": "^5.7.2"
}
+149
View File
@@ -0,0 +1,149 @@
# Shared Layer
**Shared**는 애플리케이션의 기반을 형성하는 레이어입니다. 외부 세계(백엔드, 서드파티 라이브러리, 환경)와의 연결을 생성하고, 높은 응집력을 가진 자체 라이브러리를 정의하는 곳입니다.
## 목적
- 외부 시스템 및 라이브러리와의 통합
- 프로젝트 전체에서 사용되는 공통 코드 제공
- 비즈니스 로직이 없는 재사용 가능한 유틸리티 및 UI 제공
- 글로벌 설정 및 환경 변수 관리
## 특징
- **슬라이스 없음**: Shared 레이어는 비즈니스 도메인이 없으므로 슬라이스로 나뉘지 않습니다
- **세그먼트 구성**: 기술적 목적에 따라 세그먼트로 직접 구성됩니다
- **자유로운 import**: Shared 내의 모든 파일은 서로를 참조하고 import할 수 있습니다
## 구조
```
shared/
├── ui/ # 애플리케이션 UI Kit
│ ├── button/
│ ├── input/
│ ├── modal/
│ └── index.ts
├── api/ # API 클라이언트 및 백엔드 엔드포인트 함수
│ ├── client.ts
│ └── index.ts
├── lib/ # 내부 라이브러리 모음
│ ├── dates/ # 날짜 관련 유틸리티
│ ├── colors/ # 색상 관련 유틸리티
│ ├── text/ # 텍스트 처리 유틸리티
│ └── index.ts
├── config/ # 환경 변수, 글로벌 feature flags
│ ├── env.ts
│ └── index.ts
├── types/ # 공통 타입 정의
│ └── index.ts
├── i18n/ # 번역 설정, 글로벌 번역 문자열
│ └── index.ts
└── routes/ # 라우트 상수 또는 패턴
└── index.ts
```
## 세그먼트 설명
### 📁 ui
애플리케이션의 UI Kit로, 비즈니스 로직을 포함하지 않는 재사용 가능한 UI 컴포넌트들입니다.
- Button, Input, Modal 같은 기본 컴포넌트
- 비즈니스 로직은 없지만 UI 로직은 포함 가능 (예: Autocomplete, SearchBar)
- 비즈니스 테마 컴포넌트도 허용 (예: 회사 로고, 페이지 레이아웃)
### 📁 api
API 클라이언트 및 특정 백엔드 엔드포인트 요청 함수입니다.
- HTTP 클라이언트 설정 (Axios, Fetch 등)
- 인증 인터셉터
- 공통 에러 핸들링
### 📁 lib
내부 라이브러리 모음으로, 각 라이브러리는 **하나의 관심사**에 집중해야 합니다.
> ⚠️ **중요**: `helpers`나 `utils` 폴더처럼 덤프 폴더로 만들지 마세요. 각 라이브러리는 명확한 초점 영역(예: dates, colors, text)을 가져야 하며, README로 문서화해야 합니다.
### 📁 config
환경 변수, 글로벌 feature flags 및 앱 전체 설정입니다.
### 📁 types
프로젝트 전체에서 사용되는 공통 타입 정의입니다.
### 📁 i18n
번역 설정 코드 및 글로벌 번역 문자열입니다.
### 📁 routes
라우트 상수 또는 라우트 매칭 패턴입니다.
## 예시
```typescript
// shared/ui/button/button.tsx
interface ButtonProps {
children: React.ReactNode;
variant?: 'primary' | 'secondary';
onClick?: () => void;
}
export function Button({ children, variant = 'primary', onClick }: ButtonProps) {
return (
<button
className={variant === 'primary' ? 'bg-blue-500' : 'bg-gray-500'}
onClick={onClick}
>
{children}
</button>
);
}
// shared/api/client.ts
import axios from 'axios';
export const apiClient = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL,
timeout: 10000,
});
// shared/lib/dates/format-date.ts
import dayjs from 'dayjs';
export function formatDate(date: Date, format: string = 'YYYY-MM-DD'): string {
return dayjs(date).format(format);
}
// shared/config/env.ts
export const ENV = {
apiUrl: process.env.NEXT_PUBLIC_API_URL!,
isDev: process.env.NODE_ENV === 'development',
} as const;
```
## 레이어 의존성 규칙
✅ **허용되는 의존성**:
- 같은 `shared` 레이어 내의 다른 세그먼트 (자유로운 cross-import)
- 외부 라이브러리 및 패키지
❌ **금지된 의존성**:
- `entities` 레이어
- `features` 레이어
- `widgets` 레이어
- `pages` 레이어
- `app` 레이어
> 💡 **원칙**: Shared는 가장 낮은 레이어이므로 상위 레이어에 의존하지 않습니다.
## 세그먼트 명명 규칙
세그먼트 이름은 **내용의 목적**을 설명해야 하며, **본질**을 설명하면 안 됩니다.
❌ **나쁜 예시**: `components`, `hooks`, `types` (본질을 설명)
✅ **좋은 예시**: `ui`, `api`, `lib/dates`, `config` (목적을 설명)
## 주의사항
1. **비즈니스 로직 없음**: Shared는 순수한 기술적 코드만 포함
2. **높은 재사용성**: 앱 전체에서 사용될 수 있어야 함
3. **명확한 라이브러리 구조**: `lib` 내부는 관심사별로 명확하게 분리
4. **문서화**: 각 라이브러리는 README로 사용법과 목적을 문서화
+113 -13
View File
@@ -1,35 +1,135 @@
# Widgets Layer
여러 features와 entities를 조합한 독립적인 UI 블록입니다.
**Widgets**는 큰 규모의 독립적인 UI 블록을 위한 레이어입니다. 여러 features와 entities를 조합하여 완전한 기능을 제공하는 복합 컴포넌트를 담습니다.
## 목적
- 큰 규모의 독립적인 UI 블록 구성
- 여러 features와 entities를 하나의 응집력 있는 UI로 결합
- 여러 페이지에서 재사용되는 복잡한 UI 제공
- 페이지 레벨 레이아웃 및 섹션 관리
## Widget으로 만들어야 하는 경우
Widget은 다음 조건에 해당할 때 사용하세요:
✅ **Widget으로 만들기 좋은 경우**:
- 여러 페이지에서 재사용되는 큰 UI 블록
- 페이지에 여러 개의 큰 독립적 블록이 있고, 이것이 그 중 하나인 경우
- 페이지 레벨 레이아웃 컴포넌트 (nested routing 시스템 사용 시)
❌ **Widget으로 만들지 말아야 하는 경우**:
- UI 블록이 페이지의 대부분을 차지하고 재사용되지 않는 경우 → 페이지 슬라이스 내부에 직접 배치
- 작은 재사용 컴포넌트 → `shared/ui`에 배치
## 구조
각 위젯은 다음 구조를 따릅니다:
각 widget 슬라이스는 다음 세그먼트로 구성됩니다:
```
widgets/
└── [widget-name]/
├── ui/ # UI 컴포넌트
├── model/ # 상태 관리 (선택적)
├── lib/ # 유틸리티 함수 (선택적)
├── ui/ # 위젯의 메인 UI 컴포넌트
├── model/ # 위젯 내부 상태 관리 (선택적)
├── api/ # 위젯 전용 API 호출 (선택적)
├── lib/ # 위젯 내부 유틸리티 (선택적)
└── index.ts # Public API
```
### 세그먼트 설명
- **ui**: 여러 features와 entities를 조합한 위젯 UI
- **model**: 위젯 내부 상태 및 로직 (선택적)
- **api**: 위젯이 필요로 하는 데이터 fetching (선택적)
- **lib**: 위젯 내부에서만 사용되는 헬퍼 함수 (선택적)
- **index.ts**: 슬라이스의 Public API (외부에서 사용할 수 있는 것만 export)
## 예시
```typescript
// widgets/header/ui/header.tsx
import { Logo } from 'shared/ui/logo';
import { Navigation } from 'shared/ui/navigation';
import { UserMenu } from 'features/user-menu';
import { NotificationBell } from 'features/notifications';
export function Header() {
// 헤더 UI (로고, 네비게이션, 사용자 메뉴 등)
return (
<header>
<Logo />
<Navigation />
<NotificationBell />
<UserMenu />
</header>
);
}
// widgets/header/index.ts
export { Header } from "./ui/header";
// widgets/product-list/ui/product-list.tsx
import { useProducts } from '../api/use-products';
import { ProductCard } from 'entities/product';
import { AddToCartButton } from 'features/cart-add-item';
export function ProductList() {
const { data: products, isLoading } = useProducts();
if (isLoading) return <div>로딩 중...</div>;
return (
<div>
{products.map((product) => (
<div key={product.id}>
<ProductCard product={product} />
<AddToCartButton productId={product.id} />
</div>
))}
</div>
);
}
// widgets/product-list/api/use-products.ts
import { useQuery } from '@tanstack/react-query';
import { getProducts } from 'entities/product';
export function useProducts() {
return useQuery({
queryKey: ['products'],
queryFn: getProducts,
});
}
// widgets/product-list/index.ts
export { ProductList } from './ui/product-list';
```
## 규칙
## 레이어 의존성 규칙
1. 여러 Features와 Entities를 조합할 수 있습니다
2. 다른 Widgets에 직접 의존하면 안 됩니다
3. 독립적으로 작동할 수 있어야 합니다
4. 페이지 레벨 레이아웃 컴포넌트로 사용됩니다
✅ **허용되는 의존성**:
- `shared` 레이어의 모듈
- `entities` 레이어의 모듈
- `features` 레이어의 모듈
- 같은 widget 슬라이스 내의 다른 세그먼트
❌ **금지된 의존성**:
- 다른 `widgets` 슬라이스 (widget 간 직접 의존 금지)
- `pages` 레이어
- `app` 레이어
## 명명 규칙
- 소문자와 대시 사용: `header`, `sidebar`, `product-list`
- 명사 형태 권장: UI 블록의 성격을 나타내는 이름 사용
- 구체적으로: 위젯의 역할이 명확하게 드러나도록
## Nested Routing 사용 시
Remix 같은 nested routing 시스템을 사용한다면:
- Widgets 레이어를 flat routing의 Pages 레이어처럼 사용 가능
- 완전한 라우터 블록 생성 (데이터 fetching, loading states, error boundaries 포함)
- 페이지 레이아웃을 이 레이어에 저장 가능
## 주의사항
1. **독립성 유지**: 각 위젯은 독립적으로 작동 가능해야 합니다
2. **적절한 크기**: 너무 작은 컴포넌트는 `shared/ui`에, 재사용되지 않으면 `pages`에 배치
3. **응집력**: 관련된 features와 entities를 의미 있게 조합
4. **재사용 최적화**: 여러 페이지에서 동일한 방식으로 사용될 수 있도록 설계
-831
View File
@@ -1,831 +0,0 @@
# 표준단어정의서
AI 이해용으로 정리된 표준단어명, 영문약어명, 영문명 목록입니다.
| 표준단어명 | 표준단어 영문약어명 | 표준단어 영문명 |
|-----------|-------------------|----------------|
| BOD | BOD | Biochemical Oxygen Demand |
| C/N비 | CNR | Carbon-Nitrogen Ratio |
| COD | COD | Chemical Oxygen Demand |
| F/M비 | FMR | Food-Microorganism Ratio |
| GISD | GISDATA | Geographic Information System Data |
| HTML | HTML | Hypertext Markup Language |
| ID | ID | Id |
| IP | IP | Internet Protocol |
| KEY | KEY | Key |
| ND | ND | Not Detected |
| NON | NON | Non |
| NTU | NTU | Nephelometry Turbidity Unit |
| OPT | OPT | Opt |
| PAC | PAC | Polyaluminium Chloride |
| PH | PH | Hydrogen Exponent |
| PKI | PKI | Public Key Infrastructure |
| POOL | POOL | Pool |
| SS | SS | Suspended Solids (Ss) |
| TCE | TCE | Trichloroethane |
| TM | TM | Transverse Mercator |
| T-N | TN | Total Nitrogen |
| TOC | TOC | Total Organic Carbon |
| T-P | TP | Total Phosphorus |
| URL | URL | Uniform Resource Locator |
| 가구 | HSHD | Household |
| 가능 | PSBL | Possible |
| 가동 | OPR | Operation |
| 가산 | ADTN | Addition |
| 가성소다 | NAOH | Caustic Soda(Nach) |
| 가축분뇨 | ANMA | Animal Manure |
| 값 | VAL | Value |
| 강도 | IN | Intensity |
| 강우 | RAIN | Rain |
| 개방 | OPN | Opening |
| 개별 | INDIV | Individual |
| 개보수비 | RPAFEE | Repair Fee |
| 개설 | ESTBL | Establishment |
| 개시 | STRT | Start |
| 개정 | RVSN | Revision |
| 개조 | REMDEL | Remodeling |
| 개체 | INDVD | Individual |
| 개체군 | POPU | Population |
| 개폐 | RORGN | Reorganization |
| 갱신 | UPDT | Update |
| 건물 | BLDG | Building |
| 건설 | CONC | Construction |
| 건수 | NOCS | The Number Of Cases |
| 건조 | DRY | Dry |
| 검사 | INSP | Inspection |
| 검사서 | EXRPT | Examination Report |
| 검정 | RCGN | Recognition |
| 검증 | VRFC | Verification |
| 검출 | DETECT | Detection |
| 검토 | RVW | Review |
| 격자 | LATTC | Lattice |
| 결과 | RSLT | Result |
| 결의 | DCIS | Decision |
| 결정 | DCSN | Decision |
| 경계 | BNDRY | Boundary |
| 경과 | PROC | Process |
| 경도 | LOT | Longitude |
| 경보 | ALARM | Alarm |
| 경사판 | ICNTPT | Inclination plate |
| 계 | SUM | Summation |
| 계량기 | MRNR | Measuring Instrument |
| 계량기분리 | METRSPRT | Meter Separation |
| 계면 | SGLV | Sludge Level |
| 계산식 | FMUL | Formula |
| 계약 | CTRT | Contract |
| 계약기간 | CNTRPD | Contract Period |
| 계절 | SEASON | Season |
| 계획 | PLAN | Plan |
| 고도처리 | AWTR | Advanced Water Treatment |
| 고시 | ANCMNT | Announcement |
| 고액분리 | SLSPRT | Solid-Liquid Separation |
| 고형물체류시간 | SRT | Solid Retention Time |
| 공간데이터 | SPCEDATA | Space Data |
| 공공 | PUBLIC | Public |
| 공급 | SPLY | Supply |
| 공기 | AIR | Air |
| 공기여과 | ARFT | Air Filter |
| 공문 | ODOC | Official Documnet |
| 공법 | MSRC | Method Of Construction |
| 공사 | CSTRN | Construction |
| 공사비 | CONSTEXPN | Construction Expenses |
| 공업지역 | MNFTR_ARA | Manufacturing Area |
| 공용면적 | CMAR | Common Area |
| 공통 | CMMN | Commonness |
| 관 | PP | Pipe |
| 관계 | REL | Relation |
| 관련 | RLTN | Relation |
| 관로 | PPLINE | Pipe Line |
| 관리 | MNG | Management |
| 관리기관 | MGC | Management Agency |
| 관리자 | MNGR | Manager |
| 관찰 | WTCH | Watch |
| 관측 | OBSR | Observation |
| 관측소 | OBSRVT | Observatory |
| 교반기 | AGITOR | Agirator |
| 교정 | CRRC | Correction |
| 구간 | SCTN | Section |
| 구동 | DRIVE | Drive |
| 구분 | SE | Section |
| 구성 | CMPSG | Composing |
| 구역 | ZONE | Zone |
| 구조 | STRCT | Structure |
| 권역 | DSTR | District |
| 권한 | AUTH | Authority |
| 규격 | STNDRD | Standard |
| 규모 | SCAL | Scale |
| 규제 | REGL | Regulation |
| 균등 | EQLTY | Equality |
| 금액 | AMT | Amount |
| 급수 | WSP | Water Supply |
| 기간 | WHL | While |
| 기관 | INST | Institution |
| 기록 | RECD | Recording |
| 기록부 | REGI | Register |
| 기밀 | SCRET | Secret |
| 기법 | TECQU | Techniques |
| 기본 | BSIC | Basics |
| 기본정보 | BASINF | Bassinfo |
| 기본키 | PK | Primary Key |
| 기상 | WETHER | Weather |
| 기안 | DRFTG | Drafting |
| 기재 | WRIT | Write |
| 기점 | CDPNT | Cardinal Point |
| 기존 | LGCY | Legacy |
| 기준 | CRTR | Criteria |
| 기타 | ETC | Etc |
| 기한 | TERM | Term |
| 기후 | CLMT | Climate |
| 긴급 | EMRG | Emergency |
| 날개벽 | WW | Wing Wall |
| 날씨 | WETHR | Weather |
| 날짜 | DATE | DATE |
| 남조류 | BLAL | Blue-Green Algae |
| 납 | PB | Plumbum |
| 내려받기 | DWLD | Download |
| 내부반송 | ITNRCC | Internal Recycl |
| 내용 | CN | Content |
| 내용연수 | SVLF | Service Life |
| 냄새 | SMELL | Smell |
| 년 | YY | Year |
| 년간 | FAYR | For A Year |
| 노즐 | NZL | Nozzle |
| 노출 | EXPSR | Exposure |
| 농도 | DNSTY | Density |
| 농축 | TKN | Thickened |
| 누적 | ACML | Accumulate |
| 누출 | LKG | Leakage |
| 눈 | SNW | Snow |
| 단가 | UNPRC | Unit Price |
| 단기 | SRTPD | Short Period |
| 단순 | SIMPL | Simplicity |
| 단위 | UNIT | Unit |
| 대구역 | LZONE | Large Zone |
| 대분류 | LCLAS | Large Classification |
| 대장 | REGSTR | Register |
| 대장균 | COLI | Coliform, Fecal Coliform |
| 대장균군 | COLIB | Coliform Bacteria |
| 대지면적 | SIAR | Site Area |
| 대체 | RPLC | Replace |
| 덮개 | COVR | Cover |
| 데이타 | DAT | Data |
| 도구 | UNT | Unit |
| 도래 | ADVNT | Advent |
| 도로 | ROAD | Road |
| 도로명 | RN | Road Name |
| 도시 | CTY | City |
| 도엽 | MAPDMC | Map Demarcation |
| 도표 | CHART | Chart |
| 독성 | TOXCTY | Toxicity |
| 동의 | AGRE | Agreement |
| 동절기 | WSESN | The Winter Season |
| 등급 | GRD | Grade |
| 등기 | RG | Registered |
| 등록 | REG | Registration |
| 디바이스 | DVICE | Device |
| 디코딩 | DCD | Decoding |
| 레이어 | LYR | Layer |
| 로그인 | LGN | Login |
| 로우 | ROW | Row |
| 마감 | DDLN | Deadline |
| 마이크로필터 | MCRFT | Micro Filter |
| 막 | MBRN | Membrane |
| 만족도 | STFDG | Satisfaction Degree |
| 맑음 | CLAR | Clear |
| 매각 | SAL | Sale |
| 맨홀 | MH | Manhole |
| 맵 | MAP | Map |
| 메인 | MAIN | Main |
| 메일 | EMAIL | Email |
| 메탄올 | MTN | Methanol(CH3OH) |
| 명 | NM | Name |
| 모니터링 | MTRG | Monitoring |
| 모델 | MODL | Model |
| 모델링 | MODLNG | Modeling |
| 모래 | SAND | Sand |
| 목 | MOK | Mok |
| 무산소 | ANX | Anoxic |
| 무산소조 | ANX_TANK | Anoxic Tank |
| 무인센서 | MNLSENSR | Manless Sensor |
| 문서 | DCMT | Document |
| 물 | WTR | Water |
| 미급수 | NONWTRSPL | Non Water Supply |
| 미생물 | BLGC | Biological |
| 미세먼지 | PM | Particulate Matter |
| 미세목 | MCRB | Micro Bar |
| 민간위탁 | ETSVN | Entrustment To Civilian |
| 민감 | SST | Sensitive |
| 민원 | CVLCPT | Civil Complaint |
| 바이러스 | VIRS | Virus |
| 반기 | HT | Half Term |
| 반류수 | SIDSWT | Side Stream Water |
| 반송 | SNDBK | Send Back |
| 반송수 | RCCWT | Recycled Water |
| 반송슬러지 | RTNSLG | Return Sludge |
| 반영 | RFLT | Reflection |
| 반응조 | RETNK | Reactant Tank |
| 반출 | EXPRT | Export |
| 반토 | ALUM | Alumina |
| 반환 | GVBK | Giving Back |
| 받이 | INL | Inlet |
| 발생 | OCRN | Occurrence |
| 발전 | PWGNRT | Power Generation |
| 발주기관 | ORNT | Order Institution |
| 방류 | DCWTR | Discharge Water Stock Etc |
| 방류구 | DSCHG | Discharge |
| 방류수 | EFLEC | Effluence |
| 방문 | VST | Visit |
| 방문자 | VSTR | Visitor |
| 방법 | MTHD | Method |
| 방사 | RLSE | Release |
| 배관 | PLINE | Pipeline |
| 배분 | DSTRB | Distirbution |
| 배설물 | EXCRTN | Excretion |
| 배수 | DRNG | Drainage |
| 배수구역 | DRANGZN | Drainage Zone |
| 배출 | EXHST | Exhaust |
| 배출가스 | EMGA | Emission Gases |
| 배출구 | VENT | Vent |
| 배출시설 | DHGP | Discharge Equipment |
| 배출시험 | EXHTST | Exhaust Test |
| 배출자 | DCHGR | Discharge Person |
| 밸브 | VALVE | Valve |
| 번호 | NO | Number |
| 법 | LAW | Law |
| 법적 | LGL | Legal |
| 법정 | STTY | Statutory |
| 법정동 | STDG | Statutory Dong(Administrative District) |
| 법정리 | STLI | Statutory Li(Administrative District) |
| 변경 | CHG | Change |
| 변동 | FLCTN | Fluctuation |
| 변속기 | TRMIS | Transmission |
| 보고 | RPT | Report |
| 보고서 | RPOT | Report |
| 보관 | STORG | Storage |
| 보수 | MEND | Mend |
| 보유 | HOLD | Hold |
| 보정 | RVSION | Revision |
| 보조 | ASSISC | Assistance |
| 보조금 | SBSIDY | Subsidy |
| 복개 | COVE | Cover |
| 복토 | CWTH | Covering With Soil |
| 본류 | MI_RV | Main River |
| 본번 | MNO | Main Number |
| 부검 | ATPSY | Autopsy |
| 부과 | LEVY | Levy |
| 부과금 | LVYAMT | Levy Amount |
| 부기 | BUKIP | Bookkeeping |
| 부담금 | ALOTM | Allotment |
| 부번 | SNO | Sub Number |
| 부산물 | BYPRD | By-Product |
| 부서 | DEPT | Department |
| 부숙화 | DECPZ | Decomposed ~Ize |
| 부적합 | IMPPRTY | Impropriety |
| 부착 | ASN | Adhesion |
| 부품 | CMPNT | Components |
| 부하량 | LOADQTY | Load Quantity |
| 분과 | DIVSN | Division |
| 분뇨 | ENSO | Excreta, Night Soil |
| 분류 | CL | Classification |
| 분류군 | TAXON | Taxon |
| 분리막 | SPRTMBR | Separation Membrane |
| 분배 | DTRBT | Distribution |
| 분배조 | DTRBT_TANK | Distribution Tank |
| 분야 | RLM | Realm |
| 분원성 | FECL | Fecal |
| 분원성대장균군 | FCOLI | Fecal Coliform |
| 분원성연쇄상구균 | FCSTRCCI | Fecal Streptococci |
| 분할 | PRTIN | Partition |
| 비밀번호 | PSWD | Password |
| 비상 | EMGNY | Emergency |
| 비정상 | ABNRM | Abnormality |
| 사양 | SPECS | Specification |
| 사업비 | WCT | Working Cost |
| 사업장 | BPLC | Business Place |
| 사여과지 | SAND_ FILTR | Sand Filter |
| 사용 | USE | Use |
| 사용가능 | USABLE | Usable |
| 사용권 | RIOUS | Right Of Using |
| 사용량 | USG | USAGE |
| 사용자 | USER | User |
| 사위 | FDG | Four Directions Girth |
| 사유 | RESN | Reason |
| 사이클 | CYCLE | Cycle |
| 사이트 | SITE | Site |
| 사진 | PHOT | Photograph |
| 사항 | MATTR | Matter |
| 사후 | AFTFAT | After Fact |
| 삭제 | DEL | Deletion |
| 산기관 | DFS | Diffuser |
| 산업 | INDUST | Industrial |
| 산화환원전위 | ORP | Oxidation Reduction Potential |
| 살모넬라 | SLMN | Salmonella |
| 삼원촉매장치 | TWCTLC | Three Way Catalytic Converter |
| 상세 | DTL | Details |
| 상세주소 | DADDR | Detailed Address |
| 상수 | WT | Water |
| 상업지역 | CMCL_ARA | Commercial Area |
| 상태 | STUS | Status |
| 상품 | GDS | Goods |
| 상향류 | UFW | Upflow |
| 상호 | CONM | Company Name |
| 색도 | CRMTY | Chromaticity |
| 생략 | OMS | Omission |
| 생물 | LVB | Living Being |
| 생물반응조 | BIRAT | Bioreactor |
| 생물서식처 | ORGNHBT | Organism Habitat |
| 생물종 | BISP | Biological Species |
| 생성 | CRT | Creation |
| 생슬러지 | RSLG | Raw Sludge |
| 생태 | ECLGY | Ecology |
| 생태독성 | ECTOX | ecotoxicity |
| 서류 | PAPE | Papers |
| 서명 | SIGN | Signing |
| 서버 | SRVR | Server |
| 서비스 | SRVC | Service |
| 설계 | DESGN | Design |
| 설계용량 | DESGN_CPCT | Design Capacity |
| 설립 | FNDN | Foundation |
| 설정 | STNG | Setting |
| 설치 | INSTL | Installation |
| 성격 | CHTR | Character |
| 성공 | SCS | Success |
| 성능 | PRFMNC | Performance |
| 성능검사 | EFTST | Efficiency Test |
| 성적서 | SCRRP | Score Report |
| 세균 | BCLS | Bacillus |
| 세목 | FB | Fine bar |
| 세부 | DETAIL | Detail |
| 세정 | WS | Washing |
| 세정제 | CNML | Cleaning Material |
| 소 | SML | Small |
| 소독 | DSNF | Disinfection |
| 소독제 | DSINF | Disinfectant |
| 소분류 | SCLAS | Small Classification |
| 소수점 | DCPT | Decimal Point |
| 소요 | REQ | Required |
| 소유 | OWN | Own |
| 소유역 | SBASIN | Sub Basin |
| 소재지 | PLAC | Place Of Location |
| 소포 | ATFM | Antifoaming |
| 소포수 | FBW | Foam Breaking Water |
| 소포제 | ANAG | Antifoaming Agent |
| 송부 | SENDNG | Sending |
| 송신 | SNDM | Send Message |
| 송풍기 | BLW | Blower |
| 수 | CNT | Count |
| 수거 | TKAWY | Take Away |
| 수계 | WWBH | Watershed, Water Basin, Hydrosphere |
| 수동 | HOPR | Hand Operation |
| 수리학적 체류시간 | HRT | Hydraulic Retention Time |
| 수문 | Gate | Gate |
| 수산화나트륨 | SOHY | Sodium Hydroxide |
| 수소이온 | HION | Hydrogen Ion |
| 수신 | RCPTN | Reception |
| 수용가 | RCPTR | Receptor |
| 수위 | WAL | Water Level |
| 수정 | MDFCN | Modification |
| 수정자 | MDFR | Modifier |
| 수제 | SPRDIKE | Superdike |
| 수조 | Tank | Tank |
| 수질 | QTWT | Quality Of Water |
| 수질개선 | WTRQLIMP | Water Quality Improvement |
| 수질기준 | WQST | Water Quality Standards |
| 수질배출정보 | WTDI | Water Discharge Information |
| 수집 | CLCT | Collection |
| 순환 | CCL | Cycling |
| 쉬겔라 | SHIGLA | Shigella |
| 스컴 | SCM | Scum |
| 스크린 | SCR | Screen |
| 슬러지 | SLG | Sludge |
| 슬러지 밀도지수 | SDI | sludge density index |
| 슬러지 용량 지표 | SVI | Sludge Volume Index |
| 습지 | WTLN | Wetland |
| 승인 | APRV | Approval |
| 승인권 | APPRVRGT | Right Of Approval |
| 시각 | TIME | Time |
| 시간 | HR | Hour |
| 시군구 | SGG | Si/Gun/Gu |
| 시나리오 | SCEN | Scenario |
| 시도 | CTPV | Cities And Provinces |
| 시료 | SMPL | Sample |
| 시설 | FCLT | Facility |
| 시설면적 | FCAR | Facility Area |
| 시설물 | FCLTS | Facilities |
| 시스템 | SYS | System |
| 시안 | CYN | Cyaan |
| 시운전 | TSTRN | Test Run |
| 시작 | BGNG | Beginning |
| 시점 | PTM | Point Time |
| 시행 | ENFC | Enforcement |
| 시험 | TEST | Test |
| 신고 | DCLR | Declaration |
| 신고자 | DCL | Declarer |
| 신규 | NEW | New |
| 신기술 | NTCH | New Technology |
| 신뢰 | CNFDNC | Confidence |
| 신뢰성 | CRDIBLTY | Credibility |
| 실시 | OPRT | Operation |
| 실적 | ACRS | Actual Result |
| 실행 | EXCN | Execution |
| 심사 | SRNG | Screening |
| 심의 | DLBR | Deliberation |
| 아황산환원혐기성포자형성균 | SFSRA | Spore Forming Sulfite Reducing Anaerobes |
| 안정화 | STBLZT | Stabilization |
| 암롤박스(컨테이너) | ARTCT | Arm roll type container |
| 암모니아성질소 | NHN | Ammonia Nitrogen |
| 압력 | PRESSR | Pressure |
| 압송 | PUMPNG | Pumping |
| 압축 | CMPRS | Compress |
| 액비 | LQFERTLZ | Liquid Fertilizer |
| 액상 | LIQD | Liquid |
| 약 | GENTLE | Gentle |
| 약품 | CMC | Chemical |
| 약품비 | MEDFEE | Medicine Fee |
| 약품사용 | USMD | Use Medicines |
| 업로드 | UPLD | Upload |
| 업무 | DTY | Duty |
| 없음 | NOT | Nothing |
| 에너지 | ENR | Energy |
| 에틸벤젠 | ETBNZN | Ethylbenzene |
| 여과 | FILTR | Filteration |
| 여과수 | FTWT | Filtered Water |
| 여과재 | FTMTRL | Filter Material |
| 여과형 | FILTRFOM | Filter Form |
| 여부 | YN | Yes or No |
| 여시니아균 | YERSNA | Yersinia |
| 역률 | PWRER_FCT | Power Factor |
| 역세척 | BWS | Back Wash |
| 연결 | CONN | Connection |
| 연계 | LINK | Link |
| 연도 | YR | Year |
| 연락 | CNTC | Contact |
| 연령 | AGE | Age |
| 연료화 | FUELZ | Fuelize |
| 연월 | YM | Year and Month |
| 염소 | CLRN | Chlorine |
| 염소소독 | CHDI | Chlorine Disinfection |
| 염소이온 | CLION | Chlorine Ion |
| 염화제이철 | IRCLD | Iron(III) Chloride |
| 예보 | FRCST | Forecast |
| 예비 | PRPT | Preparation |
| 예산 | BGT | Budget |
| 예상 | EXPCT | Expectation |
| 예약 | RSVT | Reservation |
| 예외 | EXCPT | Exception |
| 예정 | PRNG | Prearrangement |
| 예찰 | PRDICT | Prediction |
| 오류 | ERR | Error |
| 오수받이 | HUS_INL | House Inlet |
| 오염물질 | CNTMN | Contaminant |
| 오염원 | POLUSRC | Pollution Source |
| 오존 | OZN | Ozone |
| 오프로드 | OFFRD | Off Road |
| 옥살산 | OXACID | Oxalic Acid |
| 와류 | VORTEX | Vortex |
| 와류형 | VORTXFOM | Vortex From |
| 완결 | COMPLT | Completion |
| 완료 | CMPTN | Completion |
| 완전 | PRFECT | Perfection |
| 요건 | REQSIT | Requisite |
| 요막액 | ALLNTFLD | Allantoic Fluid |
| 요청 | DMND | Demand |
| 용량 | CPCT | Capacity |
| 용역 | SERVC | Service |
| 용존산소 | DO | Dissolved Oxygen |
| 용해 | DSLV | Dissolving |
| 우량 | EXLT | Excellent |
| 우수 | ST | Storm |
| 우수받이 | STRT_INL | Street Inlet |
| 우수토구 | STM_OVFL_MUT | Storm Overflow Mouth |
| 우회 | BP | BY PASS |
| 운반 | CNVY | Conveyance |
| 운영 | OPER | Operation |
| 운영비 | OPEXP | Operation Expense |
| 운행 | OPRAT | Operation |
| 원격 | RMRT | Rmrt |
| 원격감시체계 | TMS | Tele Monitoring System |
| 원료 | MTRAL | Material |
| 원수 | ORGWT | Origin'S Water |
| 원인자 | ORGPR | The Origin Person |
| 월 | MM | Month |
| 위도 | LAT | Latitude |
| 위반 | CNTR | Contravene |
| 위촉 | ENTRST | Entrusting |
| 위치 | LOC | Location |
| 위탁 | CNSG | Consign |
| 위탁자 | CONSGNR | Consignor |
| 유기인 | ORGP | Organic Phosphorus |
| 유량 | FLUX | Flux |
| 유량조정조 | EQLZT__TANK | Equalization Tank |
| 유입 | INFlOW | Inflow |
| 유입수 | INFWTR | Influent Water |
| 유주 | SWARMG | Swarming |
| 유지 | MNTNC | Maintenance |
| 유지용수공급 | MWRS | Maintenance Water Requirement Supply |
| 유체 | FLUID | Fluid |
| 유출 | EFFLUX | Efflux |
| 유충 | LAVL | Larval |
| 유형 | TY | Type |
| 유효 | VLD | Validity |
| 음용 | DKPS | For Drinking Purpose |
| 읍면동 | EMD | Eup/Myun/Dong |
| 응답 | RSPNS | Response |
| 응집제 | COAG | Cohesive Agents |
| 이관 | TRNSF | Transfer |
| 이동 | MVMN | Movement |
| 이력 | HST | History |
| 이메일 | EML | Email |
| 이상 | ABOVE | Above |
| 이송 | TRSF | Transfer |
| 이의 | OBJC | Objection |
| 이차 | SCDR | Secondary |
| 이차침전지 | SCDR_SDMT_TANK | Secondary Sedimaentation |
| 이행 | MIG | Migratation |
| 인건비 | PEXP | Personnel Expenses{Expenditure] |
| 인계 | HNDVR | Handover |
| 인계서 | HDOVDC | Handover Document |
| 인구 | POPL | Population |
| 인산 | PHACID | Phosphoric Acid |
| 인산염인 | POP | phosphate |
| 인양기 | LFT | Lifter |
| 인원수 | NOPE | The Number of Persons |
| 인증 | CERT | Certification |
| 인처리 | PPRCS | Phosphorus Process |
| 인허가 | APVL | Approval |
| 일 | DY | Day |
| 일련번호 | SN | Serial Number |
| 일반 | GNRL | General |
| 일별 | DALY | Daily |
| 일시 | DT | Date and Time |
| 일자 | YMD | YEAR Month Day |
| 일지 | DIARY | Diary |
| 일차 | PRM | Primary |
| 일차침전지 | PST_SDMT_TANK | Primary Sedimentation Tank |
| 일평균 | DYRG | Day Average |
| 임시 | TMPR | Temporary |
| 임의 | RNDM | Random |
| 입고 | WRHS | Warehousing |
| 입력 | INPT | Input |
| 잉여 | SPS | Surplus |
| 잉여슬러지 | EC_SLG | Excess Sludge |
| 자 | MAN | Man |
| 자갈 | GRAVEL | Gravel |
| 자료 | DATA | Data |
| 자리 | DIGIT | Digit |
| 자립화 | SLFRLI | Self Reliance |
| 자연형 | NATRLFOM | Natural Form |
| 자외선 | URLI | Ultraviolet Rays, Light |
| 자재 | MTRIL | Material |
| 자체 | ITSL | Itself |
| 작성 | WRT | Writing |
| 작업 | JOB | Job |
| 잠금 | LOCK | Lock |
| 장기 | LNGTR | Long Term |
| 장소 | PLCE | Place |
| 장착 | MNTNG | Mounting |
| 재 | RE | Re |
| 재이용 | REUSE | Reuse |
| 재이용수 | | Reuse Water |
| 재활용 | RUSE | Reuse |
| 저감 | REDUC | Reduction |
| 저류조 | DTT_TANK | Detention Tank |
| 저온 | LOWTMP | Low Temperature |
| 저장 | STRG | Storage |
| 저장소 | STORGE | Storage |
| 적발 | DSCL | Disclose |
| 적산 | ADD | Addition |
| 적용 | APLCN | Application |
| 적합 | STBLT | Suitability |
| 전기 | ELCTY | Electricity |
| 전기료 | ELFEE | Electricity Fee |
| 전력 | PWRER | Power |
| 전문 | SPCY | Specially |
| 전산 | CMPUTT | Computation |
| 전송 | TRSM | Transmission |
| 전압 | VLTGE | Voltage |
| 전용 | EXUSE | Exclusive Use |
| 전원 | SELCT | Source Of Electricity |
| 전처리 | PRETR | Pretreatment |
| 점검 | CHCK | Check |
| 접속 | CNTN | Connection |
| 정밀 | PRCIS | Precision |
| 정보 | INFO | Information |
| 정산 | CLCLN | Calculation |
| 정상 | NRMLT | Normality |
| 정수장 | WPPW | Water Purification Plant, Waterworks |
| 정제 | REFINE | Refining |
| 정지 | STP | Stop |
| 제거 | RMV | Removal |
| 제수변 | SL_VALVE | Sluice Valve |
| 제작 | MNFCT | Manufacture |
| 제조사 | MKR | Maker |
| 제출 | SBMSN | Submission |
| 제한 | LIMT | Limitation |
| 조류 | ALG | Algae |
| 조목 | CSB | Coarse Bar |
| 조사 | EXMN | Examination |
| 조성 | MAKE | Make |
| 조정 | EQLT | Equalization |
| 조치 | ACTN | Action |
| 조회 | INQ | Inquiry |
| 존재 | EXST | Existence |
| 종결 | TRMN | Termination |
| 종균제 | MICBA | Microbial Agent |
| 종료 | END | End |
| 종류 | KND | Kind |
| 종목 | IEM | Item |
| 종별 | ASORT | Assortment |
| 종사자 | ENFSN | Enfilade Person |
| 종점 | TMNL | Terminal |
| 좌표 | COOR | Coordinate |
| 주간 | WIK | Week |
| 주변 | CFR | Circumference |
| 주소 | ADDR | Address |
| 주입 | IJTN | Injection |
| 주파수 | FQNC | Frequency |
| 준공 | CMCN | Completion Of Construction |
| 중권역 | MDSTRC | Medium District |
| 중복 | DPCN | Duplication |
| 중분류 | MLSFC | Middle Classification |
| 중온 | MESPH | Mesophilic |
| 중첩 | RETRTN | Reiteration |
| 중화설비 | NUTEQP | Neutralization Equipment |
| 중화제 | CNTAG | Counteragent |
| 증가 | INCRS | Increase |
| 지도점검표사본 | CITBMR | Copy of Instruction Checklist |
| 지방자치단체 | LGOV | Local Governments |
| 지번 | LOTNO | Lot Number |
| 지상 | GRND | Ground |
| 지역 | ARA | Area |
| 지질 | NTRFS | Nature Of Soil |
| 지질도 | GEOMAP | Geological Map |
| 지하 | UDGD | Underground |
| 지하수 | GROU | Groundwater |
| 지형 | TPGRPH | Topography |
| 진공 | VCM | Vacuum |
| 진단 | DGNSS | Diagnosis |
| 진동 | VIBRAT | Vibration |
| 진행 | PRGRE | Progress |
| 질산 | NIACID | Nitric Acid. |
| 질산성질소 | NO3N | Nitrate Nitrogen |
| 집계 | TOT | Total |
| 집계구 | SUMDST | Summation District |
| 집행 | IMPL | Implementation |
| 찌꺼기 | LEES | Lees |
| 차아염소산 | NAOCL | Hypochlorous Acid |
| 차집 | ITCT | Intercepting |
| 착공 | BGNCST | Begin Construction |
| 채수 | SAMWT | Sampling Of Water |
| 채수기 | WTRSMPLR | Water Sampler |
| 채수병 | WTRBOTL | Water Bottle |
| 처리 | PRCS | Process |
| 처리비 | PSSFEE | Process Fee |
| 처리수 | TRT_WT | Treated Water |
| 처리수조 | TRT_WT_TANK | Treated Water Tank |
| 처리시설 | TRTMTFCLT | Treatment Facility |
| 처리자 | PRCR | Processor |
| 처분 | DSPS | Disposition |
| 철염 | FESLT | Ferric Salt |
| 첨부 | ATCH | Attachment |
| 첨부파일 | ATFI | Attachment File |
| 초과 | EXCS | Excess |
| 초기화 | INITL | Initialization |
| 촉매 | CTLY | Catalyst |
| 총계 | TSM | Summation |
| 총대장균군 | TCOLFGRP | Total Coliform Group |
| 총량 | TQT | Total Quantity |
| 총면적 | GFA | Gross Floor Area |
| 총사업비 | TPCO | Total Project Cost |
| 총인구 | TPOPLTN | Total Population |
| 총인처리시설 | TPFCT | Total Phosphorus facility |
| 최근 | RCNT | Recent |
| 최대값 | MAXV | Maximum Value |
| 최소값 | MINV | Minimum Value |
| 최적 | BMTB | Being The Most Suitable |
| 최종 | LAST | Last |
| 최초 | FRST | First |
| 추출 | EXTR | Extraction |
| 추출정보 | EXTRINFO | Extraction Information |
| 축 | AXS | Axis |
| 출력 | OTPT | Output |
| 출발 | LVE | Leave |
| 충전기 | CHRGR | Charger |
| 취득 | ACQS | Acquisition |
| 취소 | RTRCN | Retraction |
| 측정 | MSUR | Measurement |
| 측정기 | MSRR | Measurement Instrument |
| 측정소 | MSRSTN | Measurement Station |
| 침사지 | GTCB | Grit Chamber |
| 침전 | SDMT | Sediment |
| 침전지 | SDMT_TANK | sedimentation tank |
| 컨베이어 | CVY | Conveyor |
| 컬럼 | COL | Column |
| 코드 | CD | Code |
| 크기 | SZ | Size |
| 크실렌 | XYLEN | Xylene |
| 탄화 | CARB | Carbonization |
| 탈거 | CRYOFF | Carry Off |
| 탈리액 | SPNT | Supernatant |
| 탈수 | DWTR | Dewatering |
| 탈수기 | DEHYM | Dehydration Machine |
| 탈질 | DNTFCT | Denitrificatio |
| 탈취 | DODRZ | Deodorization |
| 탈취기 | DEODRZ | Deodorizer |
| 탈취제 | DEODR | Deodorant |
| 탈황제 | DSLFA | Desulfurizing Agent |
| 터널형 | YUNLTP | Tunnel Type |
| 테이블 | TBL | Table |
| 토구 | OTFL | Outfall |
| 토지 | LAD | Land |
| 토지면적 | LDAR | Land Area |
| 통계 | STATS | Statistics |
| 통보 | NTFCTN | Notification |
| 통신 | COMM | Communication |
| 통지 | AVTSMT | Avertissement |
| 통합 | UNTY | Unity |
| 특성 | CHRT | Character |
| 특수 | SPECL | Special |
| 특정유해물질 | SHCH | Specified Hazardous Chemicals |
| 파일 | FILE | File |
| 판정 | JGMT | Judgement |
| 펌프 | PUMP | Pump |
| 펌프장 | PUMP_STT | Pump Station |
| 페놀 | PHNL | Phenol |
| 평가 | EVL | Evaluation |
| 폐기 | DSCD | Discard |
| 폐기물 | WSTE | Waste |
| 폐쇄 | CLSG | Closing |
| 폐수 | WAWA | Waste Water |
| 폐수처리 | WSWT | Wastewater Treatment |
| 폐열 | WASTHET | Waste Heat |
| 포기 | ARTN | Aeration |
| 포트 | PORT | Port |
| 폭기조 | ARTN_TANK | Aeration Tank |
| 폴리머 | PLYMR | Polymer |
| 폴리철 | FRRCSU | Ferric Sulfate |
| 표고 | AL | Altitude |
| 표기 | MARK | Mark |
| 표시 | INDCT | Indication |
| 표준 | STD | Standard |
| 표출 | EPRSS | Expression |
| 플래그 | FLAG | Flag |
| 필드 | FILD | Field |
| 필수 | ESNTL | Essential |
| 필증 | CERFIN | Certificate Of Finishing |
| 필터 | FLTER | Filter |
| 하수 | SWGE | Sewage |
| 하수도 | DRNGSYS | Drainage System |
| 하수미처리 | SEWGUNTTM | Un Sewage Treatment |
| 하수처리 | SEWGTRTM | Sewage Treatment |
| 하수처리수 | STWTR | Sewage Treatment Water |
| 하위 | LOWR | Lower |
| 하향류 | DWFW | Downflow |
| 할인 | DSCNT | Discount |
| 함수율 | MISTR_CTNT | Moisture content |
| 합계 | SMM | Summation |
| 해당 | RLVT | Relevant |
| 해석 | INTRPRTT | Interpretation |
| 해양투기 | OCDU | Ocean Dumping |
| 행망 | ADMNW | Administration Network |
| 행정 | ADMN | Administration |
| 행정구역 | ADMI | Administrative District |
| 행정동 | DONG | Dong (Administrative District) |
| 허가 | PRMSN | Permission |
| 허용 | PERM | Permission |
| 현상 | PHNMN | Phenomenon |
| 혐기 | AARB | Anaerobic |
| 혐기조 | AARB_TANK | Anaerobic tank |
| 협잡물 | CCMT | Concomitant |
| 형태 | SHAP | Shape |
| 호기 | ARB | Aerobic |
| 호기조 | ARB_TANK | Aerobic Tank |
| 호소수 | LMSHWT | Lake And Marsh Water |
| 호수 | LKE | Lake |
| 호안 | RVTMNT | Revetment |
| 호이스트 | HIST | Hoist |
| 혼합 | CMPN | Compound |
| 혼합액현탁고형물 | MLSS | Mixed liquor suspended solids |
| 혼화지 | MXG_TNAK | Mixing tank |
| 홈페이지 | HMPG | Homepage |
| 홍수 | FLOOD | Flood |
| 확인 | IDNTY | Identify |
| 확인서 | CNFRMN | Confirmation |
| 확인자 | IDFR | Identifier |
| 확장자 | EXTN | Extension |
| 확정 | CFMTN | Confirmation |
| 환경 | ENVR | Environment |
| 환경기초시설 | ENINF | Environmental Infrastructure |
| 환원 | RSTORE | Restoration |
| 활성탄 | AC | Activated Carbon |
| 활성화 | PRMT | Promote/Facilitate |
| 활용 | PRUS | Practical Use |
| 황산 | ECCBT | Encyclopaedia Britannica (H2So4) |
| 회사 | CO | Company |
| 회수 | RTRVL | Retrieval |
| 회신 | RPLY | Reply |
| 효율 | EFC | Efficiency |
| 효율성 | EFFCTV | Effectiveness |
| 휴대 | MBL | Mobile |
| 흡수정 | EXTTW | Extraction Well |
| 흡착 | ADST | Adsorption |
File diff suppressed because it is too large Load Diff
+8 -60
View File
@@ -105,6 +105,9 @@ importers:
prettier-plugin-tailwindcss:
specifier: ^0.6.11
version: 0.6.14(prettier@3.7.4)
steiger:
specifier: ^0.5.11
version: 0.5.11(typescript@5.9.3)
tailwindcss:
specifier: ^3.4.14
version: 3.4.19(yaml@2.8.2)
@@ -10507,8 +10510,8 @@ snapshots:
'@typescript-eslint/parser': 8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react: 7.37.5(eslint@9.39.2(jiti@2.6.1))
eslint-plugin-react-hooks: 5.2.0(eslint@9.39.2(jiti@2.6.1))
@@ -10528,7 +10531,7 @@ snapshots:
eslint: 9.39.2(jiti@1.21.7)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@1.21.7))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@1.21.7))
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2(jiti@1.21.7))
eslint-plugin-react: 7.37.5(eslint@9.39.2(jiti@1.21.7))
eslint-plugin-react-hooks: 5.2.0(eslint@9.39.2(jiti@1.21.7))
@@ -10567,21 +10570,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.3
eslint: 9.39.2(jiti@2.6.1)
get-tsconfig: 4.13.0
is-bun-module: 2.0.0
stable-hash: 0.0.5
tinyglobby: 0.2.15
unrs-resolver: 1.11.1
optionalDependencies:
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@1.21.7)):
dependencies:
'@nolyfill/is-core-module': 1.0.39
@@ -10593,7 +10581,7 @@ snapshots:
tinyglobby: 0.2.15
unrs-resolver: 1.11.1
optionalDependencies:
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@1.21.7))
transitivePeerDependencies:
- supports-color
@@ -10623,17 +10611,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
transitivePeerDependencies:
- supports-color
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)):
dependencies:
debug: 3.2.7
@@ -10645,7 +10622,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7)):
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@1.21.7)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -10674,35 +10651,6 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
array.prototype.findlastindex: 1.2.6
array.prototype.flat: 1.3.3
array.prototype.flatmap: 1.3.3
debug: 3.2.7
doctrine: 2.1.0
eslint: 9.39.2(jiti@2.6.1)
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
minimatch: 3.1.2
object.fromentries: 2.0.8
object.groupby: 1.0.3
object.values: 1.2.1
semver: 6.3.1
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
'@typescript-eslint/parser': 8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.49.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@2.6.1)):
dependencies:
'@rtsao/scc': 1.1.0