ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -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>
     );
   }

리뷰: 버튼이 활성화될 때 색상 변경과 비활성화 기능까지 구현하신 점 배워갑니다:)
@@ -0,0 +1,74 @@
+[
+  {
+    "id": 1,
+    "userName": "bbangho",
+    "alt": "wecode",
+    "img": "/images/youngho/hanRiver.jpeg",
+    "comment": [
+      {
+        "id": 1,
+        "userName": "bbangho",
+        "content": "한강 다녀감~ ✌️",
+        "isLiked": true
+      },
+      {
+        "id": 2,
+        "userName": "manja",
+        "content": "한강 갱~ 🔫 🔫",
+        "isLiked": true
+      }
+    ]
+  },
+  {
+    "id": 2,
+    "userName": "joonsikyang",
+    "alt": "wecode",
+    "img": "/images/youngho/we.jpeg",
+    "comment": [
+      {
+        "id": 1,
+        "userName": "joonsikyang",
+        "content": "Work hard 🤯",
+        "isLiked": true
+      },
+      {
+        "id": 2,
+        "userName": "bbangho",
+        "content": "Go for it 🤣",
+        "isLiked": false
+      },
+      {
+        "id": 3,
+        "userName": "manja",
+        "content": "🔥🔥",
+        "isLiked": false
+      }
+    ]
+  },
+  {
+    "id": 3,
+    "userName": "jayPark",
+    "alt": "wecode",
+    "img": "/images/youngho/we.jpeg",
+    "comment": [
+      {
+        "id": 1,
+        "userName": "jayPark",
+        "content": "Let's get it",
+        "isLiked": true
+      },
+      {
+        "id": 2,
+        "userName": "bbanho",
+        "content": "Skrt~ 😎",
+        "isLiked": false
+      },
+      {
+        "id": 3,
+        "userName": "gildong",
+        "content": "Yo~ 🌞",
+        "isLiked": true
+      }
+    ]
+  }
+]

리뷰: 목데이터 사용 너무 좋습니다! :)
@@ -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>
     );
   }

리뷰: ```suggestion
              <button
                onClick={this.handleLogin}
                className={condition ? 'buttonActivate' : 'buttonDisabled'}
                id="loginButton"
                disabled={ condition ? false : true}
              >
                로그인
              </button>
```
해당 조건을 condition이라는 변수에 담아서 사용하시면 가독성이 더 좋아지겠네요!
ex) 
```
const condition = loginId.length >= 5 && loginPassword.length >= 5 && loginId.includes('@');
```
@@ -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>
     );
   }

리뷰: 참고로 위의 변수는 render 함수 내에서 선언해주시면 됩니다!!
@@ -0,0 +1,78 @@
+@import 'https://fonts.googleapis.com/css2?family=Lobster&display=swap';
+body {
+  background-color: #fafafa;
+}
+
+.container {
+  text-align: center;
+  width: 600px;
+  height: 600px;
+  margin: 50px auto 0 auto;
+  border: 1px solid #e6e6e6;
+  background-color: white;
+}
+
+.header {
+  padding: 30px;
+  font-family: 'Lobster', cursive;
+  font-size: 70px;
+  font-weight: 1px;
+}
+
+.loginForm {
+  width: 425px;
+  margin: 0 auto;
+}
+
+#id {
+  display: block;
+  width: 100%;
+  margin: 20px 0px auto;
+  padding: 15px;
+  border: 1px solid #efefef;
+  background-color: #fafafa;
+  border-radius: 5px;
+  font-size: 20px;
+}
+
+#password {
+  display: block;
+  width: 100%;
+  margin: 20px 0px auto;
+  padding: 15px;
+  border: 1px solid #efefef;
+  background-color: #fafafa;
+  border-radius: 5px;
+  font-size: 20px;
+}
+
+#loginButton {
+  display: block;
+  width: 459px;
+  margin: 20px 0px auto;
+  padding: 15px;
+  border: 0px;
+  border-radius: 5px;
+  color: white;
+  font-size: 20px;
+}
+
+.findPassword {
+  display: block;
+  height: 50px;
+  margin-top: 180px;
+  font-size: 18px;
+  text-decoration: none;
+}
+
+.buttonDisabled {
+  background-color: #c5e1fc;
+}
+
+.buttonActivate {
+  background-color: #0095f6;
+}
+
+a {
+  text-decoration: none;
+}

리뷰: ```suggestion
body {
  background-color: #fafafa;
}

.container {
  text-align: center;
  border: 1px solid #e6e6e6;
  background-color: white;
  width: 600px;
  height: 600px;
  margin: 50px auto 0 auto;
}

.header {
  font-family: 'Lobster', cursive;
  font-size: 70px;
  font-weight: 1px;
  padding: 30px;
}
```
가독성을 위해 셀럭터 시작할 때는 한 줄 띄워주시기 바랍니다.
@@ -0,0 +1,78 @@
+@import 'https://fonts.googleapis.com/css2?family=Lobster&display=swap';
+body {
+  background-color: #fafafa;
+}
+
+.container {
+  text-align: center;
+  width: 600px;
+  height: 600px;
+  margin: 50px auto 0 auto;
+  border: 1px solid #e6e6e6;
+  background-color: white;
+}
+
+.header {
+  padding: 30px;
+  font-family: 'Lobster', cursive;
+  font-size: 70px;
+  font-weight: 1px;
+}
+
+.loginForm {
+  width: 425px;
+  margin: 0 auto;
+}
+
+#id {
+  display: block;
+  width: 100%;
+  margin: 20px 0px auto;
+  padding: 15px;
+  border: 1px solid #efefef;
+  background-color: #fafafa;
+  border-radius: 5px;
+  font-size: 20px;
+}
+
+#password {
+  display: block;
+  width: 100%;
+  margin: 20px 0px auto;
+  padding: 15px;
+  border: 1px solid #efefef;
+  background-color: #fafafa;
+  border-radius: 5px;
+  font-size: 20px;
+}
+
+#loginButton {
+  display: block;
+  width: 459px;
+  margin: 20px 0px auto;
+  padding: 15px;
+  border: 0px;
+  border-radius: 5px;
+  color: white;
+  font-size: 20px;
+}
+
+.findPassword {
+  display: block;
+  height: 50px;
+  margin-top: 180px;
+  font-size: 18px;
+  text-decoration: none;
+}
+
+.buttonDisabled {
+  background-color: #c5e1fc;
+}
+
+.buttonActivate {
+  background-color: #0095f6;
+}
+
+a {
+  text-decoration: none;
+}

리뷰: 영호님! 전체적으로 CSS 속성 순서 확인해서 적용해주세요~
- 하나의 요소에 여러가지 속성을 부여하는 경우 중요도, 관련도에 따라서 나름의 convention을 지켜서 작성하는 것이 좋습니다.
- 일반적인 convention 은 아래와 같습니다. 아래와 같이 순서 적용해주세요.

    [CSS property 순서]

    - Layout Properties (position, float, clear, display)
    - Box Model Properties (width, height, margin, padding)
    - Visual Properties (color, background, border, box-shadow)
    - Typography Properties (font-size, font-family, text-align, text-transform)
    - Misc Properties (cursor, overflow, z-index)
@@ -0,0 +1,74 @@
+[
+  {
+    "id": 1,
+    "userName": "bbangho",
+    "alt": "wecode",
+    "img": "/images/youngho/hanRiver.jpeg",
+    "comment": [
+      {
+        "id": 1,
+        "userName": "bbangho",
+        "content": "한강 다녀감~ ✌️",
+        "isLiked": true
+      },
+      {
+        "id": 2,
+        "userName": "manja",
+        "content": "한강 갱~ 🔫 🔫",
+        "isLiked": true
+      }
+    ]
+  },
+  {
+    "id": 2,
+    "userName": "joonsikyang",
+    "alt": "wecode",
+    "img": "/images/youngho/we.jpeg",
+    "comment": [
+      {
+        "id": 1,
+        "userName": "joonsikyang",
+        "content": "Work hard 🤯",
+        "isLiked": true
+      },
+      {
+        "id": 2,
+        "userName": "bbangho",
+        "content": "Go for it 🤣",
+        "isLiked": false
+      },
+      {
+        "id": 3,
+        "userName": "manja",
+        "content": "🔥🔥",
+        "isLiked": false
+      }
+    ]
+  },
+  {
+    "id": 3,
+    "userName": "jayPark",
+    "alt": "wecode",
+    "img": "/images/youngho/we.jpeg",
+    "comment": [
+      {
+        "id": 1,
+        "userName": "jayPark",
+        "content": "Let's get it",
+        "isLiked": true
+      },
+      {
+        "id": 2,
+        "userName": "bbanho",
+        "content": "Skrt~ 😎",
+        "isLiked": false
+      },
+      {
+        "id": 3,
+        "userName": "gildong",
+        "content": "Yo~ 🌞",
+        "isLiked": true
+      }
+    ]
+  }
+]

리뷰: 감사합니다!
@@ -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>
     );
   }

리뷰: 반영 완료했습니다!
@@ -0,0 +1,78 @@
+@import 'https://fonts.googleapis.com/css2?family=Lobster&display=swap';
+body {
+  background-color: #fafafa;
+}
+
+.container {
+  text-align: center;
+  width: 600px;
+  height: 600px;
+  margin: 50px auto 0 auto;
+  border: 1px solid #e6e6e6;
+  background-color: white;
+}
+
+.header {
+  padding: 30px;
+  font-family: 'Lobster', cursive;
+  font-size: 70px;
+  font-weight: 1px;
+}
+
+.loginForm {
+  width: 425px;
+  margin: 0 auto;
+}
+
+#id {
+  display: block;
+  width: 100%;
+  margin: 20px 0px auto;
+  padding: 15px;
+  border: 1px solid #efefef;
+  background-color: #fafafa;
+  border-radius: 5px;
+  font-size: 20px;
+}
+
+#password {
+  display: block;
+  width: 100%;
+  margin: 20px 0px auto;
+  padding: 15px;
+  border: 1px solid #efefef;
+  background-color: #fafafa;
+  border-radius: 5px;
+  font-size: 20px;
+}
+
+#loginButton {
+  display: block;
+  width: 459px;
+  margin: 20px 0px auto;
+  padding: 15px;
+  border: 0px;
+  border-radius: 5px;
+  color: white;
+  font-size: 20px;
+}
+
+.findPassword {
+  display: block;
+  height: 50px;
+  margin-top: 180px;
+  font-size: 18px;
+  text-decoration: none;
+}
+
+.buttonDisabled {
+  background-color: #c5e1fc;
+}
+
+.buttonActivate {
+  background-color: #0095f6;
+}
+
+a {
+  text-decoration: none;
+}

리뷰: 반영 완료했습니다!
@@ -0,0 +1,17 @@
+from django.db import models
+
+class User(models.Model):
+    email    = models.EmailField(max_length=50, unique=True)
+    password = models.CharField(max_length=100)
+    relation = models.ManyToManyField('self', through='Follow', symmetrical=False)
+
+    class Meta:
+        db_table = "users"
+        
+ 
+class Follow(models.Model):
+    following = models.ForeignKey(User, on_delete = models.SET_NULL, null=True, related_name = "following")
+    follower  = models.ForeignKey(User, on_delete = models.SET_NULL, null=True, related_name = "follower")    
+    
+    class Meta:
+        db_table = "follows"
\ No newline at end of file

리뷰: 다민님! 잘 작성해주셨는데 `email` 은 겹칠 수 없는 정보이기 때문에 해당하는 옵션을 추가해주시는게 좋습니다! 알아보시고 알맞은 옵션을 추가해주세요~
@@ -0,0 +1,10 @@
+from django.urls import path
+from .views      import SignupView, LoginView, FollowView
+
+urlpatterns = [
+    path('/user', SignupView.as_view()),
+    path('/login', LoginView.as_view()),    
+    path('/follow', FollowView.as_view()),    
+
+]
+'''Error가 아니라 django의 권장사항. 하지만 패턴 컨벤션에는 위 사항이 맞다.'''

리뷰: import 하실 때 `*` 사용하지 마시고 명확하게 가져오고 싶은 class 를 적어주세요!
@@ -0,0 +1,10 @@
+from django.urls import path
+from .views      import SignupView, LoginView, FollowView
+
+urlpatterns = [
+    path('/user', SignupView.as_view()),
+    path('/login', LoginView.as_view()),    
+    path('/follow', FollowView.as_view()),    
+
+]
+'''Error가 아니라 django의 권장사항. 하지만 패턴 컨벤션에는 위 사항이 맞다.'''

리뷰: 이 부분 세션 중 한번 설명 드렸는데, 왜 `/` 관련 warning 이 뜬다고 생각하시나요!?
@@ -0,0 +1,21 @@
+"""westagram URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/3.1/topics/http/urls/
+Examples:
+Function views
+    1. Add an import:  from my_app import views
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
+Class-based views
+    1. Add an import:  from other_app.views import Home
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
+Including another URLconf
+    1. Import the include() function: from django.urls import include, path
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
+"""
+from django.urls import path, include
+
+urlpatterns = [
+    path('account', include('account.urls')),
+    path('posting', include('posting.urls')),
+]

리뷰: 이 부분은 위코드 url 패턴 컨벤션에 맞지 않습니다. 위에 리뷰드린 내용 중 `/` 관련 질문 남겨드렸으니 확인해주세요.
@@ -0,0 +1,17 @@
+from django.db import models
+
+class User(models.Model):
+    email    = models.EmailField(max_length=50, unique=True)
+    password = models.CharField(max_length=100)
+    relation = models.ManyToManyField('self', through='Follow', symmetrical=False)
+
+    class Meta:
+        db_table = "users"
+        
+ 
+class Follow(models.Model):
+    following = models.ForeignKey(User, on_delete = models.SET_NULL, null=True, related_name = "following")
+    follower  = models.ForeignKey(User, on_delete = models.SET_NULL, null=True, related_name = "follower")    
+    
+    class Meta:
+        db_table = "follows"
\ No newline at end of file

리뷰: `from django.db import models

class User(models.Model):
    email    = models.EmailField(max_length=50, unique=True)` 로 해결했습니다.
@@ -0,0 +1,10 @@
+from django.urls import path
+from .views      import SignupView, LoginView, FollowView
+
+urlpatterns = [
+    path('/user', SignupView.as_view()),
+    path('/login', LoginView.as_view()),    
+    path('/follow', FollowView.as_view()),    
+
+]
+'''Error가 아니라 django의 권장사항. 하지만 패턴 컨벤션에는 위 사항이 맞다.'''

리뷰: `from django.urls import path
from .views      import SignupView, LoginView` 로 필요한 뷰 클래스 가져오는 것으로 수정하였습니다.
@@ -0,0 +1,10 @@
+from django.urls import path
+from .views      import SignupView, LoginView, FollowView
+
+urlpatterns = [
+    path('/user', SignupView.as_view()),
+    path('/login', LoginView.as_view()),    
+    path('/follow', FollowView.as_view()),    
+
+]
+'''Error가 아니라 django의 권장사항. 하지만 패턴 컨벤션에는 위 사항이 맞다.'''

리뷰: Error가 아니라 django의 권장사항이어서 그렇습니다. 하지만 패턴 컨벤션에는 고쳐서 쓰는 것이 맞기 때문에 고쳤습니다.
@@ -0,0 +1,21 @@
+"""westagram URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/3.1/topics/http/urls/
+Examples:
+Function views
+    1. Add an import:  from my_app import views
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
+Class-based views
+    1. Add an import:  from other_app.views import Home
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
+Including another URLconf
+    1. Import the include() function: from django.urls import include, path
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
+"""
+from django.urls import path, include
+
+urlpatterns = [
+    path('account', include('account.urls')),
+    path('posting', include('posting.urls')),
+]

리뷰: 수정하였습니다.
@@ -0,0 +1,17 @@
+from django.db import models
+
+class User(models.Model):
+    email    = models.EmailField(max_length=50, unique=True)
+    password = models.CharField(max_length=100)
+    relation = models.ManyToManyField('self', through='Follow', symmetrical=False)
+
+    class Meta:
+        db_table = "users"
+        
+ 
+class Follow(models.Model):
+    following = models.ForeignKey(User, on_delete = models.SET_NULL, null=True, related_name = "following")
+    follower  = models.ForeignKey(User, on_delete = models.SET_NULL, null=True, related_name = "follower")    
+    
+    class Meta:
+        db_table = "follows"
\ No newline at end of file

리뷰: `unique=True` 굳입니다!!