ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,35 @@
+package domain.player;
+
+import domain.point.Direction;
+
+public class Player {
+    private Name name;
+    private Position position;
+
+    public Player(Name name, Position position) {
+        this.name = name;
+        this.position = position;
+    }
+
+    public void move(Direction direction) {
+        if (direction == Direction.LEFT) {
+            position.moveLeft();
+            position.moveDown();
+        }
+        if (direction == Direction.RIGHT) {
+            position.moveRight();
+            position.moveDown();
+        }
+        if (direction == Direction.DOWN) {
+            position.moveDown();
+        }
+    }
+
+    public String getName() {
+        return name.getName();
+    }
+
+    public Position getPosition() {
+        return position;
+    }
+}
\ No newline at end of file

리뷰: 인터페이스를 활용해서 if 문을 없앨 수 있지 않을까요?
@@ -0,0 +1,46 @@
+package domain.player;
+
+import domain.line.Line;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class Players {
+
+    private List<Player> players;
+
+    public Players(List<Player> players) {
+        this.players = new ArrayList<>(players);
+    }
+
+    public List<Player> getPlayers() {
+        return Collections.unmodifiableList(players);
+    }
+
+    public List<String> toPlayerNames() {
+        return players.stream()
+                .map(player -> player.getName())
+                .collect(Collectors.toList());
+    }
+
+    public int size() {
+        return players.size();
+    }
+
+    public void moveAll(List<Line> lines) {
+        lines.forEach(this::moveOneLine);
+    }
+
+    public void moveOneLine(Line line) {
+        players.forEach(player -> player.move(line.findCurrentPointDirection(player.getPosition().getX())));
+    }
+
+    public boolean isContain(String playerName) {
+        if (!toPlayerNames().contains(playerName)) {
+            return false;
+        }
+        return true;
+    }
+}

리뷰: 이 메서드는 어디서 사용되는건가요~?
@@ -0,0 +1,54 @@
+package domain.player;
+
+import java.util.Objects;
+
+public class Position {
+    private static final String NEGATIVE_ERROR_MESSAGE = "[ERROR] Position의 x, y 값은 양수입니다.";
+    private int x;
+    private int y;
+
+    public Position(int x, int y) {
+        validateNegative(x, y);
+        this.x = x;
+        this.y = y;
+    }
+
+    public void validateNegative(int x, int y) {
+        if (x < 0 || y < 0) {
+            throw new IllegalArgumentException(NEGATIVE_ERROR_MESSAGE);
+        }
+    }
+
+    public void moveLeft() {
+        x--;
+    }
+
+    public void moveRight() {
+        x++;
+    }
+
+    public void moveDown() {
+        y++;
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        Position position = (Position) o;
+        return getX() == position.getX() && getY() == position.getY();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getX(), getY());
+    }
+}

리뷰: equals 와 hashcode 를 재정의한 이유를 설명해주시면 좋을 것 같아요~
@@ -0,0 +1,65 @@
+package domain.point;
+
+public class Point {
+    private static final String CONTINUOUS_CONNECTION_BRIDGE_ERROR_MESSAGE = "[ERROR] 다리는 연속되어 존재할 수 없습니다.";
+
+    private boolean left;
+    private boolean right;
+    private Direction direction;
+
+    public Point(boolean left, boolean right) {
+        validateContinuousConnectionBridge(left, right);
+        this.left = left;
+        this.right = right;
+        this.direction = checkConnection();
+    }
+
+    public static Point onlyFirstExist() {
+        return new Point(false, false);
+    }
+
+    public static Point first(boolean right) {
+        return new Point(false, right);
+    }
+
+    public static Point next(Point prePoint, boolean right) {
+        if (prePoint.right) {
+            return new Point(prePoint.right, false);
+        }
+        return new Point(false, right);
+    }
+
+    public static Point last(Point prePoint) {
+        return new Point(prePoint.right, false);
+    }
+
+    private void validateContinuousConnectionBridge(boolean left, boolean right) {
+        if (left && right) {
+            throw new IllegalArgumentException(CONTINUOUS_CONNECTION_BRIDGE_ERROR_MESSAGE);
+        }
+    }
+
+    public Direction checkConnection() {
+        if (left & !right) {
+            return Direction.LEFT;
+        }
+        if (right & !left) {
+            return Direction.RIGHT;
+        }
+        return Direction.DOWN;
+    }
+
+    public boolean isRight() {
+        return right;
+    }
+
+    public boolean isLeft() {
+        return left;
+    }
+
+    public Direction getDirection() {
+        return direction;
+    }
+
+
+}

리뷰: check 라는 메서드는 Direction 을 반환하기에 적절하지 않은 메서드명인 것 같습니다.
getConnectedDirection() 은 어떨까요
@@ -0,0 +1,12 @@
+package domain.point;
+
+import java.util.Random;
+
+public class RandomPointGenerator {
+
+    private static Random random = new Random();
+
+    public static boolean generate() {
+        return random.nextBoolean();
+    }
+}

리뷰: 역할은 Random 을 감싼 wrapper 클래스인데 Point 라는 제한을 이름으로 주게 되는 것 같습니다.
RandomGenerator util 로 보면 어떨까요
@@ -0,0 +1,80 @@
+package domain.line;
+
+import domain.point.Direction;
+import domain.point.Point;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class LineTest {
+
+    @Test
+    @DisplayName("한 포인트의 왼쪽 연결 다리가 존재하고 오른쪽 연결 다리가 존재하지 않을 경우 방향을 왼쪽으로 반환한다.")
+    void testIfLeftBridgeExistAndRightBridgeNotExistReturnDirectionLeft() {
+        // given
+        Point prePoint = Point.first(true);
+        Point nextPoint = Point.next(prePoint, false);
+        Point lastPoint = Point.last(nextPoint);
+
+        List<Point> points = new ArrayList<>();
+        points.add(prePoint);
+        points.add(nextPoint);
+        points.add(lastPoint);
+
+        Line line = new Line(points);
+
+        // when
+        Direction currentPointDirection = line.findCurrentPointDirection(1);
+
+        // then
+        assertThat(currentPointDirection).isEqualTo(Direction.LEFT);
+    }
+
+    @Test
+    @DisplayName("한 포인트의 오른쪽 연결 다리가 존재하고 왼쪽 연결 다리가 존재하지 않을 경우 방향을 오른쪽으로 반환한다.")
+    void testIfRightBridgeExistAndLeftBridgeNotExistReturnDirectionRight() {
+        // given
+        Point prePoint = Point.first(false);
+        Point nextPoint = Point.next(prePoint, true);
+        Point lastPoint = Point.last(nextPoint);
+
+        List<Point> points = new ArrayList<>();
+        points.add(prePoint);
+        points.add(nextPoint);
+        points.add(lastPoint);
+
+        Line line = new Line(points);
+
+        // when
+        Direction currentPointDirection = line.findCurrentPointDirection(1);
+
+        // then
+        assertThat(currentPointDirection).isEqualTo(Direction.RIGHT);
+    }
+
+    @Test
+    @DisplayName("한 포인트의 양쪽 다리가 모두 존재하지 않을 경우 방향을 아래로 반환한다.")
+    void testIfBothBridgeNotExistReturnDirectionDown() {
+        // given
+        Point prePoint = Point.first(false);
+        Point nextPoint = Point.next(prePoint, false);
+        Point lastPoint = Point.last(nextPoint);
+
+        List<Point> points = new ArrayList<>();
+        points.add(prePoint);
+        points.add(nextPoint);
+        points.add(lastPoint);
+
+        Line line = new Line(points);
+
+        // when
+        Direction currentPointDirection = line.findCurrentPointDirection(1);
+
+        // then
+        assertThat(currentPointDirection).isEqualTo(Direction.DOWN);
+    }
+}
\ No newline at end of file

리뷰: good 테스트 잘 작성하셨네요
@@ -13,33 +13,40 @@ export interface ButtonProps {
 export const Button = ({
   children,
   label,
-  bgColor = 'main',
+  // 버튼의 기본 스타일을 고려했을 때 transparent가 기본적인 bgColor로 입력되기 때문에, main은 따로 입력값으로 넣어주게 의도하는게 좋을 것 같습니다.
+  bgColor = 'transparent',
   disabled,
   className,
   ...props
 }: ButtonProps) => {
   const ariaLabel = typeof children === 'string' ? children : label;
 
+  // 여러가지 분기처리가 되어 선언적으로 스타일을 적용할 수 있게 잘 짜주셨는데, 만약 유지보수를 위해 코드를 고쳐야하는 상황이라면 해당 코드가 가독성이 안좋을 수 있다는 생각을 했습니다.
+  // 따라서 코드를 쪼개어 개발자가 세세하게 스타일을 들여다보지 않고 선언적인 키워드로 스타일을 적용할 수 있도록 구분해보았습니다.
+
+  // 기본 스타일
+  const baseStyles =
+    'leading-none transition duration-200 ease-in-out cursor-pointer rounded-lg text-white';
+
+  // 배경 스타일
+  const bgColorStyles = {
+    transparent: 'ml-auto opacity-70',
+    underline:
+      'text-main border-solid border-b border-main bg-transparent hover:text-main-hover',
+    main: !disabled ? 'bg-main hover:bg-main-hover' : '',
+    sub: !disabled ? 'bg-sub hover:bg-sub-hover' : '',
+    white: !disabled ? 'bg-white hover:bg-white-hover text-black' : '',
+    disabled: 'bg-disabled cursor-not-allowed',
+  };
+
+  // 추가 조건부 스타일
+  const conditionalStyles = {
+    'p-2.5': typeof children === 'string',
+  };
+
   const classes = twMerge(
-    clsx(
-      'leading-none transition duration-200 ease-in-out cursor-pointer',
-      bgColor === 'transparent'
-        ? 'ml-auto opacity-70'
-        : bgColor === 'underline'
-          ? 'text-main border-solid border-b border-main bg-transparent hover:text-main-hover'
-          : 'text-base text-white font-medium rounded-lg border-none',
-      {
-        'bg-main hover:bg-main-hover': bgColor === 'main' && !disabled,
-        'bg-sub hover:bg-sub-hover': bgColor === 'sub' && !disabled,
-        'bg-white hover:bg-white-hover text-black':
-          bgColor === 'white' && !disabled,
-        'bg-disabled cursor-not-allowed': bgColor === 'disabled' || disabled,
-      },
-      {
-        'p-2.5': typeof children === 'string',
-      },
-    ),
-    className,
+    clsx(baseStyles, bgColorStyles[bgColor], conditionalStyles),
+    className, // 외부에서 전달된 추가 클래스
   );
 
   return (

리뷰: 스타일 키워드도 선언적으로 작성하니 가독성이 좋아졌네요 감사합니다!
@@ -1,21 +1,37 @@
 import React from 'react';
 import clsx from 'clsx';
-import {twMerge} from 'tailwind-merge';
+import { twMerge } from 'tailwind-merge';
 
 interface MainProps {
   isMobile?: boolean;
   className?: string;
   children: React.ReactNode;
 }
 
-export const Main = ({isMobile = false, className, children}: MainProps) => {
-  const classes = twMerge(
-    clsx(
-      'flex items-center justify-center min-h-screen bg-white p-4',
-      isMobile ? 'flex-col gap-6' : 'gap-24',
-    ),
-    className,
-  );
+export const Main = ({ isMobile = false, className, children }: MainProps) => {
+  // Main을 이 프로젝트 전체의 Layout으로 잡으셨는데, 이럴 경우에는 isMobile을 props로 받는것보다 내부에서 isMobile을 판단해보는게 어떨까요?
+  // 그렇게 된다면 개발자가 일일히 props로 isMobile을 넘겨줄 필요가 없으니 더 편해질 것 같습니다.
+  // 이곳에는 clsx와 twMerge를 동시에 사용하지 말고 하나만 사용해도 충분할 것 같습니다.
 
-  return <main className={classes}>{children}</main>;
+  return (
+    <main
+      className={twMerge(
+        'flex items-center justify-center min-h-screen bg-white p-4',
+        isMobile ? 'flex-col gap-6' : 'gap-24',
+      )}
+    >
+      {children}
+    </main>
+  );
+  return (
+    <main
+      className={clsx(
+        'flex items-center justify-center min-h-screen bg-white p-4',
+        isMobile ? 'flex-col gap-6' : 'gap-24',
+        className,
+      )}
+    >
+      {children}
+    </main>
+  );
 };

리뷰: isMobile에 대한 수정도 고려해보겠습니다~!
@@ -1,21 +1,37 @@
 import React from 'react';
 import clsx from 'clsx';
-import {twMerge} from 'tailwind-merge';
+import { twMerge } from 'tailwind-merge';
 
 interface MainProps {
   isMobile?: boolean;
   className?: string;
   children: React.ReactNode;
 }
 
-export const Main = ({isMobile = false, className, children}: MainProps) => {
-  const classes = twMerge(
-    clsx(
-      'flex items-center justify-center min-h-screen bg-white p-4',
-      isMobile ? 'flex-col gap-6' : 'gap-24',
-    ),
-    className,
-  );
+export const Main = ({ isMobile = false, className, children }: MainProps) => {
+  // Main을 이 프로젝트 전체의 Layout으로 잡으셨는데, 이럴 경우에는 isMobile을 props로 받는것보다 내부에서 isMobile을 판단해보는게 어떨까요?
+  // 그렇게 된다면 개발자가 일일히 props로 isMobile을 넘겨줄 필요가 없으니 더 편해질 것 같습니다.
+  // 이곳에는 clsx와 twMerge를 동시에 사용하지 말고 하나만 사용해도 충분할 것 같습니다.
 
-  return <main className={classes}>{children}</main>;
+  return (
+    <main
+      className={twMerge(
+        'flex items-center justify-center min-h-screen bg-white p-4',
+        isMobile ? 'flex-col gap-6' : 'gap-24',
+      )}
+    >
+      {children}
+    </main>
+  );
+  return (
+    <main
+      className={clsx(
+        'flex items-center justify-center min-h-screen bg-white p-4',
+        isMobile ? 'flex-col gap-6' : 'gap-24',
+        className,
+      )}
+    >
+      {children}
+    </main>
+  );
 };

리뷰: 조건부 처리를 위해선 clsx는 필요해보입니다! Main에 className이 앞으로도 추가되지 않을 거라면 clsx만 있어도 될 것 같습니다~
@@ -1,7 +1,87 @@
 import React from 'react';
+import { useState } from 'react';
+import { useNavigate, Link } from 'react-router-dom';
+import Nav from '../../../Components/Nav';
+import './Login.scss';
 
-const Login = () => {
-  return <div>Login</div>;
-};
+function Login() {
+  const [input, setInput] = useState({
+    id: '',
+    pwd: '',
+  });
+
+  const { id, pwd } = input;
+
+  const handleInput = e => {
+    const { name, value } = e.target;
+    // FIXME: setState argument -> callback function
+    setInput(input => {
+      return {
+        ...input,
+        [name]: value,
+      };
+    });
+  };
+
+  const mainPageLink = useNavigate();
+
+  const goToMainPage = () => {
+    mainPageLink('/main-YounSeop');
+  };
+
+  const checkLoginApi = () => {
+    fetch('http://10.58.3.156:8000/user/login', {
+      method: 'POST',
+      body: JSON.stringify({
+        user_email: input.id,
+        password: input.pw,
+      }),
+    })
+      .then(response => response.json())
+      .then(result => {
+        if (result.Token) {
+          localStorage.setItem('Token', result.Token);
+          goToMainPage();
+        }
+      });
+    // FIXME: status code
+  };
+
+  return (
+    <>
+      <Nav />
+      <div className="login">
+        <div className="wrapper">
+          <h1 className="westaLogo">Westagram</h1>
+          <div className="loginBox">
+            <input
+              type="text"
+              placeholder="전화번호, 사용자 이름 또는 메일"
+              name="id"
+              value={input.id}
+              onChange={handleInput}
+            />
+            <input
+              type="password"
+              placeholder="비밀번호"
+              name="pwd"
+              onChange={handleInput}
+            />
+            <button
+              id="loginBtn"
+              disabled={!id.includes('@') && pwd.length}
+              onClick={checkLoginApi}
+            >
+              로그인
+            </button>
+          </div>
+          <Link to="/" className="forgotPw">
+            비밀번호를 잊으셨나요?
+          </Link>
+        </div>
+      </div>
+    </>
+  );
+}
 
 export default Login;

리뷰: a tag Link로 바꿔주세요~
@@ -1,7 +1,87 @@
 import React from 'react';
+import { useState } from 'react';
+import { useNavigate, Link } from 'react-router-dom';
+import Nav from '../../../Components/Nav';
+import './Login.scss';
 
-const Login = () => {
-  return <div>Login</div>;
-};
+function Login() {
+  const [input, setInput] = useState({
+    id: '',
+    pwd: '',
+  });
+
+  const { id, pwd } = input;
+
+  const handleInput = e => {
+    const { name, value } = e.target;
+    // FIXME: setState argument -> callback function
+    setInput(input => {
+      return {
+        ...input,
+        [name]: value,
+      };
+    });
+  };
+
+  const mainPageLink = useNavigate();
+
+  const goToMainPage = () => {
+    mainPageLink('/main-YounSeop');
+  };
+
+  const checkLoginApi = () => {
+    fetch('http://10.58.3.156:8000/user/login', {
+      method: 'POST',
+      body: JSON.stringify({
+        user_email: input.id,
+        password: input.pw,
+      }),
+    })
+      .then(response => response.json())
+      .then(result => {
+        if (result.Token) {
+          localStorage.setItem('Token', result.Token);
+          goToMainPage();
+        }
+      });
+    // FIXME: status code
+  };
+
+  return (
+    <>
+      <Nav />
+      <div className="login">
+        <div className="wrapper">
+          <h1 className="westaLogo">Westagram</h1>
+          <div className="loginBox">
+            <input
+              type="text"
+              placeholder="전화번호, 사용자 이름 또는 메일"
+              name="id"
+              value={input.id}
+              onChange={handleInput}
+            />
+            <input
+              type="password"
+              placeholder="비밀번호"
+              name="pwd"
+              onChange={handleInput}
+            />
+            <button
+              id="loginBtn"
+              disabled={!id.includes('@') && pwd.length}
+              onClick={checkLoginApi}
+            >
+              로그인
+            </button>
+          </div>
+          <Link to="/" className="forgotPw">
+            비밀번호를 잊으셨나요?
+          </Link>
+        </div>
+      </div>
+    </>
+  );
+}
 
 export default Login;

리뷰: import 순서 정리하면 좋을거 같아요
@@ -0,0 +1,29 @@
+import React from 'react';
+import Story from './Story';
+import Recommend from './Recommend';
+import Footer from './Footer';
+
+const Aside = () => {
+  return (
+    <aside className="mainRight">
+      <div className="asideWrapper">
+        <div className="profile">
+          <img
+            src="images/younseop/post-user.jpg"
+            alt="post user"
+            className="imgUserPhoto"
+          />
+          <div className="profileTextWrapper">
+            <span className="profileName">wecode_bootcamp</span>
+            <span className="profileLocation">Wecode | 위코드</span>
+          </div>
+        </div>
+        <Story />
+        <Recommend />
+        <Footer />
+      </div>
+    </aside>
+  );
+};
+
+export default Aside;

리뷰: 구조별로 컴포넌트화 해서 구현하신 것 배워갑니다~
@@ -0,0 +1,29 @@
+import React from 'react';
+import Story from './Story';
+import Recommend from './Recommend';
+import Footer from './Footer';
+
+const Aside = () => {
+  return (
+    <aside className="mainRight">
+      <div className="asideWrapper">
+        <div className="profile">
+          <img
+            src="images/younseop/post-user.jpg"
+            alt="post user"
+            className="imgUserPhoto"
+          />
+          <div className="profileTextWrapper">
+            <span className="profileName">wecode_bootcamp</span>
+            <span className="profileLocation">Wecode | 위코드</span>
+          </div>
+        </div>
+        <Story />
+        <Recommend />
+        <Footer />
+      </div>
+    </aside>
+  );
+};
+
+export default Aside;

리뷰: ```suggestion
          <img
            src="images/younseop/post-user.jpg"
            alt="imgUserPhoto"
            className="imgUserPhoto"
```

alt 값에는 시각장애인들도 인식할 수 있게 꼭 무슨 내용인지 명시해주셔 합니다!
@@ -0,0 +1,29 @@
+import React, { useState, useEffect } from 'react';
+
+const Footer = () => {
+  const [footers, setFooters] = useState([]);
+
+  useEffect(() => {
+    fetch('http://localhost:3000/data/younseop/footer.json')
+      .then(response => response.json())
+      .then(result => setFooters(result));
+  }, []);
+
+  return (
+    <footer>
+      <p>
+        {footers.map(info => {
+          // FIXME: Link component
+          return (
+            <a href="/" key={info.id}>
+              {info.content}
+            </a>
+          );
+        })}
+      </p>
+      <span>ⓒ 2022 WESTAGRAM</span>
+    </footer>
+  );
+};
+
+export default Footer;

리뷰: ```suggestion
const FOOTER_LIST = [
  { id: 1, content: 'Westagram 정보 · ' },
  { id: 2, content: '지원 · ' },
  { id: 3, content: '홍보 센터 · ' },
  { id: 4, content: 'API · ' },
  { id: 5, content: '채용정보 ·  ' },
  { id: 6, content: '개인정보처리방침 · ' },
  { id: 7, content: '약관 · ' },
  { id: 8, content: '디렉터리 · ' },
  { id: 9, content: '프로필 · ' },
  { id: 10, content: '해시태그 ·  ' },
  { id: 11, content: '언어' },
];
```

public/data 폴더에 json 파일로 mock data 생성하셔서 fetch 해 오신 뒤에 props로 넘기는 편이 더 효율적일 것 같습니다!
@@ -0,0 +1,83 @@
+import React, { useState } from "react";
+import { useQuery } from "@tanstack/react-query";
+import Pagination from "@/components/Common/Pagination";
+import ReviewModal from "@/components/Modal/ReviewModal";
+import Tab from "@/components/Tab";
+import WriteReviewCard from "@/components/Cards/writeReviewCard";
+
+const fetchReviews = async () => {
+  return [
+    {
+      id: 1,
+      name: "김코드 기사님",
+      date: "2024.07.01",
+      price: "210,000원",
+    },
+    {
+      id: 2,
+      name: "이코드 기사님",
+      date: "2024.07.03",
+      price: "250,000원",
+    },
+  ];
+};
+
+export default function AwaitingReview() {
+  const [reviews, setReviews] = useState([]);
+  const [currentPage, setCurrentPage] = useState(1);
+  const [isModalOpen, setIsModalOpen] = useState(false);
+  const [selectedReview, setSelectedReview] = useState(null);
+
+  const ITEMS_PER_PAGE = 6;
+
+  const { data } = useQuery(
+    ["reviews", currentPage],
+    () => fetchReviews(currentPage, ITEMS_PER_PAGE),
+    {
+      keepPreviousData: true,
+    }
+  );
+
+
+
+  const handlePageChange = (page: number) => {
+    setCurrentPage(page);
+  };
+
+  const handleWriteReview = (review: any) => {
+    setSelectedReview(review);
+    setIsModalOpen(true);
+  };
+
+  return (
+    <div className="p-6">
+      <div>
+        <Tab />
+      </div>
+
+      <div className="grid gap-6">
+        {data.reviews.map((review: any) => (
+          <div key={review.id} className="p-4 border rounded-lg shadow-sm">
+            <WriteReviewCard
+              item={review}
+              onClick={() => handleWriteReview(review)}
+            />
+          </div>
+        ))}
+      </div>
+
+      <Pagination
+        currentPage={currentPage}
+        totalPages={Math.ceil(data.total / ITEMS_PER_PAGE)}
+        onPageChange={handlePageChange}
+      />
+
+      {isModalOpen && (
+        <ReviewModal
+          review={selectedReview}
+          closeModal={() => setIsModalOpen(false)}
+        />
+      )}
+    </div>
+  );
+}
\ No newline at end of file

리뷰: 이 부분은 혹시 Tab 부분이라면 제가 만들어 놓은 Tab 컴포넌트 있으니 그거 사용하시면 될 거에요! 특정 페이지 경로마다 해당 탭 메뉴 삽입 되도록해서 아무 설정안해도 자동으로 바뀔 겁니다!