Skip to content

마이크로프론트엔드를 위한 API 서버 구축

커리어 플랫폼의 마이크로앱들이 사용할 Mock API 서버를 json-server 기반으로 구축하고, CORS 및 인증 미들웨어를 설정한다.

학습 목표

  • json-server를 활용한 Mock REST API 서버 구축 방법을 이해한다
  • 마이크로앱별 API 엔드포인트를 체계적으로 설계할 수 있다
  • CORS 설정과 인증 미들웨어를 통한 API 보안 기초를 익힌다
  • Auth0 토큰을 활용한 API 인증 흐름을 구현할 수 있다

1. Mock API 서버의 역할과 아키텍처

마이크로프론트엔드에서 각 마이크로앱은 독립적으로 데이터를 관리하지만, 개발 단계에서는 통합된 Mock API 서버를 활용하면 빠르게 프로토타이핑할 수 있다. 커리어업 프로젝트에서는 json-server를 사용하여 REST API를 빠르게 구축한다.


2. 모노레포 워크스페이스에 서버 패키지 추가

json-server는 모노레포의 독립 워크스페이스로 설정한다. 별도의 빌드 과정 없이 Node.js로 직접 실행하는 방식이다.

yaml
# pnpm-workspace.yaml
packages:
  - "apps/*"
  - "packages/*"
  - "server"        # API 서버 워크스페이스
  - "fragments/*"
json
// server/package.json
{
  "name": "@career-up/server",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "json-server": "0.17.4"
  }
}

json-server 0.17.4(Stable)을 사용하는 이유: 최신 알파 버전은 API가 크게 변경되어 기존 문서와 호환되지 않는다. Stable 버전을 명시적으로 지정하여 안정적으로 사용한다.


3. db.json 데이터 설계

모든 마이크로앱이 사용할 데이터를 하나의 db.json 파일에 정의한다. json-server는 이 파일의 최상위 키를 REST 엔드포인트로 자동 매핑한다.

json
// server/db.json (구조 예시)
{
  "posts": [
    {
      "id": 1,
      "message": "마이크로프론트엔드 학습을 시작합니다.",
      "createdAt": "2024-01-15T09:00:00.000Z",
      "author": {
        "name": "홍길동",
        "email": "hong@example.com",
        "picture": "https://example.com/avatar.png"
      }
    }
  ],
  "courses": [
    {
      "id": 1,
      "thumbnail": "/images/react-course.png",
      "title": "React 심화",
      "description": "React 고급 패턴을 학습합니다."
    }
  ],
  "courseContents": [
    {
      "id": 1,
      "goals": ["컴포넌트 설계 패턴 이해", "성능 최적화 기법 습득"],
      "summaries": ["HOC와 Render Props", "React.memo와 useMemo"]
    }
  ],
  "jobs": [
    {
      "id": 1,
      "company": "테크 스타트업",
      "position": "프론트엔드 개발자",
      "location": "서울 강남구"
    }
  ],
  "connections": [
    {
      "id": 1,
      "name": "김개발",
      "picture": "https://example.com/dev.png",
      "role": "백엔드 개발자",
      "networkCount": 150
    }
  ]
}

json-server 자동 매핑 규칙:

HTTP 메서드경로동작
GET/posts전체 포스트 조회
GET/posts/1id=1 포스트 조회
POST/posts포스트 생성
PUT/posts/1포스트 전체 수정
PATCH/posts/1포스트 부분 수정
DELETE/posts/1포스트 삭제
GET/posts?_sort=id&_order=desc정렬된 목록 조회

4. 서버 코드 작성과 CORS 설정

json-server의 기본 미들웨어(jsonServer.defaults())에 CORS 자유 설정이 포함되어 있다. 추가로 커스텀 인증 미들웨어를 등록한다.

javascript
// server/index.js
const jsonServer = require("json-server");

const server = jsonServer.create();
const router = jsonServer.router("db.json");
const middlewares = jsonServer.defaults();

const AUTH0_DOMAIN = "https://your-domain.auth0.com";

// 1) 기본 미들웨어: CORS, 정적 파일, 로깅
server.use(middlewares);

// 2) JSON body 파싱
server.use(jsonServer.bodyParser);

// 3) 인증 미들웨어
server.use(async (req, res, next) => {
  const authorized = await isAuthenticated(req);
  if (authorized) {
    next();
  } else {
    res.sendStatus(401);
  }
});

// 4) 커스텀 엔드포인트: 유저 정보
server.get("/user", (req, res) => {
  res.jsonp({
    ...req.user,
    viewCount: 249,
    updateCount: 100,
    courses: [
      { courseId: 1, done: true },
      { courseId: 4, done: false }
    ]
  });
});

// 5) POST 요청 시 author 정보 자동 추가
server.post("/posts", (req, res, next) => {
  req.body.createdAt = new Date().toISOString();
  req.body.author = {
    name: req.user.name,
    email: req.user.email,
    picture: req.user.picture
  };
  next();
});

// 6) db.json 라우터 등록
server.use(router);

// 7) 서버 시작
server.listen(4000, () => {
  console.log("JSON Server is running on port 4000");
});

// Auth0 토큰 검증 함수
async function isAuthenticated(req) {
  try {
    const authorization = req.headers.authorization;
    const response = await fetch(`${AUTH0_DOMAIN}/userinfo`, {
      headers: { authorization }
    });
    const json = await response.json();
    req.user = json;
    return true;
  } catch (e) {
    return false;
  }
}

5. CORS 상세 설정

jsonServer.defaults()는 기본적으로 모든 출처(origin)의 요청을 허용한다. 프로덕션에서는 반드시 허용 출처를 제한해야 한다.

javascript
// 개발 환경 기본 CORS (json-server defaults에 포함)
// Access-Control-Allow-Origin: *
// Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
// Access-Control-Allow-Headers: Content-Type, Authorization

// 프로덕션 환경에서의 CORS 제한 예시
const corsOptions = {
  origin: [
    "http://localhost:3000", // Shell
    "http://localhost:3001", // Posting
    "http://localhost:3002", // Edu
    "http://localhost:3003", // Network
    "http://localhost:3004"  // Job
  ],
  credentials: true
};

마이크로앱별 포트 매핑:

서비스포트역할
Shell (Host)3000전체 라우팅, 인증 관리
Posting (Remote)3001포스팅 CRUD
Education (Remote)3002교육 콘텐츠
Network (Remote)3003인맥 관리
Job (Remote)3004채용 공고
API Server4000Mock REST API

6. API 엔드포인트 종합 설계

각 마이크로앱이 사용하는 엔드포인트를 정리한다.

마이크로앱엔드포인트메서드설명
공통/userGET현재 로그인 유저 정보 (커스텀)
Posting/posts?_sort=id&_order=descGET포스트 목록 (최신순)
Posting/postsPOST포스트 작성
Posting/posts/:idDELETE포스트 삭제
Education/coursesGET교육 코스 목록
Education/courseContents/:idGET코스 상세 내용
Network/myNetworkGET내 네트워크 통계 (커스텀)
Network/connectionsGET인맥 목록
Job/jobsGET채용 공고 목록
Job/applyStatusGET지원 현황 (커스텀)

핵심 정리

  1. json-server는 db.json 파일의 최상위 키를 REST 엔드포인트로 자동 매핑하여 빠르게 Mock API를 구축할 수 있다
  2. jsonServer.defaults() 미들웨어에 CORS 허용, 정적 파일 서비스, 요청 로깅이 포함되어 있다
  3. 인증 미들웨어는 Authorization 헤더의 Bearer 토큰을 Auth0 /userinfo 엔드포인트로 검증한다
  4. server.get(), server.post() 등으로 json-server 기본 라우팅 외에 커스텀 엔드포인트를 추가할 수 있다
  5. POST 요청 시 next()를 호출하기 전에 req.body를 수정하면 db.json에 수정된 데이터가 저장된다
  6. 프로덕션에서는 CORS 허용 출처를 반드시 제한하고, 실제 인증 서버를 사용해야 한다

다음 단계

  • 02-포스팅-서비스.md: CSS Modules로 스타일링하고 포스팅 CRUD 기능을 구현하며, Module Federation으로 Remote 설정을 완성한다