ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -1,8 +1,100 @@
 import React from 'react';
+import { withRouter } from 'react-router-dom';
+import './Login.scss';
+
+class Login extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      id: '',
+      pw: '',
+    };
+  }
+
+  handleInput = e => {
+    const { value, name } = e.target;
+    this.setState({
+      [name]: value,
+    });
+  };
+
+  goToMain = e => {
+    fetch('http://10.58.0.100:8000/users/signin', {
+      method: 'POST',
+      body: JSON.stringify({
+        email: this.state.id,
+        password: this.state.pw,
+        nick_name: '이의연',
+        phonenumber: '01012345678',
+      }),
+    })
+      .then(response => response.json())
+      .then(result => {
+        if (result.message === 'SUCCESS') {
+          this.props.history.push('/MainEuiyeon');
+        } else {
+          alert('아이디 및 비밀번호를 확인하세요!');
+        }
+      });
+  };
 
-class LoginEuiyeon extends React.Component {
   render() {
-    return <div>11</div>;
+    return (
+      <div class="Login">
+        <section className="loginBox">
+          <div className="logo">
+            <div className="logoFont">Westagram</div>
+          </div>
+
+          <form className="loginForm">
+            <div className="inputWrap">
+              <div className="inputId">
+                <input
+                  className="input"
+                  id="idInput"
+                  type="text"
+                  name="id"
+                  placeholder="전화번호, 사용자 이름 또는 이메일"
+                  onKeyUp={this.checkValid}
+                  onChange={this.handleInput}
+                />
+              </div>
+              <div className="inputPassword">
+                <input
+                  className="input"
+                  id="pwInput"
+                  type="password"
+                  name="pw"
+                  placeholder="비밀번호 (6자리 이상)"
+                  onKeyUp={this.checkValid}
+                  onChange={this.handleInput}
+                />
+              </div>
+            </div>
+
+            <div className="buttonWrap">
+              <button
+                className={
+                  this.state.id.includes('@') && this.state.pw.length >= 6
+                    ? 'loginBtn'
+                    : 'loginBtn_disabled'
+                }
+                type="button"
+                onClick={this.goToMain}
+              >
+                {' '}
+                로그인{' '}
+              </button>
+            </div>
+          </form>
+
+          <div className="forgotText">
+            <a className="forgotPassword">비밀번호를 잊으셨나요?</a>
+          </div>
+        </section>
+      </div>
+    );
   }
 }
-export default LoginEuiyeon;
+
+export default withRouter(Login);

리뷰: - variable.scss 는 scss 파일에서 사용하는 것이기 때문에 js 에서 import 를 하는 것이 의미가 없습니다.
- scss 파일에서 변수를 사용하는 경우에 import 해주세요!
@@ -1,8 +1,100 @@
 import React from 'react';
+import { withRouter } from 'react-router-dom';
+import './Login.scss';
+
+class Login extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      id: '',
+      pw: '',
+    };
+  }
+
+  handleInput = e => {
+    const { value, name } = e.target;
+    this.setState({
+      [name]: value,
+    });
+  };
+
+  goToMain = e => {
+    fetch('http://10.58.0.100:8000/users/signin', {
+      method: 'POST',
+      body: JSON.stringify({
+        email: this.state.id,
+        password: this.state.pw,
+        nick_name: '이의연',
+        phonenumber: '01012345678',
+      }),
+    })
+      .then(response => response.json())
+      .then(result => {
+        if (result.message === 'SUCCESS') {
+          this.props.history.push('/MainEuiyeon');
+        } else {
+          alert('아이디 및 비밀번호를 확인하세요!');
+        }
+      });
+  };
 
-class LoginEuiyeon extends React.Component {
   render() {
-    return <div>11</div>;
+    return (
+      <div class="Login">
+        <section className="loginBox">
+          <div className="logo">
+            <div className="logoFont">Westagram</div>
+          </div>
+
+          <form className="loginForm">
+            <div className="inputWrap">
+              <div className="inputId">
+                <input
+                  className="input"
+                  id="idInput"
+                  type="text"
+                  name="id"
+                  placeholder="전화번호, 사용자 이름 또는 이메일"
+                  onKeyUp={this.checkValid}
+                  onChange={this.handleInput}
+                />
+              </div>
+              <div className="inputPassword">
+                <input
+                  className="input"
+                  id="pwInput"
+                  type="password"
+                  name="pw"
+                  placeholder="비밀번호 (6자리 이상)"
+                  onKeyUp={this.checkValid}
+                  onChange={this.handleInput}
+                />
+              </div>
+            </div>
+
+            <div className="buttonWrap">
+              <button
+                className={
+                  this.state.id.includes('@') && this.state.pw.length >= 6
+                    ? 'loginBtn'
+                    : 'loginBtn_disabled'
+                }
+                type="button"
+                onClick={this.goToMain}
+              >
+                {' '}
+                로그인{' '}
+              </button>
+            </div>
+          </form>
+
+          <div className="forgotText">
+            <a className="forgotPassword">비밀번호를 잊으셨나요?</a>
+          </div>
+        </section>
+      </div>
+    );
   }
 }
-export default LoginEuiyeon;
+
+export default withRouter(Login);

리뷰: - 두 함수는 하는 역할이 비슷하기 때문에 충분히 하나의 함수로 합쳐볼 수 있을 것 같습니다.
- Refactoring CheckList 참고해서 수정해 보세요!
@@ -1,8 +1,100 @@
 import React from 'react';
+import { withRouter } from 'react-router-dom';
+import './Login.scss';
+
+class Login extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      id: '',
+      pw: '',
+    };
+  }
+
+  handleInput = e => {
+    const { value, name } = e.target;
+    this.setState({
+      [name]: value,
+    });
+  };
+
+  goToMain = e => {
+    fetch('http://10.58.0.100:8000/users/signin', {
+      method: 'POST',
+      body: JSON.stringify({
+        email: this.state.id,
+        password: this.state.pw,
+        nick_name: '이의연',
+        phonenumber: '01012345678',
+      }),
+    })
+      .then(response => response.json())
+      .then(result => {
+        if (result.message === 'SUCCESS') {
+          this.props.history.push('/MainEuiyeon');
+        } else {
+          alert('아이디 및 비밀번호를 확인하세요!');
+        }
+      });
+  };
 
-class LoginEuiyeon extends React.Component {
   render() {
-    return <div>11</div>;
+    return (
+      <div class="Login">
+        <section className="loginBox">
+          <div className="logo">
+            <div className="logoFont">Westagram</div>
+          </div>
+
+          <form className="loginForm">
+            <div className="inputWrap">
+              <div className="inputId">
+                <input
+                  className="input"
+                  id="idInput"
+                  type="text"
+                  name="id"
+                  placeholder="전화번호, 사용자 이름 또는 이메일"
+                  onKeyUp={this.checkValid}
+                  onChange={this.handleInput}
+                />
+              </div>
+              <div className="inputPassword">
+                <input
+                  className="input"
+                  id="pwInput"
+                  type="password"
+                  name="pw"
+                  placeholder="비밀번호 (6자리 이상)"
+                  onKeyUp={this.checkValid}
+                  onChange={this.handleInput}
+                />
+              </div>
+            </div>
+
+            <div className="buttonWrap">
+              <button
+                className={
+                  this.state.id.includes('@') && this.state.pw.length >= 6
+                    ? 'loginBtn'
+                    : 'loginBtn_disabled'
+                }
+                type="button"
+                onClick={this.goToMain}
+              >
+                {' '}
+                로그인{' '}
+              </button>
+            </div>
+          </form>
+
+          <div className="forgotText">
+            <a className="forgotPassword">비밀번호를 잊으셨나요?</a>
+          </div>
+        </section>
+      </div>
+    );
   }
 }
-export default LoginEuiyeon;
+
+export default withRouter(Login);

리뷰: - isActive 는 id 와 pw 로 계산할 수 있는 값이이기 때문에 state 로 관리할 필요가 없어 보입니다! 
- 아래 공식 문서 참고하셔서 어떤 값들이 state 로 적절하지 않은지 파악해보시기 바랍니다!
https://www.notion.so/wecode/Westagram-React-Refactoring-Checklist-aea297cf88ed4601b769e4b2c2cfd4e1#089493d6bfca438aa328226e327cff92
@@ -1,8 +1,100 @@
 import React from 'react';
+import { withRouter } from 'react-router-dom';
+import './Login.scss';
+
+class Login extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      id: '',
+      pw: '',
+    };
+  }
+
+  handleInput = e => {
+    const { value, name } = e.target;
+    this.setState({
+      [name]: value,
+    });
+  };
+
+  goToMain = e => {
+    fetch('http://10.58.0.100:8000/users/signin', {
+      method: 'POST',
+      body: JSON.stringify({
+        email: this.state.id,
+        password: this.state.pw,
+        nick_name: '이의연',
+        phonenumber: '01012345678',
+      }),
+    })
+      .then(response => response.json())
+      .then(result => {
+        if (result.message === 'SUCCESS') {
+          this.props.history.push('/MainEuiyeon');
+        } else {
+          alert('아이디 및 비밀번호를 확인하세요!');
+        }
+      });
+  };
 
-class LoginEuiyeon extends React.Component {
   render() {
-    return <div>11</div>;
+    return (
+      <div class="Login">
+        <section className="loginBox">
+          <div className="logo">
+            <div className="logoFont">Westagram</div>
+          </div>
+
+          <form className="loginForm">
+            <div className="inputWrap">
+              <div className="inputId">
+                <input
+                  className="input"
+                  id="idInput"
+                  type="text"
+                  name="id"
+                  placeholder="전화번호, 사용자 이름 또는 이메일"
+                  onKeyUp={this.checkValid}
+                  onChange={this.handleInput}
+                />
+              </div>
+              <div className="inputPassword">
+                <input
+                  className="input"
+                  id="pwInput"
+                  type="password"
+                  name="pw"
+                  placeholder="비밀번호 (6자리 이상)"
+                  onKeyUp={this.checkValid}
+                  onChange={this.handleInput}
+                />
+              </div>
+            </div>
+
+            <div className="buttonWrap">
+              <button
+                className={
+                  this.state.id.includes('@') && this.state.pw.length >= 6
+                    ? 'loginBtn'
+                    : 'loginBtn_disabled'
+                }
+                type="button"
+                onClick={this.goToMain}
+              >
+                {' '}
+                로그인{' '}
+              </button>
+            </div>
+          </form>
+
+          <div className="forgotText">
+            <a className="forgotPassword">비밀번호를 잊으셨나요?</a>
+          </div>
+        </section>
+      </div>
+    );
   }
 }
-export default LoginEuiyeon;
+
+export default withRouter(Login);

리뷰: - isActive 를 state 로 관리할 필요 없이, 여기서 바로 true / false 를 계산하면 될 것 같습니다!
@@ -1,3 +1,106 @@
-*{
-  margin: 0;  
-}
\ No newline at end of file
+@import '../../../styles/variable.scss';
+
+.Login {
+  @include flexCenter;
+  flex-direction: column;
+  align-items: center;
+  height: 100vh;
+
+  .loginBox {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    border: $default-border;
+    width: 430px;
+
+    .logo {
+      @include flexCenter;
+      align-items: center;
+      margin-top: 60px;
+
+      .logoFont {
+        font-size: 50px;
+        font-family: 'Lobster';
+      }
+    }
+
+    .loginForm {
+      display: flex;
+      flex-direction: column;
+      justify-content: space-around;
+      align-items: center;
+      margin-top: 80px;
+
+      .inputWrap {
+        display: flex;
+        flex-direction: column;
+        justify-content: space-evenly;
+        align-items: center;
+        height: 50%;
+        width: 80%;
+
+        .inputId,
+        .inputPassword {
+          width: 100%;
+        }
+
+        input {
+          width: 100%;
+          height: 45px;
+          margin-bottom: 15px;
+          padding: 2px 10px;
+          border-radius: 5px;
+          background-color: #eeeeef;
+          border: $default-border;
+          font-size: inherit;
+        }
+      }
+
+      .buttonWrap {
+        @include flexCenter;
+        flex-direction: column;
+        align-items: center;
+        width: 100%;
+        height: 40%;
+        margin-top: 25px;
+
+        .loginBtn {
+          width: 80%;
+          height: 45px;
+          border-radius: 5px;
+          border: transparent;
+          background-color: $btn-color-active;
+          /* background-color: #b2dffc; */
+          color: white;
+          font-size: 20px;
+          padding-top: 4px;
+        }
+
+        .loginBtn_disabled {
+          width: 80%;
+          height: 45px;
+          border-radius: 5px;
+          border: transparent;
+          background-color: $btn-color-disable;
+          color: white;
+          font-size: 20px;
+          padding-top: 4px;
+        }
+      }
+    }
+
+    .forgotText {
+      display: flex;
+      flex-direction: column;
+      justify-content: flex-end;
+      align-items: center;
+      margin: 80px 0 30px 0;
+
+      .forgotPassword {
+        text-align: end;
+        margin-bottom: 20px;
+        color: #2c5581;
+      }
+    }
+  }
+}

리뷰: - css 작업을 하실때 바깥 요소에 특정한 width / height 값을 부여하시는 것 보다, 바깥 요소의 크기는 내용물의 크기 + margin / padding 들의 합으로 자연스럽게 크기가 결정되도록 하시는 게 더 좋습니다.
- 항상 bottom up 방식으로 스타일링 하는 습관을 들여주세요!
@@ -0,0 +1,26 @@
+import React from 'react';
+import './Aside.scss';
+
+import ProfileWrap from './ProfileWrap/ProfileWrap';
+import StoryBox from './StoryBox/StoryBox';
+import RecommendBox from './RecommendBox/RecommendBox';
+import WestaInfoBox from './WestaInfoBox/WestaInfoBox';
+
+class Aside extends React.Component {
+  render() {
+    return (
+      <aside className="sideWrapper">
+        <div className="sidebar">
+          <div className="profile_bar">
+            <ProfileWrap />
+            <StoryBox />
+            <RecommendBox />
+            <WestaInfoBox />
+          </div>
+        </div>
+      </aside>
+    );
+  }
+}
+
+export default Aside;

리뷰: - Import 순서 수정해주세요! 일반적인 convention을 따르는 이유도 있지만 순서만 잘 지켜주셔도 가독성이 좋아집니다. 아래 순서 참고해주세요.
- React → Library(Package) → Component → 변수 / 이미지 → css 파일(scss 파일)
```suggestion
import React from 'react';
import ProfileWrap from './ProfileWrap/ProfileWrap';
import StoryBox from './StoryBox/StoryBox';
import RecommendBox from './RecommendBox/RecommendBox';
import WestaInfoBox from './WestaInfoBox/WestaInfoBox';
import './Aside.scss';
```
@@ -0,0 +1,56 @@
+import React from 'react';
+import './Content.scss';
+
+import Feed from './Feed/Feed';
+import Aside from './Aside/Aside';
+
+class Content extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      feeds: [],
+    };
+  }
+
+  componentDidMount() {
+    fetch('http://localhost:3000/data/feedData.json', {
+      method: 'GET',
+    })
+      .then(res => res.json())
+      .then(data => {
+        this.setState({
+          feeds: data,
+        });
+      });
+  }
+
+  render() {
+    return (
+      <div class="Main">
+        <main>
+          <div className="container">
+            <section className="articleWrapper">
+              {this.state.feeds.map(e => (
+                <Feed
+                  feed_id={e.feed_id}
+                  profile_img={e.profile_img}
+                  profile_id={e.profile_id}
+                  feed_img={e.feed_img}
+                  like_click={e.like_click}
+                  like_user_profile_img={e.like_user_profile_img}
+                  like_user_profile_id={e.like_user_profile_id}
+                  like_num={e.like_num}
+                  post_user_mension={e.post_user_mension}
+                  comments={e.comments}
+                />
+              ))}
+            </section>
+            <Aside />
+          </div>
+        </main>
+      </div>
+    );
+  }
+}
+
+export default Content;

리뷰: - `http://localhost:3000` 은 생략 가능합니다. 포트 번호가 달라지면(ex. `localhost:3001`) fetch 함수를 일일이 수정해주어야 하기 때문에 유지보수가 어려워집니다. 아래 코드 참고해서 수정해주세요!
```jsx
const foo = () => {
	// fetch("http://localhost:3000/images/1")
	fetch("/images/1")
}
```
- fetch함수의 `get method`는 method의 default 값입니다. 따라서 생략이 가능합니다. 
```jsx
const foo = () => {
    fetch(`${cartAPI}/quantity`)
    .then((res) => res.json())
```
@@ -0,0 +1,56 @@
+import React from 'react';
+import './Content.scss';
+
+import Feed from './Feed/Feed';
+import Aside from './Aside/Aside';
+
+class Content extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      feeds: [],
+    };
+  }
+
+  componentDidMount() {
+    fetch('http://localhost:3000/data/feedData.json', {
+      method: 'GET',
+    })
+      .then(res => res.json())
+      .then(data => {
+        this.setState({
+          feeds: data,
+        });
+      });
+  }
+
+  render() {
+    return (
+      <div class="Main">
+        <main>
+          <div className="container">
+            <section className="articleWrapper">
+              {this.state.feeds.map(e => (
+                <Feed
+                  feed_id={e.feed_id}
+                  profile_img={e.profile_img}
+                  profile_id={e.profile_id}
+                  feed_img={e.feed_img}
+                  like_click={e.like_click}
+                  like_user_profile_img={e.like_user_profile_img}
+                  like_user_profile_id={e.like_user_profile_id}
+                  like_num={e.like_num}
+                  post_user_mension={e.post_user_mension}
+                  comments={e.comments}
+                />
+              ))}
+            </section>
+            <Aside />
+          </div>
+        </main>
+      </div>
+    );
+  }
+}
+
+export default Content;

리뷰: - mock up 데이터의 키 값은 스네이크 케이스로 사용해주셔도 되지만 (백엔드에서는 보통 스네이크 케이스를 쓰기 때문에) props 의 이름은 카멜 케이스로 통일해 주세요!
@@ -1,3 +1,5 @@
-import date from './date.svg';
-export * from './Eyes';
+import date from "./date.svg";
+export * from "./Eyes";
 export { date };
+import Logo from "./Logo.svg";
+export { Logo };

리뷰: svg는 import logo from './logo.svg'; export {logo}; 이런 식으로 해주어야할텐데 지금 정상 작동하시나요?
그리고 이미지는 소문자로 네이밍하는 것이 좋습니다.
@@ -0,0 +1,65 @@
+import styled from "styled-components";
+import { Logo } from "../../assets";
+import { useState } from "react";
+import { LoginBtn } from "../header/LoginBtn";
+import { font } from "../../theme";
+
+export const Header = () => {
+  const [isLogined, setIsLogined] = useState<boolean>(false);
+
+  return (
+    <Container>
+      {isLogined && (
+        <>
+          <img src={Logo} alt={"logo"} />
+          <Box>
+            <LeftBox>
+              <p>학생봉사 시간 조회/부여</p>
+              <p>봉사활동 신청 조회/생성</p>
+              <p>봉사 일정 확인</p>
+              <p>알림 생성</p>
+            </LeftBox>
+            <RightBox>
+              <p>마이페이지</p>
+              <LoginBtn isLogined={isLogined} />
+            </RightBox>
+          </Box>
+        </>
+      )}
+      {!isLogined && (
+        <Box>
+          <img src={Logo} alt={"logo"} />
+          <LoginBtn isLogined={isLogined} />
+        </Box>
+      )}
+    </Container>
+  );
+};
+
+const Container = styled.div`
+  width: 100vw;
+  height: 70px;
+  display: flex;
+  align-items: center;
+  padding: 0 90px;
+  gap: 82.5px;
+  font: ${font.Body3};
+`;
+
+const Box = styled.div`
+  width: 100%;
+  display: flex;
+  justify-content: space-between;
+`;
+
+const LeftBox = styled.div`
+  display: flex;
+  gap: 82.5px;
+  align-items: center;
+`;
+
+const RightBox = styled.div`
+  display: flex;
+  align-items: center;
+  gap: 82.5px;
+`;

리뷰: 이건 왜 이렇게 불러오시나용
@@ -1,10 +1,94 @@
 import React from 'react';
+import { Link } from 'react-router-dom';
+
+import './Login.scss';
 
 class Login extends React.Component {
+  constructor() {
+    super();
+    this.state = {
+      loginId: '',
+      loginPassword: '',
+    };
+  }
+
+  handleLoginInput = e => {
+    const { value, name } = e.target;
+    this.setState({
+      [name]: value,
+    });
+  };
+
+  handleLogin = () => {
+    fetch('http://10.58.0.84:8000/users/login', {
+      method: 'POST',
+      body: JSON.stringify({
+        email: this.state.loginId,
+        password: this.state.loginPassword,
+      }),
+    })
+      .then(response => response.json())
+      .then(result => console.log('결과: ', result));
+  };
+
+  // handleLogin = () => {
+  //   fetch('http://10.58.0.84:8000/users/signup', {
+  //     method: 'POST',
+  //     body: JSON.stringify({
+  //       name: '김영호',
+  //       email: this.state.loginId,
+  //       password: this.state.loginPassword,
+  //       phone_number: '01012345678',
+  //       date_of_birth: '1995-07-07',
+  //       gender: 'M',
+  //       address: 'Seoul',
+  //     }),
+  //   })
+  //     .then(response => response.json())
+  //     .then(result => console.log('결과: ', result));
+  // };
+
   render() {
+    const { checkIdPassword, handleLoginInput } = this;
+    const { loginId, loginPassword } = this.state;
+
+    const condition =
+      loginId.length >= 5 && loginPassword.length >= 5 && loginId.includes('@');
+
     return (
       <div>
-        <h3>로그인</h3>
+        <div className="container">
+          <header className="header">Westagram</header>
+          <form className="loginForm" onKeyUp={checkIdPassword}>
+            <input
+              id="id"
+              name="loginId"
+              type="text"
+              placeholder="전화번호, 사용자 이름 또는 이메일"
+              onChange={handleLoginInput}
+            />
+            <input
+              id="password"
+              name="loginPassword"
+              type="password"
+              placeholder="비밀번호"
+              onChange={handleLoginInput}
+            />
+            <Link to="/main">
+              <button
+                onClick={this.handleLogin}
+                className={condition ? 'buttonActivate' : 'buttonDisabled'}
+                id="loginButton"
+                disabled={condition ? false : true}
+              >
+                로그인
+              </button>
+            </Link>
+          </form>
+          <a href="#!" className="findPassword">
+            비밀번호를 잊으셨나요?
+          </a>
+        </div>
       </div>
     );
   }

리뷰: 삼항연산자 사용을 잘 하신거 같습니다.