Skip to content

[7주차/찬찬] 워크북 제출합니다#12

Open
inhadissolve wants to merge 3 commits into
UMC-Inha:chanchan/mainfrom
inhadissolve:main
Open

[7주차/찬찬] 워크북 제출합니다#12
inhadissolve wants to merge 3 commits into
UMC-Inha:chanchan/mainfrom
inhadissolve:main

Conversation

@inhadissolve
Copy link
Copy Markdown

@inhadissolve inhadissolve commented May 13, 2026

✅ 실습 체크리스트

  • 이론 학습을 완료하셨나요?
  • 미션 요구사항을 모두 이해하셨나요?
  • 실습을 수행하기 위한 공부를 완료하셨나요?
  • 실습 요구사항을 모두 완료하셨나요?

✅ 컨벤션 체크리스트

  • 디렉토리 구조 컨벤션을 잘 지켰나요?
  • pr 제목을 컨벤션에 맞게 작성하였나요?
  • pr에 해당되는 이슈를 연결하였나요?(중요)
  • 적절한 라벨을 설정하였나요?
  • 파트장에게 code review를 요청하기 위해 reviewer를 등록하였나요?
  • 닉네임/main 브랜치의 최신 상태를 반영하고 있는지 확인했나요?(매우 중요!)

@inhadissolve inhadissolve self-assigned this May 13, 2026
@inhadissolve inhadissolve added the documentation Improvements or additions to documentation label May 13, 2026
Comment on lines +1 to +18
export class AppError extends Error {
public readonly errorCode: string;
public readonly statusCode: number;
public readonly data?: unknown;

constructor(params: {
errorCode: string;
message: string;
statusCode: number;
data?: unknown;
}) {
super(params.message);

this.errorCode = params.errorCode;
this.statusCode = params.statusCode;
this.data = params.data ?? null;
}
} No newline at end of file
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전역 AppError 선언해서 사용하신것 좋습니다~


export function authorizeUser() {
return async (req: Request, res: Response, next: NextFunction) => {
const { username } = req.cookies;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

클라이언트에서 보내준 쿠키만 검증에 사용하는것은 위험할 수 있습니다! 항상 서버는 클라이언트를 의심하고 보수적으로 동작해야한다는것을 명심해주세요!

Comment on lines +7 to +11
if (username) {
console.log(`[인증 성공] ${username}님, 환영합니다.`);
next();
return;
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

username은 클라이언트가 조작할 수 있습니다.
인증에는 최소한 다음 중 하나가 필요합니다.

  • 서버 세션 ID
  • 서명된 쿠키
  • JWT access token
  • DB에서 검증 가능한 session token

단순히 username 문자열만 보고 인증하면 안 됩니다!

Comment on lines +15 to +19
res
.status(401)
.send(
'<script>alert("로그인이 필요합니다!");location.href="/api/v1/users/login";</script>'
);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

응답을 HTML script로 하는것은 의도한 대로 동작하지 않을수 있습니다! API 서버라면 가능하면 응답형식을 JSON으로 통일하는 방법으로 고려하고 alert 창이 뜨는 로직은 클라이언트에 위임하는 방식으로 생각해주세요!

Comment thread src/index.ts
Comment on lines +34 to +37
*/
const router = express.Router();

app.get("/api/v1/users/:userId/reviews", handleListMyReviews);
RegisterRoutes(router);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드를 확인해보니 user이외에는 tsoa 등록이 안되어있네요! tsoa는 @ decorator를 통해서만 경로가 등록되니 추후에 나머지 엔드포인트도 수정해주세요!

Comment on lines +33 to +64
@Get("guest")
public async handleGuestPage(): Promise<string> {
return `
<h1>게스트 페이지</h1>
<p>이 페이지는 로그인이 필요 없습니다.</p>
<ul>
<li><a href="/api/v1/users/mypage">마이페이지로 이동</a></li>
</ul>
`;
}

@Get("login")
public async handleLoginPage(): Promise<string> {
return `
<h1>로그인 페이지</h1>
<p>로그인이 필요한 페이지에서 이동합니다.</p>
<a href="/api/v1/users/set-login">로그인 쿠키 생성하기</a>
`;
}

res.status(StatusCodes.OK).json({
result: user,
@Get("mypage")
@Middlewares(authorizeUser())
public async handleMypage(
@Request() req: ExpressRequest
): Promise<string> {
return `
<h1>마이페이지</h1>
<p>환영합니다, ${req.cookies.username}님!</p>
<p>이 페이지는 로그인한 사람만 볼 수 있습니다.</p>
<a href="/api/v1/users/set-logout">로그아웃</a>
`;
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

단순 페이지 반환, 비동기 로직이 없는 코드는 async를 안붙이셔도 됩니다! 로직 내부에서 repo나 비동기 처리가 필요한 함수만 async 를 명시해주세요

Comment on lines +10 to 26
export const userSignUp = async (
data: UserSignUpRequest
): Promise<UserSignUpResponse> => {
const joinUserId = await addUser({
email: data.email,
password: hashedPassword,
password: data.password,
name: data.name,
gender: data.gender,
birth: data.birth,
address: data.address,
detailAddress: data.detailAddress,

// 요청 body에서는 birth가 문자열로 들어오기 때문에 Date 객체로 변환합니다.
birth: new Date(data.birth),

// 선택값은 undefined로 들어올 수 있으므로 기본값을 넣어줍니다.
address: data.address ?? "",
detailAddress: data.detailAddress ?? "",
phoneNumber: data.phoneNumber,
});
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oauth를 통해 회원가입, 로그인 하는 경우 각자 필요한 데이터 필드가 다릅니다! 단순 이메일로 회원가입 로그인도 처리 될 수 있도록 확인해주세요!

Comment thread prisma/schema.prisma
Comment on lines 10 to 25
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oauth 회원가입이 들어가는 경우 원래 사용하던 user schema와 필요한 데이터가 각자 다를 수 있습니다! 단일 schema로 운영할 경우 해당 유저가 어떤 oauth로 회원가입했는지 확인하는 필드, 각 oauth에서 발급해주는 id 등을 추가해주시면 좋을거 같습니다!

Comment on lines +1 to +11
export interface ApiResponse<T> {
resultType: "SUCCESS";
error: null;
success: T;
}

export const success = <T>(data: T): ApiResponse<T> => ({
resultType: "SUCCESS",
error: null,
success: data,
}); No newline at end of file
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants