diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..48fc681 --- /dev/null +++ b/.env.example @@ -0,0 +1,41 @@ +# Database Configuration +DB_HOST= +DB_PORT= +DB_NAME= +DB_USERNAME= +DB_PASSWORD= + +# Spring Profile +SPRING_PROFILES_ACTIVE= + +# OAuth - Kakao +KAKAO_CLIENT_ID= +KAKAO_CLIENT_SECRET= +KAKAO_REDIRECT_URI= +KAKAO_NATIVE_CLIENT_ID= + +# OAuth - Google +GOOGLE_CLIENT_ID= +GOOGLE_CLIENT_SECRET= +GOOGLE_REDIRECT_URI= +GOOGLE_AOD_CLIENT_ID= + +# JWT +JWT_ISSUER= +JWT_SECRET= +JWT_ACCESS_EXPIRATION= +JWT_REFRESH_EXPIRATION= + +# AWS S3 Configuration +AWS_S3_BUCKET_NAME= +AWS_S3_REGION= +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_CLOUDFRONT_DOMAIN= +RESIZE_SECRET_KEY= + +# Public Data Service Key +K_CULTURAL_INFO_CENTER_KEY= + +# FCM +FIREBASE_CONFIG_PATH= diff --git a/.gitignore b/.gitignore index b6fed4c..41220b4 100644 --- a/.gitignore +++ b/.gitignore @@ -40,18 +40,10 @@ out/ /db !/resources/db/*.sql mongodb -/src/main/resources/application.yml -/src/main/resources/application-dev.yml -/src/main/resources/application-stage.yml -/src/main/resources/application-prod.yml + .DS_Store elasticsearch/ .cursorrules -application-stageing.yml -application-stage.yml -application-production.yml -application-prod.yml -application-local.yml !/docker/elasticsearch /src/main/resources/firebase/ diff --git a/build.gradle b/build.gradle index 64251d2..ffd3086 100644 --- a/build.gradle +++ b/build.gradle @@ -43,12 +43,11 @@ dependencies { testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-data-redis' - implementation 'org.flywaydb:flyway-core' - implementation 'org.flywaydb:flyway-mysql' implementation 'org.springframework.boot:spring-boot-starter-webflux' implementation 'io.github.resilience4j:resilience4j-spring-boot3:2.2.0' implementation 'io.github.resilience4j:resilience4j-reactor:2.2.0' implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml' + implementation 'io.github.cdimascio:java-dotenv:5.2.2' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.9' diff --git a/docker-compose.override.yml b/docker-compose.override.yml deleted file mode 100644 index b3b9fc6..0000000 --- a/docker-compose.override.yml +++ /dev/null @@ -1,80 +0,0 @@ -version: "3.8" - -services: - java: - container_name: backend - build: - context: . - dockerfile: docker/Dockerfile - target: develop - image: artrip-backend:latest - ports: - - ${HTTP_PORT}:8080 - - "35729:35729" - volumes: - - .:/app - - gradle-cache:/home/gradle/.gradle - depends_on: - elasticsearch: - condition: service_healthy - db: - condition: service_started - redis: - condition: service_started - environment: - - SPRING_PROFILES_ACTIVE=local - - SPRING_DEVTOOLS_RESTART_ENABLED=true - - SPRING_DEVTOOLS_LIVERELOAD_ENABLED=true - env_file: - - .env - - db: - image: mysql:8.4 - container_name: db - platform: linux/amd64 - environment: - MYSQL_USER: artrip - MYSQL_ROOT_PASSWORD: artrip1! - MYSQL_DATABASE: artrip - MYSQL_PASSWORD: artrip1! - ports: - - "33069:3306" - volumes: - - ./db/data:/var/lib/mysql - - ./db/conf:/etc/mysql/conf.d - - redis: - image: redis:7.2 - container_name: redis - restart: always - ports: - - "63799:6379" - volumes: - - redis-data:/data - - elasticsearch: - build: - context: ./docker/elasticsearch - args: - ELASTIC_VERSION: 8.11.0 - container_name: elastic - environment: - - discovery.type=single-node - - xpack.security.enabled=false - - xpack.security.http.ssl.enabled=false - - ES_JAVA_OPTS=-Xms1g -Xmx1g - ports: - - "${ELASTICSEARCH_PORT:-9200}:9200" - - "${ELASTICSEARCH_TRANSPORT_PORT:-9300}:9300" - volumes: - - ./elasticsearch/data:/usr/share/elasticsearch/data - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:9200/_cluster/health"] - interval: 10s - timeout: 5s - retries: 5 - start_period: 30s - -volumes: - redis-data: - gradle-cache: \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml deleted file mode 100644 index da7bea2..0000000 --- a/docker-compose.prod.yml +++ /dev/null @@ -1,50 +0,0 @@ -version: "3.8" - -services: - java: - container_name: backend-prod - image: artrip-backend:latest - build: - context: . - dockerfile: docker/Dockerfile - target: production - ports: - - 882:8080 - environment: - - SPRING_PROFILES_ACTIVE=prod - depends_on: - redis: - condition: service_started - elasticsearch: - condition: service_healthy - restart: always - volumes: !reset [] - env_file: - - .env - - - db: !reset {} - redis: !reset {} - - elasticsearch: - build: - context: ./docker/elasticsearch - container_name: elasticsearch-stage - ports: - - "${ELASTICSEARCH_PORT:-9201}:9200" - - "${ELASTICSEARCH_TRANSPORT_PORT:-9301}:9300" - environment: - - ES_JAVA_OPTS=-Xms2g -Xmx2g - - discovery.type=single-node - - xpack.security.enabled=false - - xpack.security.http.ssl.enabled=false - - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:9200/_cluster/health"] - interval: 10s - timeout: 5s - retries: 5 - start_period: 30s - -volumes: - elasticsearch-prod-data: diff --git a/docker-compose.stage.yml b/docker-compose.stage.yml deleted file mode 100644 index 6f78114..0000000 --- a/docker-compose.stage.yml +++ /dev/null @@ -1,51 +0,0 @@ -version: "3.8" - -services: - java: - container_name: backend-stage - image: artrip-backend:latest - build: - context: . - dockerfile: docker/Dockerfile - target: production - ports: - - 881:8080 - environment: - - SPRING_PROFILES_ACTIVE=stage - depends_on: - elasticsearch: - condition: service_healthy - extra_hosts: - - "host.docker.internal:host-gateway" - volumes: - - ${FIREBASE_PATH} - env_file: - - .env - - db: !reset {} - redis: !reset {} - - elasticsearch: - build: - context: ./docker/elasticsearch - container_name: elasticsearch-stage - ports: - - "${ELASTICSEARCH_PORT:-9201}:9200" - - "${ELASTICSEARCH_TRANSPORT_PORT:-9301}:9300" - environment: - - discovery.type=single-node - - xpack.security.enabled=false - - xpack.security.http.ssl.enabled=false - - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:9200/_cluster/health"] - interval: 10s - timeout: 5s - retries: 5 - start_period: 30s - volumes: - - elasticsearch-stage-data:/usr/share/elasticsearch/data - -volumes: - redis-stage-data: - elasticsearch-stage-data: \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index dab5586..29f0bb2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,50 @@ version: "3.8" services: - app: - build: - context: . - dockerfile: docker/Dockerfile + db: + image: mysql:8.4 + container_name: db + platform: linux/amd64 + environment: + MYSQL_USER: artrip + MYSQL_ROOT_PASSWORD: artrip1! + MYSQL_DATABASE: artrip + MYSQL_PASSWORD: artrip1! + ports: + - "33069:3306" + volumes: + - ./db/data:/var/lib/mysql + - ./db/conf:/etc/mysql/conf.d + + redis: + image: redis:7.2 + container_name: redis + restart: always + ports: + - "63799:6379" + volumes: + - redis-data:/data + + elasticsearch: + image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0 + container_name: elastic + environment: + - discovery.type=single-node + - xpack.security.enabled=false + - xpack.security.http.ssl.enabled=false + - ES_JAVA_OPTS=-Xms1g -Xmx1g + ports: + - "9200:9200" + - "9300:9300" + volumes: + - ./elasticsearch/data:/usr/share/elasticsearch/data + healthcheck: + test: [ "CMD", "curl", "-f", "http://localhost:9200/_cluster/health" ] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + + +volumes: + redis-data: \ No newline at end of file diff --git a/docker/elasticsearch/Dockerfile b/docker/elasticsearch/Dockerfile deleted file mode 100644 index 7660434..0000000 --- a/docker/elasticsearch/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -# Elasticsearch with Nori (Korean analyzer) plugin -ARG ELASTIC_VERSION - -# https://www.docker.elastic.co/ -FROM docker.elastic.co/elasticsearch/elasticsearch:${ELASTIC_VERSION:-8.11.0} - -RUN bin/elasticsearch-plugin install --batch analysis-nori - -#ENTRYPOINT ["/entrypoint.sh"] diff --git a/src/main/java/org/atdev/artrip/Application.java b/src/main/java/org/atdev/artrip/Application.java index 36453b0..82e50b8 100644 --- a/src/main/java/org/atdev/artrip/Application.java +++ b/src/main/java/org/atdev/artrip/Application.java @@ -18,39 +18,5 @@ public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } - @Bean - public CommandLineRunner testDb(DataSource dataSource) { - return args -> { - System.out.println("DB 연결 체크 시작"); - try (var conn = dataSource.getConnection()) { - System.out.println("DB 연결 성공!"); - System.out.println("JDBC URL: " + conn.getMetaData().getURL()); - System.out.println("DB 제품: " + conn.getMetaData().getDatabaseProductName()); - System.out.println("DB 버전: " + conn.getMetaData().getDatabaseProductVersion()); - System.out.println("DB 사용자: " + conn.getMetaData().getUserName()); - } catch (Exception e) { - System.err.println("DB 연결 실패!"); - e.printStackTrace(); - } - }; - } - - @Bean - public CommandLineRunner testRedis(StringRedisTemplate jwtRedisTemplate) { - return args -> { - System.out.println("Redis 연결 체크"); - - try { - jwtRedisTemplate.opsForValue().set("testKey", "greeting"); - - String value = jwtRedisTemplate.opsForValue().get("testKey"); - System.out.println("Redis 연결 성공 : " + value); - } catch (Exception e) { - System.err.println("Redis 연결 실패"); - e.printStackTrace(); - } - - }; - } } diff --git a/src/main/java/org/atdev/artrip/config/DataSourceConfig.java b/src/main/java/org/atdev/artrip/config/DataSourceConfig.java new file mode 100644 index 0000000..0d5e1ac --- /dev/null +++ b/src/main/java/org/atdev/artrip/config/DataSourceConfig.java @@ -0,0 +1,44 @@ +package org.atdev.artrip.config; + +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +import javax.sql.DataSource; + +@Configuration(proxyBeanMethods = false) +public class DataSourceConfig { + + @Bean + @Profile("local") + public DataSource localDataSource() { + HikariDataSource dataSource = new HikariDataSource(); + dataSource.setJdbcUrl("jdbc:mysql://localhost:33069/artrip?serverTimezone=Asia/Seoul&useSSL=false&allowPublicKeyRetrieval=true"); + dataSource.setUsername("root"); + dataSource.setPassword("artrip1!"); + return dataSource; + } + + @Bean + @Profile("dev") + public DataSource devDataSource( + @Value("${DB_HOST}") String dbHost, + @Value("${DB_PORT}") int dbPort, + @Value("${DB_NAME}") String dbName, + @Value("${DB_USERNAME}") String username, + @Value("${DB_PASSWORD}") String password + ) { + + HikariDataSource dataSource = new HikariDataSource(); + String jdbcUrl = String.format("jdbc:mysql://%s:%d/%s?serverTimezone=Asia/Seoul&useSSL=false&allowPublicKeyRetrieval=true", + dbHost, dbPort, dbName); + dataSource.setJdbcUrl(jdbcUrl); + dataSource.setUsername(username); + dataSource.setPassword(password); + return dataSource; + + } + +} diff --git a/src/main/java/org/atdev/artrip/config/ElasticsearchConfig.java b/src/main/java/org/atdev/artrip/config/ElasticsearchConfig.java index dc18f4f..aa94135 100644 --- a/src/main/java/org/atdev/artrip/config/ElasticsearchConfig.java +++ b/src/main/java/org/atdev/artrip/config/ElasticsearchConfig.java @@ -16,12 +16,9 @@ @Configuration public class ElasticsearchConfig { - @Value("${spring.elasticsearch.uris}") - private String elasticsearchUris; - @Bean public RestClient restClient() { - return RestClient.builder(HttpHost.create(elasticsearchUris)).build(); + return RestClient.builder(new HttpHost("localhost", 9200)).build(); } @Bean diff --git a/src/main/java/org/atdev/artrip/config/SecurityConfig.java b/src/main/java/org/atdev/artrip/config/SecurityConfig.java index a312513..e8db359 100644 --- a/src/main/java/org/atdev/artrip/config/SecurityConfig.java +++ b/src/main/java/org/atdev/artrip/config/SecurityConfig.java @@ -4,9 +4,9 @@ import lombok.RequiredArgsConstructor; import org.atdev.artrip.service.CustomOAuth2UserService; import org.atdev.artrip.security.OAuth2LoginSuccessHandler; -import org.atdev.artrip.jwt.jwt.JwtAuthenticationFilter; -import org.atdev.artrip.jwt.jwt.JwtProvider; -import org.atdev.artrip.jwt.jwt.exception.JwtExceptionFilter; +import org.atdev.artrip.jwt.JwtAuthenticationFilter; +import org.atdev.artrip.jwt.JwtProvider; +import org.atdev.artrip.jwt.exception.JwtExceptionFilter; import org.atdev.artrip.global.apipayload.exception.handler.JwtAccessDeniedHandler; import org.atdev.artrip.global.apipayload.exception.handler.JwtAuthenticationEntryPoint; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/org/atdev/artrip/domain/curation/Curation.java b/src/main/java/org/atdev/artrip/domain/curation/Curation.java index 25c8c02..97c55f0 100644 --- a/src/main/java/org/atdev/artrip/domain/curation/Curation.java +++ b/src/main/java/org/atdev/artrip/domain/curation/Curation.java @@ -31,9 +31,11 @@ public class Curation { @Column(name = "curation_type", nullable = false) private CurationType curationType; + @Builder.Default @Column(name = "is_active") private boolean isActive = true; + @Builder.Default @ManyToMany @JoinTable( name = "curation_exhibit", diff --git a/src/main/java/org/atdev/artrip/elastic/service/ExhibitIndexService.java b/src/main/java/org/atdev/artrip/elastic/service/ExhibitIndexService.java index ea9dc59..87d4a9b 100644 --- a/src/main/java/org/atdev/artrip/elastic/service/ExhibitIndexService.java +++ b/src/main/java/org/atdev/artrip/elastic/service/ExhibitIndexService.java @@ -96,7 +96,7 @@ public void createAndApplyIndex() { ) .analyzer("ngram_nori_analyzer", an -> an .custom(ca -> ca - .tokenizer("nori_tokenizer") + .tokenizer("standard") .filter("lowercase", "ngram_filter") ) ) diff --git a/src/main/java/org/atdev/artrip/jwt/JwtGenerator.java b/src/main/java/org/atdev/artrip/jwt/JwtGenerator.java index e397aeb..e402f62 100644 --- a/src/main/java/org/atdev/artrip/jwt/JwtGenerator.java +++ b/src/main/java/org/atdev/artrip/jwt/JwtGenerator.java @@ -2,8 +2,8 @@ import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; -import org.atdev.artrip.domain.Enum.Role; -import org.atdev.artrip.domain.auth.data.User; +import org.atdev.artrip.constants.Role; +import org.atdev.artrip.domain.auth.User; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; diff --git a/src/main/java/org/atdev/artrip/repository/ExhibitRepositoryImpl.java b/src/main/java/org/atdev/artrip/repository/ExhibitRepositoryImpl.java index 7804737..6c95c7c 100644 --- a/src/main/java/org/atdev/artrip/repository/ExhibitRepositoryImpl.java +++ b/src/main/java/org/atdev/artrip/repository/ExhibitRepositoryImpl.java @@ -10,12 +10,12 @@ import org.atdev.artrip.constants.SortType; import org.atdev.artrip.constants.Status; import org.atdev.artrip.domain.exhibit.Exhibit; -import org.atdev.artrip.domain.exhibit.data.QExhibit; +import org.atdev.artrip.domain.exhibit.QExhibit; import org.atdev.artrip.controller.dto.request.ExhibitFilterRequest; -import org.atdev.artrip.domain.exhibitHall.data.QExhibitHall; +import org.atdev.artrip.domain.exhibitHall.QExhibitHall; import org.atdev.artrip.controller.dto.response.HomeListResponse; import org.atdev.artrip.controller.dto.request.RandomExhibitRequest; -import org.atdev.artrip.domain.keyword.data.QKeyword; +import org.atdev.artrip.domain.keyword.QKeyword; import org.springframework.data.domain.*; import org.springframework.stereotype.Repository; diff --git a/src/main/java/org/atdev/artrip/security/OAuth2LoginSuccessHandler.java b/src/main/java/org/atdev/artrip/security/OAuth2LoginSuccessHandler.java index f972cce..dfac000 100644 --- a/src/main/java/org/atdev/artrip/security/OAuth2LoginSuccessHandler.java +++ b/src/main/java/org/atdev/artrip/security/OAuth2LoginSuccessHandler.java @@ -6,9 +6,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.atdev.artrip.domain.oauth.OAuth2UserInfo; -import org.atdev.artrip.jwt.jwt.JwtGenerator; -import org.atdev.artrip.jwt.jwt.JwtToken; -import org.atdev.artrip.jwt.jwt.repository.RefreshTokenRedisRepository; +import org.atdev.artrip.jwt.JwtGenerator; +import org.atdev.artrip.jwt.JwtToken; +import org.atdev.artrip.jwt.repository.RefreshTokenRedisRepository; import org.atdev.artrip.constants.Provider; import org.atdev.artrip.domain.auth.User; import org.atdev.artrip.repository.UserRepository; diff --git a/src/main/java/org/atdev/artrip/service/AuthService.java b/src/main/java/org/atdev/artrip/service/AuthService.java index 97db222..2614b93 100644 --- a/src/main/java/org/atdev/artrip/service/AuthService.java +++ b/src/main/java/org/atdev/artrip/service/AuthService.java @@ -16,10 +16,10 @@ import org.atdev.artrip.constants.Role; import org.atdev.artrip.domain.auth.SocialAccounts; import org.atdev.artrip.domain.auth.User; -import org.atdev.artrip.jwt.jwt.JwtGenerator; -import org.atdev.artrip.jwt.jwt.JwtProvider; -import org.atdev.artrip.jwt.jwt.JwtToken; -import org.atdev.artrip.jwt.jwt.repository.RefreshTokenRedisRepository; +import org.atdev.artrip.jwt.JwtGenerator; +import org.atdev.artrip.jwt.JwtProvider; +import org.atdev.artrip.jwt.JwtToken; +import org.atdev.artrip.jwt.repository.RefreshTokenRedisRepository; import org.atdev.artrip.repository.UserRepository; import org.atdev.artrip.controller.dto.request.ReissueRequest; import org.atdev.artrip.controller.dto.response.SocialLoginResponse; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..7ed2ea1 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,177 @@ +spring: + application: + name: artrip + profiles: + active: local + config: + import: optional:file:.env[.properties] + + servlet: + multipart: + max-file-size: 2MB + max-request-size: 10MB + + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + hikari: + connection-timeout: 30000 + maximum-pool-size: 10 + minimum-idle: 5 + + jpa: + database: mysql + database-platform: org.hibernate.dialect.MySQLDialect + + cloud: + aws: + credentials: + access-key: ${AWS_ACCESS_KEY_ID} + secret-key: ${AWS_SECRET_ACCESS_KEY} + region: + static: ${AWS_S3_REGION} + auto: false + s3: + bucket: ${AWS_S3_BUCKET_NAME} + cloudfront: + domain: ${AWS_CLOUDFRONT_DOMAIN} + + security: + oauth2: + client: + registration: + kakao: + client-authentication-method: client_secret_post + client-id: ${KAKAO_CLIENT_ID} + client-secret: ${KAKAO_CLIENT_SECRET} + native-client-id: ${KAKAO_NATIVE_CLIENT_ID} + authorization-grant-type: authorization_code + scope: profile_nickname, account_email + client-name: Kakao + + google: + client-id: ${GOOGLE_CLIENT_ID} + client-secret: ${GOOGLE_CLIENT_SECRET} + aod-client-id: ${GOOGLE_AOD_CLIENT_ID} + authorization-grant-type: authorization_code + scope: + - profile + - email + client-name: Google + + provider: + kakao: + authorization-uri: https://kauth.kakao.com/oauth/authorize + token-uri: https://kauth.kakao.com/oauth/token + user-info-uri: https://kapi.kakao.com/v2/user/me + user-name-attribute: id + google: + authorization-uri: https://accounts.google.com/o/oauth2/v2/auth + token-uri: https://oauth2.googleapis.com/token + user-info-uri: https://www.googleapis.com/oauth2/v3/userinfo + user-name-attribute: sub + + jwt: + issuer: ${JWT_ISSUER} + secret: ${JWT_SECRET} + access-token-expiration-millis: 900000 + refresh-token-expiration-millis: 604800000 + task: + scheduling: + pool: + size: 5 + thread-name-prefix: scheduling- + +firebase: + credentials: + path: ${FIREBASE_CONFIG_PATH} + +external: + culturalapi: + base-url: https://apis.data.go.kr/B553457/cultureinfo + service-key: ${K_CULTURAL_INFO_CENTER_KEY} + connect-timeout: 5000 + read-timeout: 60000 + page-size: 50 + +resilience4j: + retry: + instances: + publicDataApi: + max-attempts: 3 + wait-duration: 2s + retry-exceptions: + - java.io.IOException + - java.util.concurrent.TimeoutException + - org.springframework.web.reactive.function.client.WebClientResponseException$ServiceUnavailable + +image: + upload: + max-size: 2097152 + allowed-extensions: jpg,jpeg,png,webp + resize: + secret-key: ${RESIZE_SECRET_KEY} +--- +spring: + config: + activate: + on-profile: local + + jpa: + hibernate: + ddl-auto: update + + data: + redis: + host: localhost + port: 63799 + + security: + oauth2: + client: + registration: + kakao: + redirect-uri: http://localhost:8080/login/oauth2/code/kakao + google: + redirect-uri: http://localhost:8080/login/oauth2/code/google + +logging: + level: + org.atdev.artrip: DEBUG + io.lettuce: WARN + co.elastic: WARN # Elasticsearch 제외 후 제거 예정 + +server: + port: 8080 + +--- +spring: + config: + activate: + on-profile: dev + + jpa: + hibernate: + ddl-auto: update + show-sql: false + + data: + redis: + host: localhost + port: 63799 + + security: + oauth2: + client: + registration: + kakao: + redirect-uri: https://dev.coffit.today/login/oauth2/code/kakao + google: + redirect-uri: https://dev.coffit.today/login/oauth2/code/google + +logging: + level: + root: info + org.atdev.artrip: info + +server: + port: 8082 \ No newline at end of file diff --git a/src/main/resources/db/migration/V20251127__init_database.sql b/src/main/resources/db/migration/V20251127__init_database.sql deleted file mode 100644 index f5df891..0000000 --- a/src/main/resources/db/migration/V20251127__init_database.sql +++ /dev/null @@ -1,249 +0,0 @@ --- Migration: init_database --- Created: 2025-11-16 --- --- ======================================== --- Add your DDL statements below --- ======================================== --- -- --- Example: Create table --- CREATE TABLE example ( --- id BIGINT AUTO_INCREMENT PRIMARY KEY, --- name VARCHAR(255) NOT NULL, --- created_at DATETIME(6) NOT NULL --- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; --- -- --- Example: Add column --- ALTER TABLE example ADD COLUMN email VARCHAR(255) NULL; - --- Example: Create index --- CREATE INDEX idx_example_name ON example(name); - -CREATE TABLE `user` ( - `stamp_num` tinyint DEFAULT NULL, - `created_at` datetime(6) NOT NULL, - `updated_at` datetime(6) DEFAULT NULL, - `user_id` bigint NOT NULL AUTO_INCREMENT, - `email` varchar(255) DEFAULT NULL, - `name` varchar(255) NOT NULL, - `push_token` varchar(255) DEFAULT NULL, - `role` enum('ADMIN','USER') NOT NULL, - PRIMARY KEY (`user_id`) -); - -CREATE TABLE `exhibit_hall` ( - `exhibit_hall_id` BIGINT NOT NULL AUTO_INCREMENT, - `name` VARCHAR(255) NOT NULL, - `country` VARCHAR(255) NULL, - `region` VARCHAR(255) NULL, - `address` VARCHAR(255) NULL, - `opening_hours` VARCHAR(255) NULL, - `closed_days` VARCHAR(255) NULL, - `phone` VARCHAR(255) NULL, - `homepage_url` VARCHAR(255) NULL, - `is_domestic` BIT(1) NULL, - `created_at` DATETIME(6) NULL, - `updated_at` DATETIME(6) NULL, - - PRIMARY KEY (`exhibit_hall_id`) -); - -CREATE TABLE `keyword` ( - `keyword_id` bigint NOT NULL AUTO_INCREMENT, - `name` varchar(255) NOT NULL, - `type` enum('GENRE','STYLE') NOT NULL, - `group` varchar(255) NOT NULL, - - PRIMARY KEY (`keyword_id`) -); - -CREATE TABLE `exhibit` ( - `exhibit_id` BIGINT NOT NULL AUTO_INCREMENT, - `exhibit_hall_id` BIGINT NULL, - `title` VARCHAR(255) NULL, - `ticket_url` VARCHAR(255) NULL, - `description` VARCHAR(255) NULL, - `poster_url` VARCHAR(255) NULL, - `latitude` DECIMAL(38,2) NULL, - `longitude` DECIMAL(38,2) NULL, - `start_date` DATETIME(6) NULL, - `end_date` DATETIME(6) NULL, - `created_at` DATETIME(6) NULL, - `updated_at` DATETIME(6) NULL, - - `status` ENUM('FINISHED', 'ONGOING', 'UPCOMING') NOT NULL, - - PRIMARY KEY (`exhibit_id`), - KEY `idx_exhibit_hall_id` (`exhibit_hall_id`), - CONSTRAINT `fk_exhibit_exhibit_hall` - FOREIGN KEY (`exhibit_hall_id`) REFERENCES `exhibit_hall`(`exhibit_hall_id`) -); - -CREATE TABLE `exhibit_keyword` ( - exhibit_id BIGINT NOT NULL, - keyword_id BIGINT NOT NULL, - - PRIMARY KEY (exhibit_id, keyword_id), - KEY `idx_keyword_id`(`keyword_id`), - CONSTRAINT `fk_exhibit_keyword_exhibit` - FOREIGN KEY (`exhibit_id`) REFERENCES `exhibit` (`exhibit_id`), - CONSTRAINT `fk_exhibit_keyword_keyword_id` - FOREIGN KEY (`keyword_id`) REFERENCES keyword(`keyword_id`) -); - -CREATE TABLE `favorite_exhibit` ( - `created_at` datetime(6) NOT NULL, - `exhibit_id` bigint NOT NULL, - `favorite_id` bigint NOT NULL AUTO_INCREMENT, - `user_id` bigint NOT NULL, - - PRIMARY KEY (favorite_id), - KEY `idx_exhibit_id` (`exhibit_id`), - KEY `idx_user_id` (`user_id`), - CONSTRAINT `fk_favorite_exhibit_user_id` - FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`), - CONSTRAINT `fk_favorite_exhibit_exhibit_id` - FOREIGN KEY (`exhibit_id`) REFERENCES `exhibit` (`exhibit_id`) -); - -CREATE TABLE `notification` ( - `is_read` bit(1) DEFAULT NULL, - `created_at` datetime(6) NOT NULL, - `notification_id` bigint NOT NULL AUTO_INCREMENT, - `user_id` bigint NOT NULL, - `extra` varchar(255) DEFAULT NULL, - `message` varchar(255) NOT NULL, - `type` varchar(255) NOT NULL, - - PRIMARY KEY (`notification_id`), - - KEY `idx_user_id` (`user_id`), - CONSTRAINT `fk_notification_user_id` - FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) -); - -CREATE TABLE `recent_exhibit` ( - `exhibit_id` bigint DEFAULT NULL, - `recent_exhibit_id` bigint NOT NULL AUTO_INCREMENT, - `user_id` bigint DEFAULT NULL, - `view_at` datetime(6) DEFAULT NULL, - - PRIMARY KEY (`recent_exhibit_id`), - - KEY `idx_exhibit_id` (`exhibit_id`), - KEY `idx_user_id` (`user_id`), - CONSTRAINT `fk_recent_exhibit_exhibit_id` - FOREIGN KEY (`exhibit_id`) REFERENCES `exhibit` (`exhibit_id`), - CONSTRAINT `fk_recent_exhibit_user_id` - FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) -); - -CREATE TABLE `review` ( - `created_at` datetime(6) NOT NULL, - `exhibit_id` bigint NOT NULL, - `review_id` bigint NOT NULL AUTO_INCREMENT, - `updated_at` datetime(6) DEFAULT NULL, - `user_id` bigint NOT NULL, - `visit_date` date DEFAULT NULL, - `content` varchar(2000) NOT NULL, - PRIMARY KEY (`review_id`), - KEY `idx_exhibit_id` (`exhibit_id`), - KEY `idx_user_id` (`user_id`), - CONSTRAINT `fk_review_exhibit_id` - FOREIGN KEY (`exhibit_id`) REFERENCES `exhibit` (`exhibit_id`), - CONSTRAINT `fk_review_user_id` - FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) -); - -CREATE TABLE `images` ( - `curation_id` int DEFAULT NULL, - `created_at` datetime(6) DEFAULT NULL, - `exhibit_id` bigint DEFAULT NULL, - `img_id` bigint NOT NULL AUTO_INCREMENT, - `review_id` bigint DEFAULT NULL, - `user_id` bigint DEFAULT NULL, - `image_url` varchar(255) DEFAULT NULL, - - PRIMARY KEY (`img_id`), - - KEY `idx_exhibit_id`(`exhibit_id`), - KEY `idx_review_id`(`review_id`), - KEY `idx_user_id`(`user_id`), - CONSTRAINT `fk_images_user_id` - FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`), - CONSTRAINT `fk_images_review_id` - FOREIGN KEY (`review_id`) REFERENCES `review` (`review_id`), - CONSTRAINT `fk_images_exhibit_id` - FOREIGN KEY (`exhibit_id`) REFERENCES `exhibit` (`exhibit_id`) -); - -CREATE TABLE `refresh_token` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `refresh_token` varchar(255) NOT NULL, - `username` varchar(255) NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `uk_username` (`username`) -); - -CREATE TABLE `review_image` ( - `img_id` bigint NOT NULL AUTO_INCREMENT, - `created_at` datetime(6) DEFAULT NULL, - `curation_id` int DEFAULT NULL, - `display_order` int NOT NULL, - `image_url` varchar(255) DEFAULT NULL, - `review_id` bigint DEFAULT NULL, - PRIMARY KEY (`img_id`), - KEY `idx_review_id` (`review_id`), - CONSTRAINT `fk_review_images_review_id` - FOREIGN KEY (`review_id`) REFERENCES `review` (`review_id`) -); - -CREATE TABLE `search_history` ( - `created_at` datetime(6) NOT NULL, - `search_history_id` bigint NOT NULL AUTO_INCREMENT, - `user_id` bigint NOT NULL, - `content` varchar(255) NOT NULL, - - PRIMARY KEY (`search_history_id`), - KEY `idx_user_id` (`user_id`), - CONSTRAINT `fk_search_history_user_id` - FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) -); - -CREATE TABLE `social_accounts` ( - `created_at` datetime(6) NOT NULL, - `social_id` bigint NOT NULL AUTO_INCREMENT, - `user_id` bigint NOT NULL, - `access_token` varchar(255) DEFAULT NULL, - `provider_id` varchar(255) NOT NULL, - `refresh_token` varchar(255) DEFAULT NULL, - `provider` enum('APPLE','GOOGLE','KAKAO') NOT NULL, - - PRIMARY KEY (`social_id`), - - KEY `idx_user_id` (`user_id`), - CONSTRAINT `fk_social_accounts_user_id` - FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) -); - -CREATE TABLE `stamp` ( - `acquire_at` datetime(6) NOT NULL, - `review_id` bigint NOT NULL, - `stamp_id` bigint NOT NULL AUTO_INCREMENT, - `user_rank` varchar(255) NOT NULL, - PRIMARY KEY (`stamp_id`), - KEY `idx_review_id` (`review_id`), - CONSTRAINT `fk_stamp_review_id` - FOREIGN KEY (`review_id`) REFERENCES `review` (`review_id`) -); - -CREATE TABLE `user_keyword` ( - `created_at` datetime(6) NOT NULL, - `id` bigint NOT NULL AUTO_INCREMENT, - `keyword_id` bigint DEFAULT NULL, - `user_id` bigint NOT NULL, - PRIMARY KEY (`id`), - KEY `idx_keyword_id` (`keyword_id`), - KEY `idx_user_id` (`user_id`), - CONSTRAINT `fk_user_keyword_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`), - CONSTRAINT `fk_user_keyword_keyword_id` FOREIGN KEY (`keyword_id`) REFERENCES `keyword` (`keyword_id`) -); \ No newline at end of file diff --git a/src/main/resources/db/migration/V20251209__add_onboarding_completed_to_user.sql b/src/main/resources/db/migration/V20251209__add_onboarding_completed_to_user.sql deleted file mode 100644 index 9923d9c..0000000 --- a/src/main/resources/db/migration/V20251209__add_onboarding_completed_to_user.sql +++ /dev/null @@ -1,3 +0,0 @@ -ALTER TABLE `user` - ADD COLUMN `onboarding_completed` TINYINT(1) -NOT NULL DEFAULT 0; \ No newline at end of file diff --git a/src/main/resources/db/migration/V20251213__modify_exhibit_hall_and_keyword_schema.sql b/src/main/resources/db/migration/V20251213__modify_exhibit_hall_and_keyword_schema.sql deleted file mode 100644 index fc6977c..0000000 --- a/src/main/resources/db/migration/V20251213__modify_exhibit_hall_and_keyword_schema.sql +++ /dev/null @@ -1,7 +0,0 @@ -alter table exhibit_hall add Column longitude DECIMAL(10, 7) NULL; -alter table exhibit_hall add Column latitude DECIMAL(10, 7) NULL; - -alter table exhibit drop Column longitude; -alter table exhibit drop Column latitude; - -alter table keyword drop column `group` diff --git a/src/main/resources/db/migration/V20251217.1__add_nickname_drop_pushtoken.sql b/src/main/resources/db/migration/V20251217.1__add_nickname_drop_pushtoken.sql deleted file mode 100644 index 0897778..0000000 --- a/src/main/resources/db/migration/V20251217.1__add_nickname_drop_pushtoken.sql +++ /dev/null @@ -1,5 +0,0 @@ -ALTER TABLE `user` -DROP COLUMN push_token; - -ALTER TABLE `user` - ADD COLUMN nick_name VARCHAR(50) NULL UNIQUE COMMENT '사용자 닉네임'; diff --git a/src/main/resources/db/migration/V20251217__modify_exhibit_status_eumn_type.sql b/src/main/resources/db/migration/V20251217__modify_exhibit_status_eumn_type.sql deleted file mode 100644 index 54590ef..0000000 --- a/src/main/resources/db/migration/V20251217__modify_exhibit_status_eumn_type.sql +++ /dev/null @@ -1,2 +0,0 @@ -alter table exhibit -modify column status enum('FINISHED', 'ONGOING', 'UPCOMING', 'ENDING_SOON')not null ; \ No newline at end of file diff --git a/src/main/resources/db/migration/V20251219__modify_exhibit_date_type.sql b/src/main/resources/db/migration/V20251219__modify_exhibit_date_type.sql deleted file mode 100644 index d20fbfd..0000000 --- a/src/main/resources/db/migration/V20251219__modify_exhibit_date_type.sql +++ /dev/null @@ -1,2 +0,0 @@ -alter table exhibit modify column start_date date; -alter table exhibit modify column end_date date; \ No newline at end of file diff --git a/src/main/resources/db/migration/V20251220__add_status_to_favorite.sql b/src/main/resources/db/migration/V20251220__add_status_to_favorite.sql deleted file mode 100644 index e9b45d4..0000000 --- a/src/main/resources/db/migration/V20251220__add_status_to_favorite.sql +++ /dev/null @@ -1 +0,0 @@ -alter table favorite_exhibit add status TINYINT(1) NOT NULL default 0; \ No newline at end of file diff --git a/src/main/resources/db/migration/V20251221__add_profile_image_to_user.sql b/src/main/resources/db/migration/V20251221__add_profile_image_to_user.sql deleted file mode 100644 index 59f3c1c..0000000 --- a/src/main/resources/db/migration/V20251221__add_profile_image_to_user.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE `user` - ADD COLUMN profile_image_url VARCHAR(500) NULL diff --git a/src/main/resources/db/migration/V20251227_1__add_favorite_count.sql b/src/main/resources/db/migration/V20251227_1__add_favorite_count.sql deleted file mode 100644 index 3399cfd..0000000 --- a/src/main/resources/db/migration/V20251227_1__add_favorite_count.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE exhibit - RENAME COLUMN favoriteCount TO favorite_count; \ No newline at end of file diff --git a/src/main/resources/db/migration/V20251227__add_favorite_count.sql b/src/main/resources/db/migration/V20251227__add_favorite_count.sql deleted file mode 100644 index 07e6503..0000000 --- a/src/main/resources/db/migration/V20251227__add_favorite_count.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE exhibit - ADD COLUMN favoriteCount BIGINT NOT NULL DEFAULT 0; \ No newline at end of file diff --git a/src/main/resources/db/migration/V20260101__create_curation.sql b/src/main/resources/db/migration/V20260101__create_curation.sql deleted file mode 100644 index e7ac36b..0000000 --- a/src/main/resources/db/migration/V20260101__create_curation.sql +++ /dev/null @@ -1,24 +0,0 @@ -CREATE TABLE curation -( - curation_id BIGINT AUTO_INCREMENT PRIMARY KEY, - title VARCHAR(255) NOT NULL, - sub_description VARCHAR(255) , - curation_type VARCHAR(50) NOT NULL , - is_active BOOLEAN DEFAULT TRUE -); -CREATE TABLE curation_exhibit -( - curation_id BIGINT NOT NULL, - exhibit_id BIGINT NOT NULL, - PRIMARY KEY (curation_id, exhibit_id), - - CONSTRAINT fk_curation_exhibit_curation - FOREIGN KEY (curation_id) REFERENCES curation (curation_id) - ON DELETE CASCADE, - - CONSTRAINT fk_curation_exhibit_exhibit - FOREIGN KEY (exhibit_id) REFERENCES exhibit (exhibit_id) - ON DELETE CASCADE -); - -CREATE INDEX idx_curation_exhibit_exhibit_id ON curation_exhibit(exhibit_id); \ No newline at end of file