Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 8 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
# Readme

## 프로젝트 소개
![title_image](./readme/wide.png)

### 문제 인식
## 서비스 개요

2010년대 유행한 BNPL(Buy Now, Pay Later) 서비스는 선구매 후결제의 편리함을 제공했지만, 연체와 부채 증가라는 구조적 한계가 드러났습니다. 이에 따라 2020년대에는 **SNPL(Save
Now, Pay Later)**, 즉 ‘저축을 통한 지불’이라는 새로운 개념이 등장했습니다. 이는 보상과 건전한 소비 습관을 중시하는 MZ세대의 성향과 잘 맞는 방식입니다.

한편, 리처드 탈러 박사의 ‘심리적 회계’ 이론에 따르면 사람들은 돈을 단순한 총액으로 보지 않고, 마음속에서 ‘저축’, ‘여행비’, ‘투자금’ 등으로 구분하여 관리합니다. 그러나 현실의 금융 계좌는 대부분 단일
구조로 되어 있어, 마음속의 구분이 실제 금융 관리로는 이어지지 못하고 자금의 흐름이 불명확해지는 문제가 있습니다.

### 만들게 된 계기

저희 팀은 이러한 한계를 해결하기 위해, **심리적 회계 개념을 반영한 개인 맞춤형 금융 관리 서비스의 필요성**을 느꼈습니다. 특히 MZ세대의 ‘미닝아웃 소비’나 ‘YONO(You Only Need One)족’과
같은 현상은 개인의 가치관과 목적이 소비에 직접 반영된다는 점에서 SNPL의 철학과 맞닿아 있다고 생각했습니다.

하지만 기존 시중 은행이나 대중적인 금융 플랫폼에서는 이러한 심리적·행동적 특성을 충분히 반영한 서비스를 찾아보기 어려웠습니다.

이에 저희는 **MZ세대의 심리적 회계 구조를 실제 금융 계좌 설계에 녹여낸 서비스, PLANIT을 기획하게 되었습니다.**
PLANIT은 ‘심리적 회계’ 이론에서 착안한 목표지향 자산관리 서비스입니다.
사람들이 마음속으로는 자금을 ‘여행비’, ‘저축’, ‘투자금’처럼 나누어 관리하지만,
실제 금융 계좌에서는 이를 구분하기 어렵다는 점에서 아이디어를 얻었습니다.
PLANIT은 사용자가 목표별로 자산을 시각화·분리 관리할 수 있도록 도와
‘Save Now, Pay Later’ — 저축을 통한 실현 문화를 제안합니다.
MZ세대의 가치소비와 자기주도적 금융습관 형성을 지향합니다.

## 상세 기능

Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dependencies {
{ exclude group: 'commons-logging', module: 'commons-logging' }
implementation "org.springframework:spring-webmvc:${springVersion}"
implementation 'javax.inject:javax.inject:1'
implementation 'org.springframework:spring-aspects:5.3.39'

// AOP
runtimeOnly 'org.aspectj:aspectjrt:1.9.20'
Expand Down
Binary file added readme/wide.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 48 additions & 10 deletions src/main/java/woojooin/planit/global/config/RootConfig.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package woojooin.planit.global.config;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
Expand All @@ -22,6 +25,8 @@
import com.zaxxer.hikari.HikariDataSource;

import lombok.extern.slf4j.Slf4j;
import woojooin.planit.global.config.datasource.RoutingDataSource;
import woojooin.planit.global.enums.DataSourceType;

@Configuration
@PropertySource({"classpath:/application.properties"})
Expand Down Expand Up @@ -53,17 +58,51 @@ public class RootConfig {
@Value("${jdbc.password}")
String password;

@Bean
public DataSource dataSource() {
@Value("${jdbc.master.url}")
private String masterUrl;
@Value("${jdbc.master.username}")
private String masterUsername;
@Value("${jdbc.master.password}")
private String masterPassword;
@Value("${jdbc.slave.url}")
private String slaveUrl;
@Value("${jdbc.slave.username}")
private String slaveUsername;
@Value("${jdbc.slave.password}")
private String slavePassword;

@Bean(name = "masterDataSource")
public DataSource masterDataSource() {
HikariConfig config = new HikariConfig();
config.setDriverClassName(driver);
config.setJdbcUrl(masterUrl);
config.setUsername(masterUsername);
config.setPassword(masterPassword);

log.info("id = {} password = {}", masterUsername, masterPassword);
return new HikariDataSource(config);
}

@Bean(name = "slaveDataSource")
public DataSource slaveDataSource() {
HikariConfig config = new HikariConfig();
config.setDriverClassName(driver);
config.setJdbcUrl(url);
config.setUsername(username);
config.setPassword(password);
config.setJdbcUrl(slaveUrl);
config.setUsername(slaveUsername);
config.setPassword(slavePassword);
log.info("id={} password={}", slaveUsername, slavePassword);
return new HikariDataSource(config);
}

HikariDataSource dataSource = new HikariDataSource(config);
return dataSource;
@Bean
public DataSource routingDataSource() {
RoutingDataSource routingDataSource = new RoutingDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceType.MASTER, masterDataSource());
targetDataSources.put(DataSourceType.SLAVE, slaveDataSource());
routingDataSource.setTargetDataSources(targetDataSources);
routingDataSource.setDefaultTargetDataSource(masterDataSource());
return routingDataSource;
}

@Autowired
Expand All @@ -74,17 +113,16 @@ public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
sqlSessionFactory.setConfigLocation(
applicationContext.getResource("classpath:/mybatis-config.xml"));
sqlSessionFactory.setDataSource(dataSource());

sqlSessionFactory.setMapperLocations(
applicationContext.getResources("classpath:/mapper/**/*.xml"));
sqlSessionFactory.setDataSource(routingDataSource());

return (SqlSessionFactory)sqlSessionFactory.getObject();
}

@Bean
public DataSourceTransactionManager transactionManager() {
DataSourceTransactionManager manager = new DataSourceTransactionManager(dataSource());
DataSourceTransactionManager manager = new DataSourceTransactionManager(routingDataSource());
return manager;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package woojooin.planit.global.config.datasource;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import woojooin.planit.global.enums.DataSourceType;

@Aspect
@Component
public class DataSourceAspect {

@Before("@annotation(woojooin.planit.global.config.datasource.ReadOnly)")
public void setReadDataSource() {
DataSourceContextHolder.set(DataSourceType.SLAVE);
}

@After("@annotation(woojooin.planit.global.config.datasource.ReadOnly)")
public void clearDataSource() {
DataSourceContextHolder.clear();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package woojooin.planit.global.config.datasource;

import woojooin.planit.global.enums.DataSourceType;

public class DataSourceContextHolder {

private static final ThreadLocal<DataSourceType> contextHolder = new ThreadLocal<>();

public static void set(DataSourceType type) {
contextHolder.set(type);
}

public static DataSourceType get() {
return contextHolder.get() == null ? DataSourceType.MASTER : contextHolder.get();
}

public static void clear() {
contextHolder.remove();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package woojooin.planit.global.config.datasource;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ReadOnly {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package woojooin.planit.global.config.datasource;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class RoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package woojooin.planit.global.enums;

public enum DataSourceType {
MASTER, SLAVE;
}