Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions week07/keyword/keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## 핵심 키워드

- 미들웨어

요청과 응답 사이에서 실행되는 함수

요청을 가로채서 로깅, 인증, 데이터 변환 등의 작업을 수행한 후 다음 단계로 전달함

```jsx
app.use((req, res, next) => {
console.log('요청 받음');
next(); // 다음 미들웨어로
});
```

- HTTP 상태 코드

서버의 응답 상태를 나타내는 3자리 숫자

- **2xx (성공)**: 200 OK, 201 Created
- **3xx (리다이렉션)**: 301 Moved Permanently, 302 Found
- **4xx (클라이언트 에러)**: 400 Bad Request, 401 Unauthorized, 404 Not Found
- **5xx (서버 에러)**: 500 Internal Server Error, 503 Service Unavailable
- 에러 핸들링(Error Handling)

프로그램 실행 중 발생하는 오류를 처리하는 방법

- **try-catch**: 예외를 잡아서 처리
- **에러 미들웨어**: Express에서 전역 에러 처리
- **Promise rejection**: `.catch()` 또는 `try-catch with async/await`
79 changes: 79 additions & 0 deletions week07/mission/mission.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
## 미션 기록

### 성공 응답 및 에러 처리

```jsx
export const handleAddUserMission = async (req, res, next) => {
try {
const dto = createUserMissionDto(req.body);
const userMission = await addUserMission(dto);
res.status(StatusCodes.CREATED).success(userMission);
} catch (err) {
next(err);
}
};

export const handleListUserMissionsInProgress = async (req, res) => {
const usermissions = await listUserMissionsInProgress(
parseInt(req.params.userId),
typeof req.query.cursor === "string" ? parseInt(req.query.cursor) : 0
);
res.status(StatusCodes.OK).success(usermissions);
};

```

POST api (생성)

- 성공 시 201(CREATED)
- 에러 발생 시 catch(err)로 들어옴
- catch 블록에서 next(err) 호출 시 Express가 전역 에러 핸들러로 이동(app.use)
- 전역 에러 핸들러에서는 res.error(…)를 통해 클라이언트에 최종 JSON 응답 반환

GET api (조회)

- 성공 시 200(OK)

응답 형식

- 성공 응답: `res.success(data)`
- 실패 응답: `res.error({ errorCode, reason, data })`

---

서비스 내부 동작

```jsx
export const addUserMission = async (data) => {
const mission = await getMissionById(data.missionId);
if (!mission) throw new MissionError("해당 미션이 존재하지 않습니다.", data);

const existing = await getUserMission(data.userId, data.missionId);
if (existing) throw new DuplicateMissionError("이미 도전 중인 미션입니다.", data);

const userMissionId = await insertUserMission(data);

const userMission = await getUserMissionById(userMissionId);
return userMission;
};
```

각 서비스 내부에서 에러 발생 시 throw new CustomError() 형태로 커스텀 에러를 던짐

에러 발생 시 호출한 컨트롤러의 try-catch 블록으로 전달됨 → next(err) 호출

커스텀 에러

```jsx
export class DuplicateMissionError extends Error {
errorCode = "M002";

constructor(reason, data) {
super(reason);
this.reason = reason;
this.data = data;
}
}
```

.