diff --git a/src/main/java/ladder/LadderGameController.java b/src/main/java/ladder/LadderGameController.java
new file mode 100644
index 0000000000..fbabbaf3f0
--- /dev/null
+++ b/src/main/java/ladder/LadderGameController.java
@@ -0,0 +1,33 @@
+package ladder;
+
+import ladder.domain.ladder.Ladder;
+import ladder.domain.player.Players;
+import ladder.view.input.ConsoleInputView;
+import ladder.view.input.InputView;
+import ladder.view.output.OutputView;
+
+public class LadderGameController {
+
+    private final InputView inputView;
+    private final OutputView outputView;
+
+    public LadderGameController(InputView inputView, OutputView outputView) {
+        this.inputView = inputView;
+        this.outputView = outputView;
+    }
+
+    public static void main(String[] args) {
+        LadderGameController game = new LadderGameController(new ConsoleInputView(), new OutputView());
+        game.run();
+    }
+
+    private void run() {
+        String inputNames = inputView.inputPlayerNames();
+        Players players = new Players(inputNames);
+
+        int height = inputView.inputLadderHeight();
+        Ladder ladder = new Ladder(height, players.count());
+
+        outputView.printResult(players, ladder);
+    }
+}
diff --git a/src/main/java/ladder/README.md b/src/main/java/ladder/README.md
new file mode 100644
index 0000000000..fcc32481a6
--- /dev/null
+++ b/src/main/java/ladder/README.md
@@ -0,0 +1,34 @@
+## 2단계 - 사다리(생성)
+
+### 기능 요구사항
+- 사다리 게임에 참여하는 사람에 이름을 최대5글자까지 부여할 수 있다. 사다리를 출력할 때 사람 이름도 같이 출력한다.
+- 사람 이름은 쉼표(,)를 기준으로 구분한다.
+- 사람 이름을 5자 기준으로 출력하기 때문에 사다리 폭도 넓어져야 한다.
+- 사다리 타기가 정상적으로 동작하려면 라인이 겹치지 않도록 해야 한다.
+  - `|-----|-----|` 모양과 같이 가로 라인이 겹치는 경우 어느 방향으로 이동할지 결정할 수 없다.
+
+
+### 프로그래밍 요구사항
+
+- 자바 8의 스트림과 람다를 적용해 프로그래밍한다.
+- 규칙 6: 모든 엔티티를 작게 유지한다.
+
+### 실행 결과
+위 요구사항에 따라 4명의 사람을 위한 5개 높이 사다리를 만들 경우, 프로그램을 실행한 결과는 다음과 같다.
+
+```
+참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)
+pobi,honux,crong,jk
+
+최대 사다리 높이는 몇 개인가요?
+5
+
+실행결과
+
+pobi  honux crong   jk
+    |-----|     |-----|
+    |     |-----|     |
+    |-----|     |     |
+    |     |-----|     |
+    |-----|     |-----|
+```
diff --git a/src/main/java/ladder/domain/ladder/Ladder.java b/src/main/java/ladder/domain/ladder/Ladder.java
new file mode 100644
index 0000000000..bfb56197cf
--- /dev/null
+++ b/src/main/java/ladder/domain/ladder/Ladder.java
@@ -0,0 +1,19 @@
+package ladder.domain.ladder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.IntStream;
+
+public class Ladder {
+    private final List<Line> lines;
+
+    public Ladder(int height, int countOfPlayers) {
+        lines = new ArrayList<>();
+        IntStream.range(0, height)
+                .forEach(i -> lines.add(new Line(countOfPlayers)));
+    }
+
+    public List<Line> getLines() {
+        return lines;
+    }
+}
diff --git a/src/main/java/ladder/domain/ladder/Line.java b/src/main/java/ladder/domain/ladder/Line.java
new file mode 100644
index 0000000000..b04ba750a1
--- /dev/null
+++ b/src/main/java/ladder/domain/ladder/Line.java
@@ -0,0 +1,29 @@
+package ladder.domain.ladder;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class Line {
+    private final List<Point> points;
+
+    public Line(int countOfPlayers) {
+        int numberOfPoints = countOfPlayers - 1;
+        this.points = initializePoints(numberOfPoints);
+    }
+
+    private List<Point> initializePoints(int numberOfPoints) {
+        boolean previousHasLine = false;
+        List<Point> points = new ArrayList<>();
+        for (int i = 0; i < numberOfPoints; i++) {
+            Point point = Point.create(previousHasLine);
+            points.add(point);
+            previousHasLine = point.hasLine();
+        }
+        return Collections.unmodifiableList(points);
+    }
+
+    public List<Point> getPoints() {
+        return points;
+    }
+}
diff --git a/src/main/java/ladder/domain/ladder/Point.java b/src/main/java/ladder/domain/ladder/Point.java
new file mode 100644
index 0000000000..c32a541d3f
--- /dev/null
+++ b/src/main/java/ladder/domain/ladder/Point.java
@@ -0,0 +1,18 @@
+package ladder.domain.ladder;
+
+public class Point {
+    private final boolean hasLine;
+
+    public Point(boolean hasLine) {
+        this.hasLine = hasLine;
+    }
+
+    public boolean hasLine() {
+        return hasLine;
+    }
+
+    public static Point create(boolean previousHasLine) {
+        if (previousHasLine) return new Point(false);
+        return new Point(Math.random() > 0.5);
+    }
+}
diff --git a/src/main/java/ladder/domain/player/Player.java b/src/main/java/ladder/domain/player/Player.java
new file mode 100644
index 0000000000..7a7d9a6a42
--- /dev/null
+++ b/src/main/java/ladder/domain/player/Player.java
@@ -0,0 +1,17 @@
+package ladder.domain.player;
+
+public class Player {
+    private static final int MAX_NAME_LENGTH = 5;
+    private final String name;
+
+    public Player(String name) {
+        if (name.length() > MAX_NAME_LENGTH) {
+            throw new IllegalArgumentException("이름은 최대 5자까지 가능합니다.");
+        }
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
diff --git a/src/main/java/ladder/domain/player/Players.java b/src/main/java/ladder/domain/player/Players.java
new file mode 100644
index 0000000000..797f37cc53
--- /dev/null
+++ b/src/main/java/ladder/domain/player/Players.java
@@ -0,0 +1,26 @@
+package ladder.domain.player;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class Players {
+    private static final String DELIMITER_COMMA = ",";
+
+    private final List<Player> players;
+
+    public Players(String input) {
+        this.players = Arrays.stream(input.split(DELIMITER_COMMA))
+                .map(String::trim)
+                .map(Player::new)
+                .collect(Collectors.toList());
+    }
+
+    public int count() {
+        return players.size();
+    }
+
+    public List<Player> getPlayers() {
+        return players;
+    }
+}
diff --git a/src/main/java/ladder/view/input/BaseInputView.java b/src/main/java/ladder/view/input/BaseInputView.java
new file mode 100644
index 0000000000..0f42246b76
--- /dev/null
+++ b/src/main/java/ladder/view/input/BaseInputView.java
@@ -0,0 +1,4 @@
+package ladder.view.input;
+
+public abstract class BaseInputView implements InputView {
+}
diff --git a/src/main/java/ladder/view/input/ConsoleInputView.java b/src/main/java/ladder/view/input/ConsoleInputView.java
new file mode 100644
index 0000000000..6a3ee81a60
--- /dev/null
+++ b/src/main/java/ladder/view/input/ConsoleInputView.java
@@ -0,0 +1,24 @@
+package ladder.view.input;
+
+import java.util.Scanner;
+
+public class ConsoleInputView extends BaseInputView {
+    private static final Scanner scanner = new Scanner(System.in);
+
+    @Override
+    public String read() {
+        return scanner.nextLine();
+    }
+
+    @Override
+    public String inputPlayerNames() {
+        System.out.println("참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)");
+        return read();
+    }
+
+    @Override
+    public int inputLadderHeight() {
+        System.out.println("최대 사다리 높이는 몇 개인가요?");
+        return Integer.parseInt(read());
+    }
+}
diff --git a/src/main/java/ladder/view/input/InputView.java b/src/main/java/ladder/view/input/InputView.java
new file mode 100644
index 0000000000..89003d96ef
--- /dev/null
+++ b/src/main/java/ladder/view/input/InputView.java
@@ -0,0 +1,7 @@
+package ladder.view.input;
+
+public interface InputView {
+    String read();
+    String inputPlayerNames();
+    int inputLadderHeight();
+}
diff --git a/src/main/java/ladder/view/output/OutputView.java b/src/main/java/ladder/view/output/OutputView.java
new file mode 100644
index 0000000000..e93f5c27f2
--- /dev/null
+++ b/src/main/java/ladder/view/output/OutputView.java
@@ -0,0 +1,36 @@
+package ladder.view.output;
+
+import ladder.domain.ladder.Ladder;
+import ladder.domain.ladder.Line;
+import ladder.domain.ladder.Point;
+import ladder.domain.player.Players;
+
+public class OutputView {
+
+    public static void printResult(Players players, Ladder ladder) {
+        System.out.println("\n실행결과\n");
+
+        printPlayerNames(players);
+        printLadder(ladder);
+    }
+
+    private static void printPlayerNames(Players players) {
+        players.getPlayers()
+                .forEach(p -> System.out.printf("%-6s", p.getName()));
+        System.out.println();
+    }
+
+    private static void printLadder(Ladder ladder) {
+        ladder.getLines().forEach(OutputView::printLine);
+    }
+
+    private static void printLine(Line line) {
+        StringBuilder sb = new StringBuilder();
+        for (Point point : line.getPoints()) {
+            sb.append("|").append(point.hasLine() ? "-----" : "     ");
+        }
+        sb.append("|");
+        System.out.println(sb);
+    }
+
+}
diff --git a/src/test/java/ladder/domain/player/PlayerTest.java b/src/test/java/ladder/domain/player/PlayerTest.java
new file mode 100644
index 0000000000..d601abfa94
--- /dev/null
+++ b/src/test/java/ladder/domain/player/PlayerTest.java
@@ -0,0 +1,26 @@
+package ladder.domain.player;
+
+import ladder.view.fake.FakeInputView;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
+
+class PlayerTest {
+
+    @Test
+    @DisplayName("참여자의 이름이 5글자가 넘으면 예외가 발생한다.")
+    void getPlayerName() {
+        FakeInputView inputView = new FakeInputView("yeseul");
+        assertThatThrownBy(() -> new Player(inputView.inputPlayerNames()))
+                .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    @DisplayName("참여자의 이름은 쉼표가 아닌 다른 구분자가 사용되면 예외가 발생한다.")
+    void getSplitter() {
+        FakeInputView inputView = new FakeInputView("yeseul,pobi|crong");
+        assertThatThrownBy(() -> new Players(inputView.inputPlayerNames()))
+                .isInstanceOf(IllegalArgumentException.class);
+    }
+}
diff --git a/src/test/java/ladder/view/fake/FakeInputView.java b/src/test/java/ladder/view/fake/FakeInputView.java
new file mode 100644
index 0000000000..b77941de12
--- /dev/null
+++ b/src/test/java/ladder/view/fake/FakeInputView.java
@@ -0,0 +1,27 @@
+package ladder.view.fake;
+
+import ladder.view.input.BaseInputView;
+
+public class FakeInputView extends BaseInputView {
+
+    private final String input;
+
+    public FakeInputView(String input) {
+        this.input = input;
+    }
+
+    @Override
+    public String read() {
+        return input.trim();
+    }
+
+    @Override
+    public String inputPlayerNames() {
+        return this.input;
+    }
+
+    @Override
+    public int inputLadderHeight() {
+        return Integer.parseInt(this.input);
+    }
+}