4 글 보임 - 1 에서 4 까지 (총 4 중에서)
-
글쓴이글
-
2023년 6월 19일 23:21 #87635
강민택참가자안녕하세요 선생님. 선생님의 nextJs 강의를 듣고 난 뒤에 개인 프로젝트에 적용을 하던 도중 해결되지 않는 부분이 있어서 질문 남깁니다!
프로필 사진 업로드 후에 변경 기능을 추가하려고 합니다. 사진은 S3에 업로드가 되고, S3에서 url을 반환받아서 mongoDB에 유저정보에 저장하는 식으로 되어 있는데요, mongoDB updateOne 함수로 DB profileImage 데이터가 바뀌는 것 까지는 잘됩니다! 하지만 로그아웃을 했다가 다시 재 로그인을 해야지만 변경된 프로필 이미지가 뜨는데, 로그인 상태에서 바로 변경될 수는 없는건가요? ( 로그인 방식은 next-auth 의 jwt 방식을 사용했습니다 ) 제가 생각한 문제점은 1. session에 원래 있던 프로필 이미지가 저장이 되어있기때문에 클라이언트 측에서는 변경된 이미지를 확인불가능하다. 2. 세션 업데이트를 하지않아서 이미지가 변경되지 않는것이다.
이렇게 생각했었는데요, 그래서 시도한 방법은
1. useSession 훅의 update함수를 사용하는것
2. 클라이언트 측에서 이미지 업로드를 할때에 session 업데이트를 하는 api를 만들어서 적용, 이렇게 시도했었는데 해결이 안되네요.. 이제는 뭐가 문제인지 잘 모르겠습니다. 아래는 코드 입니다. // Profile.js ( Profile 페이지 컴포넌트 )
"use client";
import * as S from "./profileStyle"; import Link from "next/link"; import Image from "next/image"; import back from "/public/assets/img/left.png"; import edit from "/public/assets/img/editprofile.png"; import LogoutOnclick from "./logoutOnclick"; import useImageUpload from "../../hooks/useImageUpload"; import { useSession } from "next-auth/react"; export default function Profile() { const right = ">"; const { data: session, status, update } = useSession(); let user = session?.user;
const { src, handleImageUpload } = useImageUpload();
const handleFileChange = (e) => { const file = e.target.files[0]; handleImageUpload(file); }; const userProfileImage = user?.profileImage; const profileImageUrl = `https://baemin-taek.s3.amazonaws.com/${userProfileImage}`; return ( <S.Container> <S.Header> <Link href="/mypage" as="/mypage"> <Image src={back} width={27} alt="back-btn" /> </Link> <span className="header-title">내 정보 수정</span> </S.Header> {userProfileImage ? ( <Image src={profileImageUrl} alt="profile-image" width={100} height={100} /> ) : ( <Image src={edit} alt="edit" width={100} height={100} /> )} <input type="file" accept="image/*" onChange={handleFileChange} />
<S.InfoBox> <S.Item> <span className="title">닉네임</span> <div> <span className="sub">{user?.name}</span> <S.RightBtn>{right}</S.RightBtn> </div> </S.Item> <S.Item> <span className="title">이메일</span> <span className="sub">{user?.email}</span> </S.Item> <S.Item style={{ borderBottom: "none" }}> <span className="title">휴대폰 번호 변경</span> <S.RightBtn>{right}</S.RightBtn> </S.Item> </S.InfoBox> <S.Box> <div style={{ display: "flex", flexDirection: "column" }}> <span className="title">로그인 기기 관리</span> <span className="disc"> 내 아이디로 로그인 된 기기를 관리할 수 있어요 </span> </div> <S.RightBtn style={{ marginRight: "15px" }}>{right}</S.RightBtn> </S.Box> <S.Box> <div style={{ display: "flex", flexDirection: "column" }}> <span className="title">연결된 서비스 관리</span> <span className="disc"> 배민 아이디와 연결된 서비를 관리할 수 있어요 </span> </div> <S.RightBtn style={{ marginRight: "15px" }}>{right}</S.RightBtn> </S.Box> <S.Box> <span className="title">연동된 소셜 계정</span> </S.Box> <S.AccountBox> <LogoutOnclick /> <span className="bar">|</span> <span className="out">회원탈퇴</span> </S.AccountBox> </S.Container> ); }
/api/image.js
import aws from 'aws-sdk'; import { MongoClient } from 'mongodb'; import { getSession } from "next-auth/react";
export default async function handler(req, res) { const session = await getSession({ req }); aws.config.update({ accessKeyId: process.env.ACCESS_KEY, secretAccessKey: process.env.SECRET_KEY, region: 'ap-northeast-2', signatureVersion: 'v4', });
const s3 = new aws.S3(); const url = await s3.createPresignedPost({ Bucket: process.env.BUCKET_NAME, Fields: { key: req.query.file }, Expires: 60, // seconds Conditions: [ ['content-length-range', 0, 1048576], // 파일용량 1MB 까지 제한 ], });
// MongoDB 저장 const userId = session?.user?.name; const value = url.fields.key; try { const mongoUrl = process.env.MONGO_URL; const client = await MongoClient.connect(mongoUrl); const db = client.db('baemin'); const collection = db.collection('accounts'); await collection.updateOne( { name: userId }, { $set: { profileImage: value} } );
client.close(); } catch (error) { console.error('MongoDB 저장 실패:', error); res.status(500).json({ error: ' MongoDB 저장 실패' }); return; }
res.status(200).json(url); }
/hooks/useImageUpload ( 이미지 업로드 커스텀 훅 )
import { useState } from "react"; export default function useImageUpload() { const [src, setSrc] = useState(""); const handleImageUpload = async (file) => { try { const filename = encodeURIComponent(file.name); let res = await fetch(`/api/imageUpload/image?file=${filename}`); res = await res.json();
// S3 업로드 const formData = new FormData(); Object.entries({ ...res.fields, file }).forEach(([key, value]) => { formData.append(key, value); });
let result = await fetch(res.url, { method: "POST", body: formData, });
if (result.ok) { setSrc(`${result.url}/${filename}`); } else { window.alert('이미지 크기는는 1MB 이하여야 합니다.'); } } catch (error) { console.error(error); } };
return { src, handleImageUpload }; }
여기까지 제 코드 입니다.. 어떤 부분이 문제인지 아니면 접근 방식이 잘못되었는지 알려주신다면 감사하겠습니다! 앗 추가로 useSession() 쓰면 update 함수에 nextauth 설정파일에있는 jwt 함수가 실행된다고 알고 있는데 유저 jwt내용을 어떻게 수정할수있을까요? / [...nextauth].js callbacks: { //4. jwt 만들 때 실행되는 코드 //user변수는 DB의 유저정보담겨있고 token.user 저장 시 jwt에 들어감. jwt: async ({ token, user }) => { if (user) { token.user = {}; token.user.name = user.name; token.user.email = user.email; token.user.profileImage = user.profileImage; } return token; }, //5. 유저 세션이 조회될 때 마다 실행되는 코드 session: async ({ session, token }) => { session.user = token.user; return session; }, }, next auth 설정 부분입니다! 이틀째 해결을 못하고있는데 답답하네요 ㅠㅠ
2023년 6월 20일 09:35 #87669
codingapple키 마스터https://stackoverflow.com/a/75924500 이거 따라합시다 아무 페이지에서 update() 실행하면 jwt: async ({ token, user }) => { 안에있는게 실행되는데 거기서 jwt안에 원하는 정보 추가하는 식으로 하면 되는듯요
2023년 6월 20일 15:57 #87730
강민택참가자덕분에 해결했습니다!
근데 의도에 맞게 동작은 하는데 이렇게 하는게 맞는지 확신이 들진 않습니다. 혹시 죄송하지만 코드가 괜찮은지 한번 봐주실수있나요?
수정된 부분은 다음과 같습니다. // jwt jwt: async ({ token, user, session, trigger }) => { if (user) { token.user = {}; token.user.name = user.name; token.user.email = user.email; token.user.profileImage = user.profileImage; } if( trigger === 'update'){ token.user.profileImage = session.info } return token; }, // image upload 부분 const handleFileChange = (e) => { const file = e.target.files[0]; handleImageUpload(file); sessionUpdate({ info: file.name }) }; 항상 감사합니다. 좋은 하루 보내세요!
-
글쓴이글
4 글 보임 - 1 에서 4 까지 (총 4 중에서)
- 답변은 로그인 후 가능합니다.