diff --git a/src/integrationTest/resources/db/migration/V1__initial.sql b/src/integrationTest/resources/db/migration/V1__initial.sql deleted file mode 100644 index d3b226b..0000000 --- a/src/integrationTest/resources/db/migration/V1__initial.sql +++ /dev/null @@ -1,145 +0,0 @@ --- OPIc 연습 앱 Database Schema (PostgreSQL) --- 생성일: 2026-02-02 --- 버전: 1.0.0 (MVP) - -CREATE TABLE users ( - id BIGSERIAL PRIMARY KEY, - username TEXT NOT NULL UNIQUE, - password TEXT NOT NULL, - email TEXT UNIQUE, - terms_agreed_at TIMESTAMP, - privacy_agreed_at TIMESTAMP, - user_role_code CHAR(7) NOT NULL DEFAULT 'USR0001', - created_at TIMESTAMP NOT NULL DEFAULT NOW(), - updated_at TIMESTAMP NOT NULL DEFAULT NOW(), - deleted_at TIMESTAMP -); - -CREATE TABLE category ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - created_at TIMESTAMP NOT NULL DEFAULT NOW(), - updated_at TIMESTAMP NOT NULL DEFAULT NOW(), - deleted_at TIMESTAMP -); - -CREATE TABLE question_type ( - id BIGSERIAL PRIMARY KEY, - name TEXT NOT NULL UNIQUE, - created_at TIMESTAMP NOT NULL DEFAULT NOW(), - updated_at TIMESTAMP NOT NULL DEFAULT NOW(), - deleted_at TIMESTAMP -); - -CREATE TABLE questions ( - id BIGSERIAL PRIMARY KEY, - category_id BIGINT NOT NULL, - question_type_id BIGINT NOT NULL, - question TEXT NOT NULL, - audio_file_url TEXT, - duration_ms INTEGER, - created_at TIMESTAMP NOT NULL DEFAULT NOW(), - updated_at TIMESTAMP NOT NULL DEFAULT NOW(), - deleted_at TIMESTAMP -); - -CREATE TABLE question_sets ( - id BIGSERIAL PRIMARY KEY, - user_id BIGINT NOT NULL, - title TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT NOW(), - updated_at TIMESTAMP NOT NULL DEFAULT NOW(), - deleted_at TIMESTAMP -); - -CREATE TABLE question_set_items ( - item_id BIGSERIAL PRIMARY KEY, - question_set_id BIGINT NOT NULL, - question_id BIGINT NOT NULL, - order_index INTEGER NOT NULL, - UNIQUE(question_set_id, question_id), - UNIQUE(question_set_id, order_index) -); - -CREATE TABLE session_status_mapping ( - status_code CHAR(7) PRIMARY KEY, - status_text TEXT NOT NULL, - description TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT NOW(), - updated_at TIMESTAMP NOT NULL DEFAULT NOW(), - deleted_at TIMESTAMP -); - -CREATE TABLE sessions ( - id BIGSERIAL PRIMARY KEY, - user_id BIGINT NOT NULL, - question_set_id BIGINT, - title TEXT NOT NULL, - mode TEXT NOT NULL, - status_code CHAR(7) NOT NULL, - current_index INTEGER NOT NULL DEFAULT 0, - created_at TIMESTAMP NOT NULL DEFAULT NOW(), - started_at TIMESTAMP, - completed_at TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT NOW(), - deleted_at TIMESTAMP -); - -CREATE TABLE answers ( - id BIGSERIAL PRIMARY KEY, - question_id BIGINT NOT NULL, - session_id BIGINT NOT NULL, - audio_url TEXT NOT NULL, - storage_type VARCHAR(10) NOT NULL, - mime_type TEXT NOT NULL, - duration_ms INTEGER NOT NULL, - transcript TEXT, - word_segments JSONB, - pause_analysis JSONB, - feedback JSONB, - upload_status_code CHAR(7) NOT NULL DEFAULT 'UPL0001', - feedback_status_code CHAR(7) NOT NULL DEFAULT 'FBS0001', - created_at TIMESTAMP NOT NULL DEFAULT NOW(), - updated_at TIMESTAMP NOT NULL DEFAULT NOW(), - deleted_at TIMESTAMP -); - -CREATE TABLE refresh_token ( - id BIGSERIAL PRIMARY KEY, - user_id BIGINT NOT NULL, - token VARCHAR(512) NOT NULL, - expires_at TIMESTAMP NOT NULL, - created_at TIMESTAMP NOT NULL, - - CONSTRAINT uk_refresh_token UNIQUE (token) -); - -CREATE TABLE feature_flags ( - flag_name VARCHAR(100) PRIMARY KEY, - enabled BOOLEAN NOT NULL DEFAULT true, - description TEXT, - updated_at TIMESTAMP NOT NULL DEFAULT NOW() -); - --- 초기 데이터 -INSERT INTO feature_flags (flag_name, enabled, description) -VALUES ('ai-for-free', true, '이벤트 또는 특별 기간동안 AI 기능 임시 허용'); - -CREATE TABLE drill_answers ( - id BIGSERIAL PRIMARY KEY, - user_id BIGINT NOT NULL, - question_id BIGINT NOT NULL, - audio_url TEXT NOT NULL, - storage_type VARCHAR(10) NOT NULL DEFAULT 'S3', - mime_type TEXT NOT NULL, - duration_ms INTEGER NOT NULL DEFAULT 0, - transcript TEXT, - word_segments JSONB, - pause_analysis JSONB, - feedback JSONB, - upload_status_code CHAR(7) NOT NULL DEFAULT 'UPL0001', - feedback_status_code CHAR(7) NOT NULL DEFAULT 'FBS0001', - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - deleted_at TIMESTAMP -); \ No newline at end of file diff --git a/src/integrationTest/resources/db/migration/V2__add_refresh_token_revoke.sql b/src/integrationTest/resources/db/migration/V2__add_refresh_token_revoke.sql deleted file mode 100644 index c92b414..0000000 --- a/src/integrationTest/resources/db/migration/V2__add_refresh_token_revoke.sql +++ /dev/null @@ -1,8 +0,0 @@ --- Migration: refresh_token soft delete 지원 --- 적용일: 2026-03-01 --- 배경: 탈취 감지를 위해 revoke 이력 보관 (hard delete → soft delete 전환) --- revoke 후 90일 보관, 이후 스케줄러가 삭제 - -ALTER TABLE refresh_token - ADD COLUMN revoked BOOLEAN NOT NULL DEFAULT FALSE, - ADD COLUMN revoked_at TIMESTAMP; diff --git a/src/integrationTest/resources/db/migration/V3__create_notices.sql b/src/integrationTest/resources/db/migration/V3__create_notices.sql deleted file mode 100644 index 176d2cc..0000000 --- a/src/integrationTest/resources/db/migration/V3__create_notices.sql +++ /dev/null @@ -1,9 +0,0 @@ --- V005: notices 테이블 생성 -CREATE TABLE notices ( - id BIGSERIAL PRIMARY KEY, - title VARCHAR(200) NOT NULL, - content TEXT NOT NULL, - created_at TIMESTAMP NOT NULL DEFAULT NOW(), - updated_at TIMESTAMP NOT NULL DEFAULT NOW(), - deleted_at TIMESTAMP -); diff --git a/src/integrationTest/resources/db/migration/V4__email_not_null.sql b/src/integrationTest/resources/db/migration/V4__email_not_null.sql deleted file mode 100644 index a25bbea..0000000 --- a/src/integrationTest/resources/db/migration/V4__email_not_null.sql +++ /dev/null @@ -1,5 +0,0 @@ --- V006: users.email NOT NULL 제약 추가 --- 배경: 로그인 식별자를 username → email로 변경함에 따라 email 필수화 --- 적용 전 확인: SELECT email FROM users WHERE email IS NULL; → 0 rows 확인됨 (2026-03-30) - -ALTER TABLE users ALTER COLUMN email SET NOT NULL; diff --git a/src/integrationTest/resources/db/migration/V5__add_password_reset_sessions.sql b/src/integrationTest/resources/db/migration/V5__add_password_reset_sessions.sql deleted file mode 100644 index 09ddfcd..0000000 --- a/src/integrationTest/resources/db/migration/V5__add_password_reset_sessions.sql +++ /dev/null @@ -1,14 +0,0 @@ -CREATE TABLE password_reset_session ( - id UUID PRIMARY KEY, - user_id BIGINT, - code_hash VARCHAR(256), - expires_at TIMESTAMP, - used_at TIMESTAMP, - attempt_count INT NOT NULL DEFAULT 0, - resend_count INT NOT NULL DEFAULT 0, - last_resent_at TIMESTAMP, - blocked_until TIMESTAMP, - verified_at TIMESTAMP, - created_at TIMESTAMP NOT NULL -); - diff --git a/src/integrationTest/resources/db/migration/V6__add_status_changed_at.sql b/src/integrationTest/resources/db/migration/V6__add_status_changed_at.sql deleted file mode 100644 index 06ede61..0000000 --- a/src/integrationTest/resources/db/migration/V6__add_status_changed_at.sql +++ /dev/null @@ -1,8 +0,0 @@ --- V008: answers, drill_answers 테이블에 status_changed_at 컬럼 추가 --- 목적: 피드백 상태 변경 시각 추적 (30초 SLA 기준, 스케줄러 타임아웃 판단) - -ALTER TABLE answers - ADD COLUMN status_changed_at TIMESTAMP; - -ALTER TABLE drill_answers - ADD COLUMN status_changed_at TIMESTAMP; diff --git a/src/integrationTest/resources/db/migration/V7__workflow_test.sql b/src/integrationTest/resources/db/migration/V7__workflow_test.sql deleted file mode 100644 index 55d499f..0000000 --- a/src/integrationTest/resources/db/migration/V7__workflow_test.sql +++ /dev/null @@ -1,2 +0,0 @@ --- V7: test sql - noop --- testing for github action workflow \ No newline at end of file diff --git a/src/main/resources/application-dev-postgres.yml b/src/main/resources/application-dev-postgres.yml index 679a03e..37ccffd 100644 --- a/src/main/resources/application-dev-postgres.yml +++ b/src/main/resources/application-dev-postgres.yml @@ -16,7 +16,7 @@ spring: jpa: hibernate: ddl-auto: validate - show-sql: true + show-sql: false jwt: secret: dev-secret-key-change-in-production-this-must-be-at-least-256-bits-long @@ -37,6 +37,13 @@ password: max-resend-count: 100 block-minutes: 100 +aws: + s3: + bucket: opic-practice-test + lambda: + session-feedback-function-name: opic-transcription-test + drill-answer-feedback-function-name: drill-transcription-test + management: endpoints: web: diff --git a/src/main/resources/application-load-test.yml b/src/main/resources/application-load-test.yml index f65cc22..ce79903 100644 --- a/src/main/resources/application-load-test.yml +++ b/src/main/resources/application-load-test.yml @@ -36,7 +36,7 @@ internal: password: reset: code: - secret: dev-secret-key-change-in-production-this-must-be-at-least-256-bits-long + secret: ${PASSWORD_RESET_CODE_SECRET:load-test-secret-key-change-in-production-this-must-be-at-least-256-bits-long} session-expire-minutes: 100 code-expire-minutes: 100 max-attempts: 100 @@ -65,3 +65,6 @@ management: tags: application: opic-practice env: load-test + distribution: + percentiles: + http.server.requests: 0.5, 0.95, 0.99