Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5408b50
tset: Score ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
soohyun1904 Apr 5, 2026
01889ed
feat: Score ๊ฐ์ฒด ์ถ”๊ฐ€
soohyun1904 Apr 5, 2026
da42f3a
feat: PieceName ์ถ”๊ฐ€
soohyun1904 Apr 5, 2026
ecb018e
feat: MoveStrategy ๊ตฌํ˜„์ฒด ์‹ฑ๊ธ€ํ†ค ์ถ”๊ฐ€
soohyun1904 Apr 5, 2026
87cd305
refactor: Position, Row, Column ์ˆ˜์ •
soohyun1904 Apr 2, 2026
2c46551
test: Direction ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
soohyun1904 Apr 6, 2026
3299b54
feat: Direction ๊ฐ์ฒด ๊ธฐ๋Šฅ ์ถ”๊ฐ€
soohyun1904 Apr 6, 2026
7e0b9ae
test: Position, Row, Column ์ƒ์„ฑ์ž ์ˆ˜์ •์œผ๋กœ ์ธํ•œ ํ…Œ์ŠคํŠธ ๋ณ€๊ฒฝ
soohyun1904 Apr 6, 2026
c62cb1e
test: ๊ถ์„ฑ(Palace, Palaces) ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
soohyun1904 Apr 6, 2026
f2ee335
feat: ๊ถ์„ฑ(Palace, Palaces) ๊ฐ์ฒด ์ถ”๊ฐ€
soohyun1904 Apr 6, 2026
ad64c77
test: ๊ธฐ๋ฌผ ์›€์ง์ž„ ๊ถ์„ฑ ํŒ๋‹จ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
soohyun1904 Apr 7, 2026
14ab1d0
feat: ๊ธฐ๋ฌผ ๊ถ์„ฑ ๋‚ด๋ถ€ ์›€์ง์ž„ ์ถ”๊ฐ€
soohyun1904 Apr 7, 2026
8f2aa8e
test: ๊ถ์„ฑ ๋‚ด๋ถ€ ํŒ๋‹จ(false) ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
soohyun1904 Apr 7, 2026
2d69e86
refactor: ์ด๋™ ์ „๋žต ๊ฐ์ฒด ์ˆ˜์ •์œผ๋กœ ์ธํ•œ ๋ณ€๊ฒฝ
soohyun1904 Apr 7, 2026
ce02030
test: ๊ธฐ๋ฌผ(Piece) ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
soohyun1904 Apr 7, 2026
6123d3b
feat: ๊ธฐ๋ฌผ(Piece) ๊ธฐ๋Šฅ ์ถ”๊ฐ€
soohyun1904 Apr 7, 2026
292c307
test: ๋ณด๋“œ(Board) ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
soohyun1904 Apr 7, 2026
19c2224
feat: ๋‚˜๋ผ ๋ณ„ ์™• ํ™•์ธ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
soohyun1904 Apr 7, 2026
e26aa53
feat: ์ข…๋ฃŒ ์ถ”๊ฐ€
soohyun1904 Apr 7, 2026
7043892
chore: .gitignore ์—…๋ฐ์ดํŠธ
soohyun1904 Apr 7, 2026
554e7dc
test: Score ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
soohyun1904 Apr 8, 2026
a2b564e
feat: ์ ์ˆ˜(Score) ๋ฐฐ์œจ ๊ณฑํ•˜๋Š” ๊ธฐ๋Šฅ ์ถ”๊ฐ€
soohyun1904 Apr 8, 2026
b6bf6fc
test: Board ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
soohyun1904 Apr 8, 2026
c8dd20d
feat: ๋ณด๋“œ(board) ์ ์ˆ˜ ํŒ๋‹จ ํ›„ ์ŠนํŒจ ํŒ๋‹จ ๋กœ์ง ์ถ”๊ฐ€
soohyun1904 Apr 8, 2026
a760d34
feat: ํ•ญ๋ณต, ๋ฌด์Šน๋ถ€ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
soohyun1904 Apr 8, 2026
ec2f413
chore: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค SQL ์˜์กด์„ฑ, properties, sql ์ถ”๊ฐ€,
soohyun1904 Apr 9, 2026
fa07793
feat: ๊ธฐ๋ฌผ(Piece), ๋งˆ์ƒ ๋ฐฐ์น˜ ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค ์ถ”๊ฐ€
soohyun1904 Apr 9, 2026
0716a11
feat: DB ์กฐํšŒ, ์‚ญ์ œ, ์‚ฝ์ž…์„ ์œ„ํ•œ Entity ์ถ”๊ฐ€
soohyun1904 Apr 9, 2026
f34508b
chore: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์„ค์ • ๋ฐ SQL ํ™˜๊ฒฝ ๊ตฌ์ถ•
soohyun1904 Apr 9, 2026
fc618fe
feat: ์—”ํ‹ฐํ‹ฐ mapper ์ถ”๊ฐ€
soohyun1904 Apr 9, 2026
bd152a2
feat: ๊ธฐ๋ฌผ, ๊ฒŒ์ž„ Dao ์ถ”๊ฐ€
soohyun1904 Apr 9, 2026
564cb77
feat: ์žฅ๊ธฐ ์„œ๋น„์Šค, ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ถ”๊ฐ€
soohyun1904 Apr 9, 2026
63e91d9
feat: ์œ ๋‹ˆํฌ ์ปฌ๋Ÿผ ์กฐํฌ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ์ถ”๊ฐ€
soohyun1904 Apr 9, 2026
c736386
refactor: Db, ์„œ๋น„์Šค ์ถ”๊ฐ€๋กœ ์ธํ•œ ์ „์ฒด์ ์ธ ์ˆ˜์ •
soohyun1904 Apr 9, 2026
38e8eb6
test: ์žฅ๊ธฐ ํ…Œใ…กํŠธ ์ถ”์ •
soohyun1904 Apr 9, 2026
2c07af8
refacotor: mapper ๋ฉ”์†Œ๋„ ๋ช…์‹œ์ ์œผ๋กœ ์ˆ˜์ •
soohyun1904 Apr 11, 2026
c81ae57
feat: ๊ฒŒ์ž„ ์ด๋ฆ„ ๊ฒ€์ฆ ์ถ”๊ฐ€
soohyun1904 Apr 11, 2026
885234f
refactor: ์ปจํŠธ๋กค๋Ÿฌ loadGame์—์„œ ์ด๋ฆ„ ๊ฒ€์ฆ ์‚ญ์ œ
soohyun1904 Apr 11, 2026
c0bb5bd
feat: ๊ฒŒ์ž„ ์‚ญ์ œ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
soohyun1904 Apr 11, 2026
5fe3ce9
feat: ํŠธ๋žœ์žญ์…˜, ์ปค๋„ฅ์…˜ ํ’€ ์ถ”๊ฐ€
soohyun1904 Apr 12, 2026
5cd0a6b
test: dao, repository ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
soohyun1904 Apr 12, 2026
7788a7d
refactor: ์ƒ์„ฑ ์‹œ ์ค‘๋ณต๋œ ์ด๋ฆ„ ์ฒดํฌ ์ถ”๊ฐ€
soohyun1904 Apr 12, 2026
ae704c3
refactor: ๊ฐ ๊ณ„์ธต ๋ณ„ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ์™„ํ™”
soohyun1904 Apr 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ out/

### VS Code ###
.vscode/
src/main/resources/application.properties
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ dependencies {
testImplementation platform('org.assertj:assertj-bom:3.27.3')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.assertj:assertj-core')

implementation 'com.mysql:mysql-connector-j:9.3.0'
testImplementation 'com.h2database:h2:2.2.224'
}

java {
Expand Down
20 changes: 20 additions & 0 deletions init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- 1. ๊ฒŒ์ž„ ํ…Œ์ด๋ธ” (๋ฉ”ํƒ€๋ฐ์ดํ„ฐ)
CREATE TABLE game (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(50) NOT NULL UNIQUE,
status VARCHAR(20) NOT NULL, -- PLAYING, CHO_WIN, HAN_WIN, DRAW
current_turn VARCHAR(10) NOT NULL -- CHO, HAN
);

-- 2. ๊ธฐ๋ฌผ ์ƒํƒœ ํ…Œ์ด๋ธ” (1๋ฒˆ ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐ)
CREATE TABLE piece (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
game_id VARCHAR(36) NOT NULL, -- ์–ด๋–ค ๊ฒŒ์ž„ํŒ์— ์†ํ•ด์žˆ๋Š”์ง€ (FK)
piece_name VARCHAR(20) NOT NULL, -- CHO_SOLDIER, HAN_CHARIOT ๋“ฑ
camp VARCHAR(3) NOT NULL,
row_index INT NOT NULL, -- Y ์ขŒํ‘œ (0~9)
column_index INT NOT NULL, -- X ์ขŒํ‘œ (0~8)


FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
49 changes: 48 additions & 1 deletion src/main/java/janggi/config/AppConfig.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,58 @@
package janggi.config;

import janggi.controller.JanggiController;
import janggi.persistence.GameRepositoryImpl;
import janggi.persistence.dao.GameDao;
import janggi.persistence.dao.JdbcGameDao;
import janggi.persistence.dao.JdbcPieceDao;
import janggi.persistence.dao.PieceDao;
import janggi.persistence.mapper.GameMapper;
import janggi.persistence.mapper.PieceMapper;
import janggi.service.GameRepository;
import janggi.service.JanggiService;
import janggi.view.InputView;
import janggi.view.OutputView;

public class AppConfig {
private final ConnectionPool connectionPool = DatabaseConfig.getPool();

public JanggiController janggiController() {
return new JanggiController(new InputView(), new OutputView());
return new JanggiController(inputView(), outputView(), janggiService());
}

public InputView inputView() {
return new InputView();
}

public OutputView outputView() {
return new OutputView();
}

public JanggiService janggiService() {
return new JanggiService(gameRepository(), transactionManager());
}

public TransactionManager transactionManager() {
return new TransactionManager(connectionPool);
}

public GameRepository gameRepository() {
return new GameRepositoryImpl(gameDao(), pieceDao(), gameMapper(), pieceMapper());
}

public GameDao gameDao() {
return new JdbcGameDao(connectionPool);
}

public PieceDao pieceDao() {
return new JdbcPieceDao(connectionPool);
}

public GameMapper gameMapper() {
return new GameMapper();
}

public PieceMapper pieceMapper() {
return new PieceMapper();
}
}
99 changes: 99 additions & 0 deletions src/main/java/janggi/config/ConnectionPool.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package janggi.config;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

public class ConnectionPool {
private final BlockingQueue<Connection> pool;
private final String url;
private final String username;
private final String password;
private final long timeoutMillis;

private final int poolSize;

ConnectionPool(String url, String username, String password, int poolSize) {
this.url = url;
this.username = username;
this.password = password;
this.timeoutMillis = 5000;
this.poolSize = poolSize;

this.pool = new ArrayBlockingQueue<>(this.poolSize);

try {
for (int i = 0; i < this.poolSize; i++) {
pool.offer(createConnection());
}
} catch (SQLException e) {
throw new RuntimeException("์ปค๋„ฅ์…˜ ํ’€ ์ดˆ๊ธฐํ™” ์‹คํŒจ", e);
}
}

private Connection createConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}

public Connection getConnection() {
try {
Connection conn = pool.poll(timeoutMillis, TimeUnit.MILLISECONDS);
if (conn == null) {
throw new RuntimeException("์ปค๋„ฅ์…˜ ํš๋“ ๋Œ€๊ธฐ ์‹œ๊ฐ„ ์ดˆ๊ณผ (Timeout)");
}

if (!conn.isValid(1)) {
try {
conn.close();
} catch (SQLException ignored) {}
conn = createConnection();
}

return conn;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("์ปค๋„ฅ์…˜ ๋Œ€๊ธฐ ์ค‘ ์ธํ„ฐ๋ŸฝํŠธ ๋ฐœ์ƒ", e);
} catch (SQLException e) {
throw new RuntimeException("์œ ํšจํ•˜์ง€ ์•Š์€ ์ปค๋„ฅ์…˜ ์žฌ์„ค์ • ๋ฐ ๊ฒ€์ฆ ์‹คํŒจ", e);
}
}

public void release(Connection conn) {
if (conn != null) {
try {
if (!conn.isClosed()) {
conn.setAutoCommit(true);
pool.offer(conn);
}
} catch (SQLException e) {
try {
conn.close();
} catch (SQLException ignored) {}
}
}
}

public void shutdown() {
Connection conn;
while ((conn = pool.poll()) != null) {
try {
conn.close();
} catch (SQLException ignored) {}
}
}

public PooledConnection getPooledConnection() {
return new PooledConnection(getConnection(), this);
}

public int getAvailableCount() {
return pool.size();
}

public int getActiveCount() {
return poolSize - pool.size();
}
}
42 changes: 42 additions & 0 deletions src/main/java/janggi/config/DatabaseConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package janggi.config;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

public class DatabaseConfig {
private static final Properties properties = new Properties();
private static final ConnectionPool connectionPool;

static {
try (InputStream input = DatabaseConfig.class.getResourceAsStream("/application.properties")) {
if (input == null) {
throw new RuntimeException("application.properties ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
}
properties.load(input);
} catch (Exception e) {
throw new RuntimeException("JDBC ์ดˆ๊ธฐํ™” ์‹คํŒจ", e);
}

connectionPool = new ConnectionPool(
properties.getProperty("db.url"),
properties.getProperty("db.id"),
properties.getProperty("db.password"),
5
);
}

public static void shutdown() {
connectionPool.shutdown();
}

public static PooledConnection getConnection() {
return connectionPool.getPooledConnection();
}

public static ConnectionPool getPool() {
return connectionPool;
}
}
22 changes: 22 additions & 0 deletions src/main/java/janggi/config/PooledConnection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package janggi.config;

import java.sql.Connection;

public class PooledConnection implements AutoCloseable{
private final Connection conn;
private final ConnectionPool pool;

PooledConnection(Connection conn, ConnectionPool pool) {
this.conn = conn;
this.pool = pool;
}

public Connection getConnection() {
return conn;
}

@Override
public void close() {
pool.release(conn);
}
}
9 changes: 9 additions & 0 deletions src/main/java/janggi/config/TransactionCallback.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package janggi.config;

import java.sql.Connection;
import java.sql.SQLException;

@FunctionalInterface
public interface TransactionCallback<T> {
T run(Connection conn) throws SQLException;
}
28 changes: 28 additions & 0 deletions src/main/java/janggi/config/TransactionManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package janggi.config;

import java.sql.Connection;
import java.sql.SQLException;

public class TransactionManager {
private final ConnectionPool pool;

public TransactionManager(ConnectionPool pool) {
this.pool = pool;
}

public <T> T execute(TransactionCallback<T> callback) {
PooledConnection pooledConn = pool.getPooledConnection();
Connection conn = pooledConn.getConnection();
try {
conn.setAutoCommit(false);
T result = callback.run(conn);
conn.commit();
return result;
} catch (Exception e) {
try { conn.rollback(); } catch (SQLException ignored) {}
throw new RuntimeException("ํŠธ๋žœ์žญ์…˜ ์‹คํ–‰ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.", e);
} finally {
pooledConn.close();
}
}
}
Loading