ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,46 @@
+@import url('https://fonts.googleapis.com/css2?family=Lobster&display=swap');
+@import '../../../styles/variable.scss';
+
+.Login {
+  .container {
+    width: 2000px;
+    max-width: 100vw;
+
+    .loginContainer {
+      width: 350px;
+      height: 400px;
+      margin: 25vh auto;
+      border: 2px solid lightgrey;
+      text-align: center;
+
+      p {
+        margin: 50px auto;
+        font-family: 'Lobster';
+        font-size: 40px;
+      }
+
+      .inputId {
+        @include idpwContainer;
+      }
+
+      .inputPassword {
+        @include idpwContainer;
+      }
+
+      .loginButtonOn {
+        @include loginButton;
+        background-color: blue;
+      }
+
+      .loginButtonOff {
+        @include loginButton;
+        background-color: skyblue;
+      }
+
+      a {
+        text-decoration: none;
+        color: blue;
+      }
+    }
+  }
+}

리뷰: - common.scss 에 적합하는 것 같습니다!
@@ -0,0 +1,46 @@
+@import url('https://fonts.googleapis.com/css2?family=Lobster&display=swap');
+@import '../../../styles/variable.scss';
+
+.Login {
+  .container {
+    width: 2000px;
+    max-width: 100vw;
+
+    .loginContainer {
+      width: 350px;
+      height: 400px;
+      margin: 25vh auto;
+      border: 2px solid lightgrey;
+      text-align: center;
+
+      p {
+        margin: 50px auto;
+        font-family: 'Lobster';
+        font-size: 40px;
+      }
+
+      .inputId {
+        @include idpwContainer;
+      }
+
+      .inputPassword {
+        @include idpwContainer;
+      }
+
+      .loginButtonOn {
+        @include loginButton;
+        background-color: blue;
+      }
+
+      .loginButtonOff {
+        @include loginButton;
+        background-color: skyblue;
+      }
+
+      a {
+        text-decoration: none;
+        color: blue;
+      }
+    }
+  }
+}

리뷰: - mixin 은 variable.scss 와 같은 별도의 파일을 하나 더 만들어서 그곳에서 일괄적으로 관리해주세요!
@@ -0,0 +1,46 @@
+@import url('https://fonts.googleapis.com/css2?family=Lobster&display=swap');
+@import '../../../styles/variable.scss';
+
+.Login {
+  .container {
+    width: 2000px;
+    max-width: 100vw;
+
+    .loginContainer {
+      width: 350px;
+      height: 400px;
+      margin: 25vh auto;
+      border: 2px solid lightgrey;
+      text-align: center;
+
+      p {
+        margin: 50px auto;
+        font-family: 'Lobster';
+        font-size: 40px;
+      }
+
+      .inputId {
+        @include idpwContainer;
+      }
+
+      .inputPassword {
+        @include idpwContainer;
+      }
+
+      .loginButtonOn {
+        @include loginButton;
+        background-color: blue;
+      }
+
+      .loginButtonOff {
+        @include loginButton;
+        background-color: skyblue;
+      }
+
+      a {
+        text-decoration: none;
+        color: blue;
+      }
+    }
+  }
+}

리뷰: - 스타일링을 부여하기 위함으로는 className 으로도 충분합니다. id 를 사용하실 이유가 없습니다.
@@ -0,0 +1,80 @@
+import React from 'react';
+import Comment from './Comment';
+import './CommentList.scss';
+
+class CommentList extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      commentInput: '',
+      newComment: [],
+      nickname: '',
+      commentList: [],
+      commentValue: '',
+    };
+  }
+
+  componentDidMount() {
+    fetch('http://localhost:3000/data/commentData.json', {
+      method: 'GET', // GET method는 기본값이라서 생략이 가능합니다.
+    }) // 예시코드에서는 이해를 돕기 위해 명시적으로 기입해뒀습니다.
+      .then(res => res.json())
+      .then(data => {
+        this.setState({
+          commentList: data,
+        });
+      });
+  }
+
+  checkInput = e => {
+    this.setState({
+      commentInput: e.target.value,
+    });
+  };
+
+  inputToComment = () => {
+    const { newComment, commentInput } = this.state;
+    this.setState({
+      nickname: 'wecode_bootcamp',
+      newComment: newComment.concat(commentInput),
+    });
+  };
+
+  enterPress = e => {
+    if (e.key === 'Enter') {
+      this.inputToComment();
+    }
+    e.target.value = '';
+  };
+
+  render() {
+    const { commentValue, commentList } = this.state;
+    return (
+      <div className="commentList">
+        {commentList.map(comment => {
+          return (
+            <Comment
+              key={comment.id}
+              nickname={comment.userName}
+              comment={comment.content}
+            />
+          );
+        })}
+
+        <div className="newText">
+          <input
+            id="typingText"
+            value={commentValue}
+            onChange={this.checkInput}
+            onKeyPress={this.enterPress}
+            type="text"
+            placeholder="댓글 달기...."
+          />
+          <button onClick={this.checkInput}>게시</button>
+        </div>
+      </div>
+    );
+  }
+}
+
+export default CommentList;

리뷰: 적용완료~! 다슬님 최고!
@@ -0,0 +1,23 @@
+import React from 'react';
+import './Comment.scss';
+
+class NewComment extends React.Component {
+  render() {
+    // const newArray = this.props.newComment.map((commentarray, index) => (
+    //   <li key={index}>
+    //     <span className="newCommentid">{this.props.nickname}</span>
+    //     <span className="newComments">{commentarray}</span>
+    //   </li>
+    // ));
+    return (
+      <div className="comment">
+        <div className="newComment">
+          <span className="newCommentid">{this.props.nickname}</span>
+          <span className="newComments">{this.props.comment}</span>
+        </div>
+      </div>
+    );
+  }
+}
+
+export default NewComment;

리뷰: 지웠습니다!
@@ -0,0 +1,15 @@
+.comment {
+  .newComment {
+    margin-bottom: 5px;
+  }
+
+  .newCommentid {
+    font-weight: bold;
+    margin-bottom: 0;
+  }
+
+  .newComments {
+    font-weight: normal;
+    margin-left: 5px;
+  }
+}

리뷰: 수정했습니다!
@@ -0,0 +1,80 @@
+import React from 'react';
+import Comment from './Comment';
+import './CommentList.scss';
+
+class CommentList extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      commentInput: '',
+      newComment: [],
+      nickname: '',
+      commentList: [],
+      commentValue: '',
+    };
+  }
+
+  componentDidMount() {
+    fetch('http://localhost:3000/data/commentData.json', {
+      method: 'GET', // GET method는 기본값이라서 생략이 가능합니다.
+    }) // 예시코드에서는 이해를 돕기 위해 명시적으로 기입해뒀습니다.
+      .then(res => res.json())
+      .then(data => {
+        this.setState({
+          commentList: data,
+        });
+      });
+  }
+
+  checkInput = e => {
+    this.setState({
+      commentInput: e.target.value,
+    });
+  };
+
+  inputToComment = () => {
+    const { newComment, commentInput } = this.state;
+    this.setState({
+      nickname: 'wecode_bootcamp',
+      newComment: newComment.concat(commentInput),
+    });
+  };
+
+  enterPress = e => {
+    if (e.key === 'Enter') {
+      this.inputToComment();
+    }
+    e.target.value = '';
+  };
+
+  render() {
+    const { commentValue, commentList } = this.state;
+    return (
+      <div className="commentList">
+        {commentList.map(comment => {
+          return (
+            <Comment
+              key={comment.id}
+              nickname={comment.userName}
+              comment={comment.content}
+            />
+          );
+        })}
+
+        <div className="newText">
+          <input
+            id="typingText"
+            value={commentValue}
+            onChange={this.checkInput}
+            onKeyPress={this.enterPress}
+            type="text"
+            placeholder="댓글 달기...."
+          />
+          <button onClick={this.checkInput}>게시</button>
+        </div>
+      </div>
+    );
+  }
+}
+
+export default CommentList;

리뷰: 적용했습니다. 구조 분해 할당이 익숙하지않아 써야할 곳을 잘 구분하지 못하는것 같습니다.. ㅠ
@@ -0,0 +1,23 @@
+import React from 'react';
+import './Comment.scss';
+
+class NewComment extends React.Component {
+  render() {
+    // const newArray = this.props.newComment.map((commentarray, index) => (
+    //   <li key={index}>
+    //     <span className="newCommentid">{this.props.nickname}</span>
+    //     <span className="newComments">{commentarray}</span>
+    //   </li>
+    // ));
+    return (
+      <div className="comment">
+        <div className="newComment">
+          <span className="newCommentid">{this.props.nickname}</span>
+          <span className="newComments">{this.props.comment}</span>
+        </div>
+      </div>
+    );
+  }
+}
+
+export default NewComment;

리뷰: 아 이런 실수를 ... 수정했습니다!
@@ -0,0 +1,80 @@
+import React from 'react';
+import Comment from './Comment';
+import './CommentList.scss';
+
+class CommentList extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      commentInput: '',
+      newComment: [],
+      nickname: '',
+      commentList: [],
+      commentValue: '',
+    };
+  }
+
+  componentDidMount() {
+    fetch('http://localhost:3000/data/commentData.json', {
+      method: 'GET', // GET method는 기본값이라서 생략이 가능합니다.
+    }) // 예시코드에서는 이해를 돕기 위해 명시적으로 기입해뒀습니다.
+      .then(res => res.json())
+      .then(data => {
+        this.setState({
+          commentList: data,
+        });
+      });
+  }
+
+  checkInput = e => {
+    this.setState({
+      commentInput: e.target.value,
+    });
+  };
+
+  inputToComment = () => {
+    const { newComment, commentInput } = this.state;
+    this.setState({
+      nickname: 'wecode_bootcamp',
+      newComment: newComment.concat(commentInput),
+    });
+  };
+
+  enterPress = e => {
+    if (e.key === 'Enter') {
+      this.inputToComment();
+    }
+    e.target.value = '';
+  };
+
+  render() {
+    const { commentValue, commentList } = this.state;
+    return (
+      <div className="commentList">
+        {commentList.map(comment => {
+          return (
+            <Comment
+              key={comment.id}
+              nickname={comment.userName}
+              comment={comment.content}
+            />
+          );
+        })}
+
+        <div className="newText">
+          <input
+            id="typingText"
+            value={commentValue}
+            onChange={this.checkInput}
+            onKeyPress={this.enterPress}
+            type="text"
+            placeholder="댓글 달기...."
+          />
+          <button onClick={this.checkInput}>게시</button>
+        </div>
+      </div>
+    );
+  }
+}
+
+export default CommentList;

리뷰: 위에서 받아온 'wecode-bootcamp' 라는 id 값을 받아오기 위해 사용했는데, 확실히 id 라는것은 적절치 않아 nickname 으로 수정했습니다!
@@ -0,0 +1,80 @@
+import React from 'react';
+import Comment from './Comment';
+import './CommentList.scss';
+
+class CommentList extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      commentInput: '',
+      newComment: [],
+      nickname: '',
+      commentList: [],
+      commentValue: '',
+    };
+  }
+
+  componentDidMount() {
+    fetch('http://localhost:3000/data/commentData.json', {
+      method: 'GET', // GET method는 기본값이라서 생략이 가능합니다.
+    }) // 예시코드에서는 이해를 돕기 위해 명시적으로 기입해뒀습니다.
+      .then(res => res.json())
+      .then(data => {
+        this.setState({
+          commentList: data,
+        });
+      });
+  }
+
+  checkInput = e => {
+    this.setState({
+      commentInput: e.target.value,
+    });
+  };
+
+  inputToComment = () => {
+    const { newComment, commentInput } = this.state;
+    this.setState({
+      nickname: 'wecode_bootcamp',
+      newComment: newComment.concat(commentInput),
+    });
+  };
+
+  enterPress = e => {
+    if (e.key === 'Enter') {
+      this.inputToComment();
+    }
+    e.target.value = '';
+  };
+
+  render() {
+    const { commentValue, commentList } = this.state;
+    return (
+      <div className="commentList">
+        {commentList.map(comment => {
+          return (
+            <Comment
+              key={comment.id}
+              nickname={comment.userName}
+              comment={comment.content}
+            />
+          );
+        })}
+
+        <div className="newText">
+          <input
+            id="typingText"
+            value={commentValue}
+            onChange={this.checkInput}
+            onKeyPress={this.enterPress}
+            type="text"
+            placeholder="댓글 달기...."
+          />
+          <button onClick={this.checkInput}>게시</button>
+        </div>
+      </div>
+    );
+  }
+}
+
+export default CommentList;

리뷰: 지웠습니다!
@@ -1,13 +1,92 @@
 import React from 'react';
+import { withRouter } from 'react-router-dom';
+import './Login.scss';
 
 class LoginAh extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      idInput: '',
+      pwInput: '',
+    };
+  }
+
+  loginTest = () => {
+    fetch('users/login', {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      body: JSON.stringify({
+        email: this.state.idInput,
+        password: this.state.pwInput,
+      }),
+    })
+      .then(response => response.json())
+      .then(response => {
+        if (response.token) {
+          localStorage.setItem('token', response.token);
+          this.props.history.push('/MainAh');
+        } else {
+          alert('아이디/비밀번호가 틀렸습니다!');
+        }
+      });
+  };
+  handleInput = event => {
+    const { name, value } = event.target;
+    this.setState({
+      [name]: value,
+    });
+  };
+
+  goToMain = () => {
+    this.props.history.push('/MainAh');
+  };
+
   render() {
+    const { idInput, pwInput } = this.state;
+    const isButtonActive = idInput.includes('@') && pwInput.length >= 5;
     return (
-      <div>
-        <p>다슬</p>
+      <div className="Login">
+        <div className="container">
+          <div className="loginContainer">
+            <p>westagram</p>
+            <div className="idContainer">
+              <input
+                onChange={this.handleInput}
+                name="idInput"
+                type="text"
+                className="inputId"
+                placeholder="전화번호, 사용자 이름 또는 이메일"
+              />
+            </div>
+            <div className="passwordContainer">
+              <input
+                onChange={this.handleInput}
+                name="pwInput"
+                type="password"
+                className="inputPassword"
+                placeholder="비밀번호"
+              />
+            </div>
+            <button
+              disabled={!isButtonActive}
+              className={`loginButton ${
+                isButtonActive ? 'loginButtonOn' : 'loginButtonOff'
+              }`}
+              // onClick={this.goToMain}
+              onClick={this.loginTest}
+            >
+              로그인
+            </button>
+            <div>
+              <a href="google.com">비밀번호를 잊으셨나요?</a>
+            </div>
+          </div>
+        </div>
       </div>
     );
   }
 }
 
-export default LoginAh;
+export default withRouter(LoginAh);

리뷰: 수정했습니다!
@@ -1,13 +1,92 @@
 import React from 'react';
+import { withRouter } from 'react-router-dom';
+import './Login.scss';
 
 class LoginAh extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      idInput: '',
+      pwInput: '',
+    };
+  }
+
+  loginTest = () => {
+    fetch('users/login', {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      body: JSON.stringify({
+        email: this.state.idInput,
+        password: this.state.pwInput,
+      }),
+    })
+      .then(response => response.json())
+      .then(response => {
+        if (response.token) {
+          localStorage.setItem('token', response.token);
+          this.props.history.push('/MainAh');
+        } else {
+          alert('아이디/비밀번호가 틀렸습니다!');
+        }
+      });
+  };
+  handleInput = event => {
+    const { name, value } = event.target;
+    this.setState({
+      [name]: value,
+    });
+  };
+
+  goToMain = () => {
+    this.props.history.push('/MainAh');
+  };
+
   render() {
+    const { idInput, pwInput } = this.state;
+    const isButtonActive = idInput.includes('@') && pwInput.length >= 5;
     return (
-      <div>
-        <p>다슬</p>
+      <div className="Login">
+        <div className="container">
+          <div className="loginContainer">
+            <p>westagram</p>
+            <div className="idContainer">
+              <input
+                onChange={this.handleInput}
+                name="idInput"
+                type="text"
+                className="inputId"
+                placeholder="전화번호, 사용자 이름 또는 이메일"
+              />
+            </div>
+            <div className="passwordContainer">
+              <input
+                onChange={this.handleInput}
+                name="pwInput"
+                type="password"
+                className="inputPassword"
+                placeholder="비밀번호"
+              />
+            </div>
+            <button
+              disabled={!isButtonActive}
+              className={`loginButton ${
+                isButtonActive ? 'loginButtonOn' : 'loginButtonOff'
+              }`}
+              // onClick={this.goToMain}
+              onClick={this.loginTest}
+            >
+              로그인
+            </button>
+            <div>
+              <a href="google.com">비밀번호를 잊으셨나요?</a>
+            </div>
+          </div>
+        </div>
       </div>
     );
   }
 }
 
-export default LoginAh;
+export default withRouter(LoginAh);

리뷰: defaultColor는 아예 지우고 삼항연산자를 이용한 해결방법을 밑에 주셔서 그거로 색상 변환까지 적용하였습니다. 상태가 변한다고 생각되는것은 자꾸 state를 이용하게 되는거 같아 더 공부하겠습니다.
@@ -1,13 +1,92 @@
 import React from 'react';
+import { withRouter } from 'react-router-dom';
+import './Login.scss';
 
 class LoginAh extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      idInput: '',
+      pwInput: '',
+    };
+  }
+
+  loginTest = () => {
+    fetch('users/login', {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      body: JSON.stringify({
+        email: this.state.idInput,
+        password: this.state.pwInput,
+      }),
+    })
+      .then(response => response.json())
+      .then(response => {
+        if (response.token) {
+          localStorage.setItem('token', response.token);
+          this.props.history.push('/MainAh');
+        } else {
+          alert('아이디/비밀번호가 틀렸습니다!');
+        }
+      });
+  };
+  handleInput = event => {
+    const { name, value } = event.target;
+    this.setState({
+      [name]: value,
+    });
+  };
+
+  goToMain = () => {
+    this.props.history.push('/MainAh');
+  };
+
   render() {
+    const { idInput, pwInput } = this.state;
+    const isButtonActive = idInput.includes('@') && pwInput.length >= 5;
     return (
-      <div>
-        <p>다슬</p>
+      <div className="Login">
+        <div className="container">
+          <div className="loginContainer">
+            <p>westagram</p>
+            <div className="idContainer">
+              <input
+                onChange={this.handleInput}
+                name="idInput"
+                type="text"
+                className="inputId"
+                placeholder="전화번호, 사용자 이름 또는 이메일"
+              />
+            </div>
+            <div className="passwordContainer">
+              <input
+                onChange={this.handleInput}
+                name="pwInput"
+                type="password"
+                className="inputPassword"
+                placeholder="비밀번호"
+              />
+            </div>
+            <button
+              disabled={!isButtonActive}
+              className={`loginButton ${
+                isButtonActive ? 'loginButtonOn' : 'loginButtonOff'
+              }`}
+              // onClick={this.goToMain}
+              onClick={this.loginTest}
+            >
+              로그인
+            </button>
+            <div>
+              <a href="google.com">비밀번호를 잊으셨나요?</a>
+            </div>
+          </div>
+        </div>
       </div>
     );
   }
 }
 
-export default LoginAh;
+export default withRouter(LoginAh);

리뷰: 하단에 주신 해결법으로 수정했습니다!
@@ -1,13 +1,92 @@
 import React from 'react';
+import { withRouter } from 'react-router-dom';
+import './Login.scss';
 
 class LoginAh extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      idInput: '',
+      pwInput: '',
+    };
+  }
+
+  loginTest = () => {
+    fetch('users/login', {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      body: JSON.stringify({
+        email: this.state.idInput,
+        password: this.state.pwInput,
+      }),
+    })
+      .then(response => response.json())
+      .then(response => {
+        if (response.token) {
+          localStorage.setItem('token', response.token);
+          this.props.history.push('/MainAh');
+        } else {
+          alert('아이디/비밀번호가 틀렸습니다!');
+        }
+      });
+  };
+  handleInput = event => {
+    const { name, value } = event.target;
+    this.setState({
+      [name]: value,
+    });
+  };
+
+  goToMain = () => {
+    this.props.history.push('/MainAh');
+  };
+
   render() {
+    const { idInput, pwInput } = this.state;
+    const isButtonActive = idInput.includes('@') && pwInput.length >= 5;
     return (
-      <div>
-        <p>다슬</p>
+      <div className="Login">
+        <div className="container">
+          <div className="loginContainer">
+            <p>westagram</p>
+            <div className="idContainer">
+              <input
+                onChange={this.handleInput}
+                name="idInput"
+                type="text"
+                className="inputId"
+                placeholder="전화번호, 사용자 이름 또는 이메일"
+              />
+            </div>
+            <div className="passwordContainer">
+              <input
+                onChange={this.handleInput}
+                name="pwInput"
+                type="password"
+                className="inputPassword"
+                placeholder="비밀번호"
+              />
+            </div>
+            <button
+              disabled={!isButtonActive}
+              className={`loginButton ${
+                isButtonActive ? 'loginButtonOn' : 'loginButtonOff'
+              }`}
+              // onClick={this.goToMain}
+              onClick={this.loginTest}
+            >
+              로그인
+            </button>
+            <div>
+              <a href="google.com">비밀번호를 잊으셨나요?</a>
+            </div>
+          </div>
+        </div>
       </div>
     );
   }
 }
 
-export default LoginAh;
+export default withRouter(LoginAh);

리뷰: 정말 감사합니다. 무조건 constructor 단에서 변화시키는 줄 알고 그곳에서만 해결하려고 했는데 render에서 변경하면 더 간단하게 되는 것 같습니다. inline 스타일링 지양하겠습니다!!!
@@ -0,0 +1,15 @@
+{
+  "arrowParens": "always",
+  "bracketSpacing": true,
+  "jsxBracketSameLine": false,
+  "jsxSingleQuote": false,
+  "printWidth": 80,
+  "proseWrap": "always",
+  "quoteProps": "as-needed",
+  "semi": true,
+  "singleQuote": false,
+  "tabWidth": 2,
+  "trailingComma": "es5",
+  "useTabs": false,
+  "endOfLine": "auto"
+}
\ No newline at end of file

리뷰: EOL이 있네요
@@ -10,7 +10,17 @@
     "@babel/core": "^7.23.0",
     "@babel/preset-env": "^7.22.20",
     "babel-jest": "^29.7.0",
-    "jest": "29.6.0"
+    "eslint": "^8.56.0",
+    "eslint-config-airbnb": "^19.0.4",
+    "eslint-config-prettier": "^9.1.0",
+    "eslint-plugin-import": "^2.29.1",
+    "eslint-plugin-jsx-a11y": "^6.8.0",
+    "eslint-plugin-prettier": "^5.1.3",
+    "eslint-plugin-react": "^7.33.2",
+    "eslint-plugin-react-hooks": "^4.6.0",
+    "husky": "^9.0.7",
+    "jest": "29.6.0",
+    "prettier": "^3.2.4"
   },
   "scripts": {
     "test": "jest"

리뷰: 오.. husky까지