## type, inteface 차이점 쉬운맛 1) 원시성 데이터 사용 type: 가능, interface: 불가능 2) 튜플 사용 type: 가능, interface: 불가능 3) interface 취약점 중복 선언하면 동일 실행 환경에서는 모두 합쳐지는 특징이 있어서 의도하지 않고 다른개발자가 같은 이름이 있는 인퍼페이스를 선언하면 에러 메세지가 뜨지 않는다
결론 가능하면 type을 더 많이 쓰는것이 좋다. 버전이 올라가면서 interface가 성능이 조금더 좋다는 이슈가 사라졌다. 고로 type을 조금더 선호하자
/**
* Represents an HTTP request handler function.
*/
type RequestHandler = (req: Request, res: Response, next: (err?: Error) => void) => void;
/**
* Represents an error handling middleware function.
*/
type ErrorHandler = (err: Error, req: Request, res: Response, next: (err?: Error) => void) => void;
/**
* Represents a middleware function, which can be either a RequestHandler or an ErrorHandler.
*/
type Middleware = RequestHandler | ErrorHandler;
서버에 middlewares 배열을두고
class Server {
private server: net.Server;
private router?: Router;
private staticDirectory?: string;
private middlewares: Middleware[] = [];
길이만큼 돌려준다.
에러가 있으면 에러도 같이 넘겨준다.
에러가 없으면, 등록된 미들웨어 실행
private runMiddleware(
middlewares: Middleware[],
index: number,
err: Error | null,
req: Request,
res: Response,
): void {
if (index < 0 || index >= middlewares.length) return;
const nextMiddleware = middlewares[index];
const next = (e?: Error) => this.runMiddleware(middlewares, index + 1, e || null, req, res);
if (err) {
// 에러가 있고, 다음에 실행할 미들웨어가 에러 처리기인경우 에러처리 미들웨어 실행
if (this.isErrorHandler(nextMiddleware)) {
(nextMiddleware as ErrorHandler)(err, req, res, next);
} else {
// 에러가 있고, 다음에 실행할 미들웨어가 에러 처리기가 아니면 그 다음 미들웨어를 찾는다
this.runMiddleware(middlewares, index + 1, err, req, res);
}
} else {
/**
* as로 타입강제지정, 등록된 함수 실행
* 아래코드와 같은기능
* if (this.isRequestHandler(nextMiddleware)) {
* nextMiddleware(req, res, next);
*/
(nextMiddleware as RequestHandler)(req, res, next);
}
}
// 기본 미들웨어 타입 정의
type BaseMiddleware = RequestHandler | ErrorHandler;
// 확장된 미들웨어 인터페이스
interface MiddlewareExtension {
__path?: string;
}
// 최종 미들웨어 타입 (교차 타입 사용)
type Middleware = BaseMiddleware & MiddlewareExtension;
/**
* 인자1개 -> 첫번째인자를 Middleware 취급
* 인자 2개 -> 첫번째인자는 path, 두번째인자는 middleware
* @param path
* @param fn
*/
public use (path: string | Middleware, middleware?: Middleware) {
if (typeof(path) === "string" && middleware) {
middleware.__path = path;
} else if (typeof path === "function") {
middleware = path;
} else {
throw new Error("Usage: use(path, fn) or use(fn)");
}
this.middlewares.push(middleware);
};
* 프론트 컨트롤러 도입 v1
설계
앞단에서 요청을 받아서 맞는 컨트롤러를 호출해줌. 유사 router?
인터페이스 설계
import {Request} from "../../was/request";
import {Response} from "../../was/response";
export interface ControllerV1 {
process(req : Request , res : Response) : void
}
회원가입 컨트롤러
viewPath를 받아서, 해당하는 html파일을 render 해준다.
import {ControllerV1} from "../ControllerV1";
import {Request} from "../../../was/request";
import {Response} from "../../../was/response";
import * as path from "path";
export class MemberFormControllerV1 implements ControllerV1{
public async process(req : Request , res : Response) : Promise<void>{
const viewPath : string = path.join(process.cwd(), 'dist','views','new-form.html');
await res.forward(req,res,viewPath);
}
}