axios 과정
Javascript useEffect(() => { const getProjectData = () => { axios .get(`${END_POINT}/project/${projectId}`, { withCredentials: true, }) .then((res) => { const urlArr = []; const descArr = []; res.data.projectdata.project_content.forEach((el) => { urlArr.push(el.image); descArr.push(el.text); }); setCurFiles(urlArr); setDescription(descArr); setProject_name(res.data.projectdata.project_name); setProject_info({ project_start: res.data.projectdata.project_start, project_end: res.data.projectdata.project_end, project_team: res.data.projectdata.project_team, project_introduction: res.data.projectdata.project_introduction, project_feature: res.data.projectdata.project_feature, project_github: res.data.projectdata.project_github, project_front_stack: res.data.projectdata.project_front_stack, project_back_stack: res.data.projectdata.project_back_stack, project_deploy_stack: res.data.projectdata.project_deploy_stack, project_url: res.data.projectdata.project_url, }); setUser_id(res.data.userdata.user_id); setUser_name(res.data.userdata.user_name); setUser_photo(res.data.userdata.user_photo); scrollTo(0) }) .catch((err) => { alert('프로젝트 정보를 받아오는데 실패하였습니다.'); }); }; getProjectData(); }, []);
이미지 업로드 서버파트
const multerS3 = require("multer-s3"); const AWS = require("aws-sdk"); // s3에 올리기 위한 multer s3 설정 const multer = require("multer"); const upload = multer({ storage: storage, limits: { fileSize: 10000000 }, }); app.post("/upload", upload.single("image"), (req, res) => { console.log("저장한 이미지", req.file); res.json({ fileName: req.file, }); }); // 멀터 테스트 // localhost multer test // multer s3를 위한 설정 try { fs.accessSync("uploads"); } catch (error) { console.log("uploads 폴더가 없으므로 생성합니다."); fs.mkdirSync("uploads"); } AWS.config.update({ accessKeyId: process.env.S3_ACCESS_KEY_ID, secretAccessKey: process.env.S3_SECRET_ACCESS_KEY, region: "ap-northeast-2", }); // AWS에서 s3로 저장하는 권한 얻는 코드 const uploadS3 = multer({ storage: multerS3({ s3: new AWS.S3(), bucket: "hometownalbaimage", //s3에서 설정한 BucketName으로 넣어야함 key(req, file, cb) { cb(null, `original/${Date.now()}_${path.basename(file.originalname)}`); }, }), limits: { fileSize: 20 * 1024 * 1024 }, // 20MB }); // 라우터 예시 app.post("/uploads3", uploadS3.single("image"), (req, res, next) => { console.log("저장한 이미지", req.file); res.json({ fileName: req.file.location.replace(/\/original\//, "/thumb/"), }); //original 폴더가 있으면 리사이징된 thumb로 교체 -> 업로드 끝나면 다시 original로 업데이트됨 }); // 프론트엔드 // uploadS3를 미들웨어로 장착하면 ok // option : Array() // multer s3를 위한 설정
token
const [isLogin, setIsLogin] = useState(false); const [accessToken, setAccessToken] = useState({ accessToken: null }) const [userInfo, setUserInfo] = useState({ email: '', nickname: '', img: '' }); const history = useHistory(); //로그인 관리---------------------------------------- const loginHandler = () => { setIsLogin(true); issueAccessToken(data.accessToken); // issueAccessToken(data.data.accessToken); } useEffect(() => { if (accessToken.accessToken === null) { logoutHadler(); } }, []) //로그아웃 관리------------------------------------------------------- const logoutHadler = () => { axios .post(`${process.env.REACT_APP_SERVER_URL}/users/signout`, { withCredentials: true }) .then((res) => { setIsLogin(false); setAccessToken({ accessToken: null }); setUserInfo({ email: '', nickname: '', img: '' }) history.push('/'); }); }; //토큰 요청-------------------------------------------------------------- const accessTokenRequest = (accessToken) => { axios .get(`${process.env.REACT_APP_SERVER_URL}/tokenData/accessToken`, { headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', }, withCredentials: true, }) .then((res) => { const { email, nickname, img } = res.data.userInfo setUserInfo({ email, nickname, img }) }) .catch((err) => console.log(err) ); } //토큰 최신화------------------------------------ const issueAccessToken = (token) => { setAccessToken({ accessToken: token }); accessTokenRequest(token); } //새로고침해도 로그인 유지-------------------- useEffect(() => { accessTokenRequest(); }, [])
<> <BrowserRouter> <Nav isLogin={isLogin} logoutHadler={logoutHadler} /> <Switch> <Route exact path="/"> <MainPage /> </Route> <Route path="/RefrigeratorPage"> <RefrigeratorPage isLogin={isLogin} userInfo={userInfo} accessToken={accessToken} /> </Route> <Route path="/AlarmPage"> <AlarmPage isLogin={isLogin} userInfo={userInfo} accessToken={accessToken} /> </Route> <Route path="/MyPage"> <MyPage isLogin={isLogin} userInfo={userInfo} accessToken={accessToken} logoutHadler={logoutHadler} /> </Route> <Route path="/LogInPage"> <LogInPage loginHandler={loginHandler} /> </Route> </Switch> </BrowserRouter> <Footer /> </> );
[JS] [emailJS] 자바스크립트로 이메일 보내기
Node.js - 이메일 보내기 기능 구현하기 (Nodemailer)
Nodemailer
Nodemailer 공식 홈페이지npm install nodemailer
"use strict"; const nodemailer = require("nodemailer"); // async..await is not allowed in global scope, must use a wrapper async function main() { // Generate test SMTP service account from ethereal.email // Only needed if you don't have a real mail account for testing let testAccount = await nodemailer.createTestAccount(); // create reusable transporter object using the default SMTP transport let transporter = nodemailer.createTransport({ host: "smtp.ethereal.email", port: 587, secure: false, // true for 465, false for other ports auth: { user: testAccount.user, // generated ethereal user pass: testAccount.pass, // generated ethereal password }, }); // send mail with defined transport object let info = await transporter.sendMail({ from: '"Fred Foo 👻" <foo@example.com>', // sender address to: "bar@example.com, baz@example.com", // list of receivers subject: "Hello ✔", // Subject line text: "Hello world?", // plain text body html: "<b>Hello world?</b>", // html body }); console.log("Message sent: %s", info.messageId); // Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com> // Preview only available when sending through an Ethereal account console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info)); // Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou... } main().catch(console.error);
mailtrap.io
mailtrap.io 공식홈페이지
https://mingule.tistory.com/68
PUT : 리소스의 모든 것을 업데이트 한다.
PATCH : 리소스의 일부를 업데이트 한다.
전체페이지
height 60em -> 40em 으로 변경 (footer가 안보인)
login 페이지
margin 10em -> 3.5em 로변경 (footer가 안보인)
냉장고 페이지
전체적인 폭 80% 축소 (너무 꽉차보여서 줄임)
마이페이지
1. 회원정보수정, 회원탈퇴 모달창 외부(배경) 클릭시 닫힘 구현
2. toggle 스위치 0.3s 슬로우 에니메이션 추가 및 on off text 추가
회원가입 색 변경
#FF7272
1. 애플리케이션 등록
앱 아이콘이 나중에 OAuth를 실행할 때 나오는 아이콘이 된다
2. 플랫폼 등록
플랫폼 등록사이트에서 OAuth 2.0을 사용할 우리의 웹사이트 도메인주소를 입력한다
3. 하단의 제품설정의 카카오 로그인 설정
Redirect URI란 카카오서버와 우리의 서버가 토큰과 정보를 주고받을 때, 우리 서비스에서 그 정보를 받는 페이지이다.
이 페이지에서 카카오서버에서 제공하는 정보를 받고 다음 작업으로 넘어가게 된다.
4. 동의항목 설정
하단의 동의항목 설정에서 로그인시 필요한(카카오서버에서 제공받을) 데이터들을 선택한다.
이는 카카오 OAuth를 이용해 처음 로그인할 때 유저에게 어떤 정보를 동의받는지 체크하는 permission List이다.
기본적인 에플리케이션 세팅은 완료
OAuth 진행과정
카카오 rest API OAuth 2.0로그인은 세가지 단계를 거친다.
인증코드 요청
인증코드로 Access Token 요청
Access Token으로 API호출
1. 인증코드 요청 후 토큰 받아오기
postMan에는 Authrization이라고 인증을 위한 도구가 있다.TYPE을 OAuth 2.0으로 선택 후 get New AccessToken을 누른다.
postMan에는 Authrization이라고 인증을 위한 도구가 있다.
TYPE을 OAuth 2.0으로 선택 후 get New AccessToken을 누른다.
1) Callback URL : Redirect URI로 등록한 주소
2) Auth URL : 카카오톡 인증코드 request 주소
GET /oauth/authorize?client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}&response_type=code HTTP/1.1 Host: kauth.kakao.com
3) Access Token URL : 카카오톡 토큰 request 주소
POST /oauth/token HTTP/1.1 Host: kauth.kakao.com Content-type: application/x-www-form-urlencoded;charset=utf-8
4) Client ID : REST API 키를 입력해서 Request Token을 클릭
2. 로그인 후 토큰 확인
이후 카카오 로그인창이 뜬다.
내부적으로 인증코드를 받아온 후 토큰을 Access Token과 Refresh Token을 정상적으로 응답받았다.
- 토큰으로 내정보 받아오기
발급받은 토큰을 Bearer형식으로 설정하고
해당 url로 get요청을 보내면 우리가 처음 permission List에 등록했던 정보들이 응답된다.
- 연결끊기
아래 url로 토큰과 함께 연결을 끊는 요청을 보낸다.https://kapi.kakao.com/v1/user/unlink