Skip to content

[Feat] 9주차 미션_겸 - #64

Open
hkjo0703 wants to merge 1 commit into
gyeomfrom
week9-gyeom
Open

[Feat] 9주차 미션_겸#64
hkjo0703 wants to merge 1 commit into
gyeomfrom
week9-gyeom

Conversation

@hkjo0703

@hkjo0703 hkjo0703 commented May 24, 2026

Copy link
Copy Markdown
Contributor

📂 관련 이슈


🛠️ 작업 사항

  • 기존에 사용자의 정보를 하드 코딩 했던 부분들이 있다면 수정
  • 기존 회원 가입 API를 수정하여 이미 존재하는 사용자도 정보를 채워 정보를 갱신할 수 있도록 수정해주셔도 괜찮고, 새로운 API를 만들어서 자기 자신의 정보를 수정하는 API를 만들어주셔도 괜찮습니다. 자유롭게 선택
  • 9주차 워크북에서 만든 인증 시스템(JWT) 을 그동안 만들었던 기존 API들에 적용하여 ‘로그인한 사용자만’ 쓸 수 있도록 보호
  • 이번 주에는 Google 로그인 외에 다른 소셜 로그인을 하나 더 연동

📸 관련 이미지 (스크린샷 또는 동영상)


💬 기타 설명

💡 추가적으로 공유할 내용이나 리뷰어에게 전달할 사항이 있다면 작성해 주세요.

@hkjo0703
hkjo0703 requested a review from wldmsdl7 May 24, 2026 16:21
@hkjo0703 hkjo0703 self-assigned this May 24, 2026
@hkjo0703 hkjo0703 added ✨Feature 새로운 기능 추가 📡 API API 관련 작업 labels May 24, 2026

@wldmsdl7 wldmsdl7 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

굿!! 잘 구현해준 것 같아 ~
tsoa 구조로 미들웨어를 등록한 점도 좋았고,
단순히 따라 구현하기보다는 tsoa 구조 자체를 이해하고 적용하려고 고민한 흔적이 보여서 좋았어!
9주차 동안 기능 구현하느라 정말 고생 많았어 !

추가로 하나만 이야기하자면,
현재처럼 하나의 폴더 안에 파일이 하나만 존재하는 구조는 조금 아쉬운 것 같아!
나중에 프로젝트를 진행할 때도 비슷한 구조가 된다면, 굳이 controller, service, repository, dto를 나누기보다는 기능 단위로 폴더를 구성하거나, 규모가 작다면 폴더를 합쳐서 관리하는 것도 좋은 방법일 것 같아 ~

9주차 관련해선 피드백 몇 가지 남겼으니까 수정하고 싶으면 수정해도 좋을 것 같아 !
tsoa의 인증 인가 구조에 대한 공식 문서 남겨줄테니까 참고해봐도 좋을 것 같아 ~

Comment thread gyeom/week9/src/index.ts
Comment on lines +124 to +138
app.get("/oauth2/login/google", passport.authenticate("google", { session: false }));
app.get("/oauth2/callback/google",
passport.authenticate("google", { session: false, failureRedirect: "/login-failed" }),
(req, res) => {
res.status(200).json({ success: true, tokens: req.user });
}
);

app.get("/oauth2/login/kakao", passport.authenticate("kakao", { session: false }));
app.get("/oauth2/callback/kakao",
passport.authenticate("kakao", { session: false, failureRedirect: "/login-failed" }),
(req, res) => {
res.status(200).json({ success: true, tokens: req.user });
}
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

OAuth2 로그인 흐름 자체는 잘 구현해준 것 같아!
다만 현재는 Google / Kakao 로그인 라우터를 app.get으로 직접 등록하고 있는데, 이전 주차에서 tsoa를 적용했던 만큼 Controller 단으로 정리해보는 것도 좋을 것 같아.

현재 프로젝트에서는 tsoa 기반 라우터와 Express 방식 라우터가 함께 사용되고 있어서, 인증 및 라우팅 구조를 하나로 통일해주면 더 일관된 구조로 가져갈 수 있지 않을까 ??

Comment on lines +32 to +51
if (!email) throw new Error("Google 프로필에 이메일이 없습니다.");

let user = await prisma.user.findFirst({ where: { email } });

if (!user) {
user = await prisma.user.create({
data: {
email,
name: profile.displayName,
gender: UserGender.NONE,
birthDate: new Date(1970, 0, 1),
address: "추후 수정",
phone: "추후 수정",
regionId: 1,
latitude: 0,
longitude: 0,
createdAt: new Date(),
},
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

지금 Strategy 내부에 DB 조회/생성 하는 로직까지 들어가 있어서 각 계층 별 책임 분리가 잘 되어있지 않는 상황이야 !

Passport Strategy 에는Oauth 인증 성공 -> Service 호출 -> 결과 반환 정도의 역할만 수행하는 경우가 많아. 따라서, 현재 googleVerify 에 있는 회원 조회, 회원 생성, 기본값 세팅과 같은 비즈니스 로직은 Service로 빼면 좋을 것 같아 ~

Comment on lines +61 to +80
if (!email) throw new Error("카카오 프로필에 이메일이 없습니다.");

let user = await prisma.user.findFirst({ where: { email } });

if (!user) {
user = await prisma.user.create({
data: {
email,
name,
gender: UserGender.NONE,
birthDate: new Date(1970, 0, 1),
address: "추후 수정",
phone: "추후 수정",
regionId: 1,
latitude: 0,
longitude: 0,
createdAt: new Date(),
},
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

이 부분도 같이 수정해주면 좋을 것 같아 !

{
clientID: process.env.PASSPORT_GOOGLE_CLIENT_ID!,
clientSecret: process.env.PASSPORT_GOOGLE_CLIENT_SECRET!,
callbackURL: "/oauth2/callback/google",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

여기 URL은 하드코딩 하는 것보단 얘도.env파일로 빼주는 게 좋아. 나중에 배포하게 되면, 실행 환경에 따라 배포 주소로 연결하거나, 로컬 주소로 연결하도록 구현하기도 하니까 참고해주면 좋을 듯 !

{
clientID: process.env.PASSPORT_KAKAO_CLIENT_ID!,
clientSecret: process.env.PASSPORT_KAKAO_CLIENT_SECRET,
callbackURL: "/oauth2/callback/kakao",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

여기도 하드코딩 된 부분 수정하면 좋을 것 같아 ~

* @summary 사용자가 특정 미션에 도전하는 엔드포인트입니다.
*/
@Post("{missionId}/challenge")
@Middlewares(authenticateJwt())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

API 마다 이렇게 미들웨어를 붙여줬구나 !
tsoa를 적용하려고 한 것 같은데, 이 방식 역시나 tsoa 구조에 Express 미들웨어를 붙여쓰는 방식이야.

tsoa가 공식적으로 제공하는 인증 방식은 @Security("jwt")야 . 스웨거 뿐만 아니라 expressAuthentication 함수와 자동으로 연동되면서 tsoa 구조의 장점이 훨씬 살아나 ! 나중에 프로젝트 할 때는 한 번 참고해서 사용해보면 좋겠다 ~

아래 코드처럼 사용할 수 있어 !

@Security("jwt")
@Post("{missionId}/challenge")
@SuccessResponse(200, "미션 도전 성공")
public async handleAddUserMission(
  @Path() missionId: number,
  @Request() req: ExpressRequest,
): Promise<ApiResponse<UserMissionAddResponse>> {

  const userId = Number((req.user as any).id);

  const userMission = await userMissionAdd(
    userId,
    { missionId }
  );

  return success(
    StatusCodes.OK,
    "미션 도전 성공",
    userMission
  );
}

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

Labels

📡 API API 관련 작업 ✨Feature 새로운 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants