Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ 4주차 기본/공유 과제 ] 보운이의 로그 #5

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
18 changes: 18 additions & 0 deletions week4/week4-Login/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
24 changes: 24 additions & 0 deletions week4/week4-Login/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
12 changes: 12 additions & 0 deletions week4/week4-Login/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"printWidth": 120,
"tabWidth": 4,
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"requirePragma": false,
"arrowParens": "always",
"endOfLine": "auto",
"arrayIndentation": "auto",
"bracketSpacing": false
}
30 changes: 30 additions & 0 deletions week4/week4-Login/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:

- Configure the top-level `parserOptions` property like this:

```js
export default {
// other rules...
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname,
},
}
```

- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
12 changes: 12 additions & 0 deletions week4/week4-Login/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";


export default [
{languageOptions: { globals: globals.browser }},
pluginJs.configs.recommended,
...tseslint.configs.recommended,
pluginReactConfig,
];
13 changes: 13 additions & 0 deletions week4/week4-Login/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>보운이의 로그인</title>
</head>
<body style="margin: 0px; background-color: rgb(184, 202, 186)">
Copy link
Member

Choose a reason for hiding this comment

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

p4: 여기 글로벌 스타일로 빼면 좋을 것 같아요!

<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
47 changes: 47 additions & 0 deletions week4/week4-Login/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "week4-login",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"format": "prettier --write --cache ."
},
"dependencies": {
"@types/styled-components": "^5.1.34",
"axios": "^1.6.8",
"file-loader": "^6.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-player": "^2.16.0",
"react-router-dom": "^6.23.0",
"styled-components": "^6.1.10",
"typescript-plugin-styled-components": "^3.0.0"
},
"devDependencies": {
"@eslint/js": "^9.2.0",
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@types/react-router": "^5.1.20",
"@types/react-router-dom": "^5.3.3",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.8.0",
"@vitejs/plugin-react-swc": "^3.5.0",
"eslint": "^9.2.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.6",
"globals": "^15.1.0",
"prettier": "^3.2.5",
"typescript": "^5.2.2",
"typescript-eslint": "^7.8.0",
"vite": "^5.2.0"
}
}
Binary file added week4/week4-Login/public/videos/고양이.mp4
Binary file not shown.
19 changes: 19 additions & 0 deletions week4/week4-Login/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {Route, Routes} from 'react-router-dom';
import MainPage from './page/MainPage';
import LoginPage from './page/LoginPage';
import SignupPage from './page/SignupPage';
import MyPage from './page/MyPage';

function App() {
return (
<Routes>
<Route path="/" element={<MainPage />} />
<Route path="/:memberId" element={<MainPage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/signup" element={<SignupPage />} />
<Route path="/mypage/:memberId" element={<MyPage />} />
</Routes>
);
}

export default App;
1 change: 1 addition & 0 deletions week4/week4-Login/src/assets/base-url.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const BASE_URL = 'http://34.64.233.12:8080';

Choose a reason for hiding this comment

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

p5)base_url을 이렇게 빼서 사용할 수 도 있군여 ?!

Copy link
Member

Choose a reason for hiding this comment

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

p1: 서버 주소는 .env 파일로 빼주세요!

Binary file added week4/week4-Login/src/assets/img2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added week4/week4-Login/src/assets/img3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions week4/week4-Login/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.tsx';
import {BrowserRouter} from 'react-router-dom';

ReactDOM.createRoot(document.getElementById('root')!).render(
<BrowserRouter>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>
Comment on lines +7 to +11
Copy link
Member

Choose a reason for hiding this comment

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

p4: 일반적으로 애플리케이션의 모든 부분에 StricMode를 적용하기위해서 StricMode를 가장 바깥쪽으로 빼주는 것으로 알고 있습니다.
BrowserRouter와 React.StrictMode의 위치를 바꿔주는 것이 좋을 것 같습니다.

);
74 changes: 74 additions & 0 deletions week4/week4-Login/src/page/LoginPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {Area, HelpP, IMG, Input, InputContaier, InputSort, MoveButton} from '../style/styleComponents';
import loginImg from '../assets/img2.jpg';
import {Link, useNavigate} from 'react-router-dom';
import {useState} from 'react';
import axios from 'axios';
import {BASE_URL} from '../assets/base-url';

export default function LoginPage() {
const navi = useNavigate();
const [id, setId] = useState('');
const [pw, setPw] = useState('');

const handleLogin = async () => {
if (id && pw) {
//만약 모두가 값이 있다면
try {
await axios
.post(`${BASE_URL}/member/login`, {
authenticationId: id,
password: pw,
})
Comment on lines +1 to +21

Choose a reason for hiding this comment

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

p5)저는 fetch를 사용했는데 axios를 많이들 사용했더라구여?! 사용하는 방법 배워갑니다~ 그리고 확실히 axios를 사용하면 형변환 할일이 없어 코드가 간결해지는 것 같아염

.then((res) => {
//location Header에 있는 게 이거 맞나..?
//useParam을 어떻게 활용하지....?
const memberId = res.headers.location;
console.log(memberId);
//아 이걸 useParam써서 메인으로 보내자
Comment on lines +23 to +27
Copy link
Member

Choose a reason for hiding this comment

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

p5: ㅋㅋㅋㅋ 생각의 흐름이 주석에 남아있는게 좋네요 ㅋㅋ console 만 지워주시면 좋을 것 같습니다.

Copy link
Member

Choose a reason for hiding this comment

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

p5: ㅋㅋㅋㅋ 너무 멋져요


alert(res.data.message);
//to main page
navi(`/${memberId}`);
})
.catch((error) => alert(error.response.data.message));
} catch {
//error
}
}
};

return (
<Area>
<h1>Login</h1>
<IMG src={loginImg} alt="loginImg" />
<InputContaier>
<InputSort>ID</InputSort>
<div style={{width: '100%'}}>
<Input
onChange={(e) => setId(e.currentTarget.value)}
Copy link
Member

Choose a reason for hiding this comment

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

p5: 저는 e.target.value로 사용했는데 차이점을 알고 계시나요?
한 번 참고하시길 바랍니다!

https://velog.io/@sunkim/Javascript-e.target%EA%B3%BC-e.currentTarget%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90

type="text"
placeholder="아이디를 입력하세요"
/>
{!id && <HelpP>아이디를 입력하세요</HelpP>}
Comment on lines +45 to +52

Choose a reason for hiding this comment

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

p4) 혹시 div style옆 width무슨 의미인지 설명해주실 수 있을까여?! 인라인스타일이면 담부터 지양하시는게 좋을 거같아여~

Copy link
Member

Choose a reason for hiding this comment

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

pr에 작성해주신 고민이 이 부분이네요.

간단한 스타일의 경우 사실 styled component를 추가로 만드는 것이 비효율 적으로 보일 수는 있지만, 나중에 유지보수를 하거나 스타일을 변경해야 하는 상황을 생각해보면, 스타일 코드가 여기저기에 나뉘어져 있다면, 유지보수할 때의 난이도가 굉장히 올라간다고 생각합니다. 따라서 조금 비효율적으로 보일진 몰라도, styled component를 사용하는 프로젝트라면 모든 스타일을 styled로 주는 것이 좋을 것 같습니다.

태그이름은 개인적 규칙이나, 팀의 컨벤션에 맞게 작성하셔야하지만 PR에 물어보셔서 답변해드리자면 InputWrapper등의 이름으로 감싸주면 될 것 같습니다.

Copy link
Member

Choose a reason for hiding this comment

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

p5: 저도 위 생각에 동의합니다. 스타일 코드가 이렇게 나뉘어져있으면 유지보수가 힘들어 질 수 있어요!

아래 링크와 같이 본인 스스로의 규칙을 만들면 좋아요! 그리고 그 규칙들을 협업하는 팀원들과 공유한다면 더 좋을 것 같아요!

https://velog.io/@hayoung474/Front-End-%EB%B3%B5%EC%9E%A1%ED%95%9C-styled-components-%EA%B5%AC%EC%A1%B0-%EA%B0%9C%EC%84%A0%ED%95%B4%EB%B3%B4%EA%B8%B0

</div>
</InputContaier>
<InputContaier>
<InputSort>PW</InputSort>
<div style={{width: '100%'}}>
<Input
onChange={(e) => setPw(e.currentTarget.value)}
type="password"
placeholder="비밀번호를 입력하세요"
/>
{!pw && <HelpP>비밀번호를 입력해주세요 제발</HelpP>}
Copy link
Member

Choose a reason for hiding this comment

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

p5: pw state값에 따라 메시지 띄워주는거 좋네요!

</div>
</InputContaier>
<div>
<MoveButton onClick={handleLogin}>로그인</MoveButton>
<Link to={'/signup'}>
<MoveButton>회원가입</MoveButton>
</Link>
</div>
</Area>
);
}
33 changes: 33 additions & 0 deletions week4/week4-Login/src/page/MainPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {Link, useParams} from 'react-router-dom';
import {Header, MoveButton, Section} from '../style/styleComponents';
import ReactPlayer from 'react-player';

function MainPage() {
const {memberId} = useParams<string>();

console.log(memberId);
Copy link
Member

Choose a reason for hiding this comment

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

p4: 테스트 끝난 console.log는 삭제해주세요~

return (
<div>
<Header>보운이의 로그인</Header>
<Section>
Comment on lines +10 to +12
Copy link
Member

Choose a reason for hiding this comment

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

p5: 가장 div가 딱히 스타일도 없고, 의미가 없는 태그라면, div대신 <></>로 감싸주는건 어떨까요?

<ReactPlayer url={'/videos/고양이.mp4'} playing={true} loop={true} muted={true} />
Copy link
Member

Choose a reason for hiding this comment

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

p5: ReactPlayer사용해서 동영상 넣으셨군요 좋네요!

<div>
{memberId ? (
<Link to={`/mypage/${memberId}`}>
<MoveButton>내 정보</MoveButton>
</Link>
) : (
<Link to={'/login'}>
<MoveButton>로그인</MoveButton>
</Link>
)}
<Link to={'/signup'}>
<MoveButton>회원가입</MoveButton>
</Link>
</div>
</Section>
</div>
);
}

export default MainPage;
88 changes: 88 additions & 0 deletions week4/week4-Login/src/page/MyPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {useEffect, useState} from 'react';
import {Area, Info, MoveButton, OneLine, PwEditBtn, ShowORNot} from '../style/styleComponents';
import {Link, useParams} from 'react-router-dom';
import axios from 'axios';
import {BASE_URL} from '../assets/base-url';
import PwEditComp from './PwEditComp';

type Info = {
id: string;
nickname: string;
phone: string;
};
Comment on lines +1 to +12

Choose a reason for hiding this comment

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

p4)코드를 각각 구조에 맞게 잘 나누신 것 같아여


export default function MyPage() {
const {memberId} = useParams<string>();
const [info, setInfo] = useState<Info>();

useEffect(() => {
//memberId로
try {
axios
.get(`${BASE_URL}/member/info`, {
headers: {
memberId: memberId,
},
})
.then((res) => {
const myInfo: Info = {
id: res.data.data.authenticationId,
nickname: res.data.data.nickname,
phone: res.data.data.phone,
};
setInfo(myInfo);
console.log(myInfo);
})
.catch((error) => {
alert(error.response.data.message);
console.log(error);
});
} catch {
//error
}
}, []);

function handleShowPw() {
const nowState = document.getElementById('showornot')!.style.visibility;
if (nowState == 'hidden') {
//숨겨뒀다가 열려고 누름 -> 보여야함
document.getElementById('showornot')!.style.visibility = 'visible';
} else {
document.getElementById('showornot')!.style.visibility = 'hidden';
}
}

Comment on lines +45 to +54

Choose a reason for hiding this comment

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

p4) 비밀번호 여닫는 폼을 이렇게도 구현할 수 있군여 배워갑니다.

Copy link
Member

Choose a reason for hiding this comment

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

P3: 리액트에서 DOM에 직접접근하여 조작하는 것은 권장되지 않는 방식입니다. state값을 styled 컴포넌트에 인자로 전달에서 인자에 따라 스타일 값을 바꿔주거나, DOM을 직접 조작해야한다면 useRef를 사용하여 조작하는 것이 나을 것 같습니다.

혹시 더 좋은 방법이 있다면 알려주시면 감사하겠습니다.

return (
<>
Copy link
Member

Choose a reason for hiding this comment

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

여기도 빈 태그 빼면 좋을 것 같아요!

<Area>
<h1>마이페이지</h1>
<section>
<OneLine>
<Info>ID</Info>
<Info>{info?.id}</Info>
</OneLine>
<OneLine>
<Info>닉네임</Info>
<Info>{info?.nickname}</Info>
</OneLine>
<OneLine>
<Info>전화번호</Info>
<Info>{info?.phone}</Info>
</OneLine>
</section>
<section>
<div style={{display: 'flex', gap: '1rem'}}>
<p>비밀번호 변경</p>
<PwEditBtn onClick={handleShowPw}>{'>'}</PwEditBtn>
</div>
<ShowORNot id="showornot">
<PwEditComp props={memberId!} />
Copy link
Member

Choose a reason for hiding this comment

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

p3: 컴포넌트에 전달하는 인자이름을 props로 하기보다는 변수에 맞는 변수명으로 넘겨주는 것이 좋을것 같습니다!

Copy link
Member

Choose a reason for hiding this comment

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

p5: memberId뒤에 ! 를 붙인 이유가 있으실까요? 에러가 나서 그냥 추가하신 거라면, 사용하는 쪽에서 null 체크를 하는 것으로는 해결이 안되나요?
실제로 url에 id 가 없으면 memberId가 빈 값일 수도 있을 것 같아 여쭤봅니다!

</ShowORNot>
</section>
<Link to={`/${memberId}`}>
<MoveButton>홈으로</MoveButton>
</Link>
</Area>
</>
);
}
Loading