diff --git a/apps/user-service/src/main/java/com/gltkorea/icebang/config/security/endpoints/SecurityEndpoints.java b/apps/user-service/src/main/java/com/gltkorea/icebang/config/security/endpoints/SecurityEndpoints.java
index bc6eafe2..da658775 100644
--- a/apps/user-service/src/main/java/com/gltkorea/icebang/config/security/endpoints/SecurityEndpoints.java
+++ b/apps/user-service/src/main/java/com/gltkorea/icebang/config/security/endpoints/SecurityEndpoints.java
@@ -1,7 +1,16 @@
package com.gltkorea.icebang.config.security.endpoints;
public enum SecurityEndpoints {
- PUBLIC("/", "/v0/auth/login", "/api/public/**", "/health", "/css/**", "/js/**", "/images/**"),
+ PUBLIC(
+ "/",
+ "/v0/auth/login",
+ "/api/public/**",
+ "/health",
+ "/css/**",
+ "/js/**",
+ "/images/**",
+ "/v0/organizations/**",
+ "/v0/auth/register"),
// 데이터 관리 관련 엔드포인트
DATA_ADMIN("/admin/**", "/api/admin/**", "/management/**", "/actuator/**"),
diff --git a/apps/user-service/src/main/resources/application-test-integration.yml b/apps/user-service/src/main/resources/application-test-integration.yml
new file mode 100644
index 00000000..95faf0f3
--- /dev/null
+++ b/apps/user-service/src/main/resources/application-test-integration.yml
@@ -0,0 +1,51 @@
+spring:
+ config:
+ activate:
+ on-profile: test-integration
+
+ # H2 인메모리 데이터베이스 설정 (Unit Test용)
+ datasource:
+ url: jdbc:h2:mem:testdb;MODE=MariaDB;DB_CLOSE_DELAY=-1;DATABASE_TO_LOWER=TRUE
+ username: sa
+ password:
+ driver-class-name: org.h2.Driver
+ hikari:
+ connection-init-sql: "SET MODE MariaDB"
+ connection-timeout: 30000
+ idle-timeout: 600000
+ max-lifetime: 1800000
+ maximum-pool-size: 10
+ minimum-idle: 5
+ pool-name: HikariCP-MyBatis
+
+ # H2 웹 콘솔 활성화 (디버깅용)
+ h2:
+ console:
+ enabled: true
+
+ # JPA 설정 (H2용)
+ jpa:
+ hibernate:
+ ddl-auto: create-drop
+ show-sql: true
+ properties:
+ hibernate:
+ dialect: org.hibernate.dialect.H2Dialect
+
+ # SQL 스크립트 초기화 설정
+ sql:
+ init:
+ mode: always
+ schema-locations:
+ - classpath:sql/00-drop-h2.sql
+ - classpath:sql/01-schema.sql
+ encoding: UTF-8
+
+mybatis:
+ mapper-locations: classpath:mybatis/mapper/**/*.xml
+ type-aliases-package: com.gltkorea.icebang.dto
+ configuration:
+ map-underscore-to-camel-case: true
+
+logging:
+ config: classpath:log4j2-test-unit.yml
\ No newline at end of file
diff --git a/apps/user-service/src/main/resources/mybatis/mapper/AuthMapper.xml b/apps/user-service/src/main/resources/mybatis/mapper/AuthMapper.xml
index 0023c224..154dbb39 100644
--- a/apps/user-service/src/main/resources/mybatis/mapper/AuthMapper.xml
+++ b/apps/user-service/src/main/resources/mybatis/mapper/AuthMapper.xml
@@ -37,7 +37,7 @@
INSERT INTO user_organization (user_id, organization_id, department_id, position_id, status)
- VALUES (#{id}, #{organizationId}, #{departmentId}, #{positionId}, #{status});
+ VALUES (#{id}, #{orgId}, #{deptId}, #{positionId}, #{status});
diff --git a/apps/user-service/src/main/resources/mybatis/mapper/OrganizationMapper.xml b/apps/user-service/src/main/resources/mybatis/mapper/OrganizationMapper.xml
index 6a8201b8..740b81a3 100644
--- a/apps/user-service/src/main/resources/mybatis/mapper/OrganizationMapper.xml
+++ b/apps/user-service/src/main/resources/mybatis/mapper/OrganizationMapper.xml
@@ -9,7 +9,7 @@
SELECT
id,
name as organizationName
- FROM organizations
+ FROM organization
ORDER BY name
@@ -18,7 +18,7 @@
SELECT
id,
name
- FROM departments
+ FROM department
WHERE organization_id = #{organizationId}
ORDER BY name
@@ -28,7 +28,7 @@
SELECT
id,
title
- FROM positions
+ FROM position
WHERE organization_id = #{organizationId}
ORDER BY title
@@ -39,7 +39,7 @@
id,
name,
description
- FROM roles
+ FROM role
WHERE organization_id = #{organizationId}
ORDER BY name
diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/DatabaseConnectionTest.java b/apps/user-service/src/test/java/com/gltkorea/icebang/DatabaseConnectionTest.java
deleted file mode 100644
index c15170cc..00000000
--- a/apps/user-service/src/test/java/com/gltkorea/icebang/DatabaseConnectionTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// package com.gltkorea.icebang;
-//
-// import static org.assertj.core.api.Assertions.assertThat;
-//
-// import java.sql.Connection;
-// import java.sql.SQLException;
-// import java.util.Optional;
-//
-// import javax.sql.DataSource;
-//
-// import org.junit.jupiter.api.DisplayName;
-// import org.junit.jupiter.api.Test;
-// import org.springframework.beans.factory.annotation.Autowired;
-// import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
-// import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
-// import org.springframework.boot.test.context.SpringBootTest;
-// import org.springframework.context.annotation.Import;
-// import org.springframework.test.context.ActiveProfiles;
-// import org.springframework.test.context.jdbc.Sql;
-// import org.springframework.transaction.annotation.Transactional;
-//
-// import com.gltkorea.icebang.dto.UserDto;
-// import com.gltkorea.icebang.mapper.UserMapper;
-//
-// @SpringBootTest
-// @Import(TestcontainersConfiguration.class)
-// @AutoConfigureTestDatabase(replace = Replace.NONE)
-// @ActiveProfiles("test") // application-test-unit.yml 설정을 활성화
-// @Transactional // 테스트 후 데이터 롤백
-// @Sql(
-// scripts = {"classpath:sql/create-01-schema.sql", "classpath:sql/insert-user-data.sql"},
-// executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
-// class DatabaseConnectionTest {
-//
-// @Autowired private DataSource dataSource;
-//
-// @Autowired private UserMapper userMapper; // JPA Repository 대신 MyBatis Mapper를 주입
-//
-// @Test
-// @DisplayName("DataSource를 통해 DB 커넥션을 성공적으로 얻을 수 있다.")
-// void canGetDatabaseConnection() {
-// try (Connection connection = dataSource.getConnection()) {
-// assertThat(connection).isNotNull();
-// assertThat(connection.isValid(1)).isTrue();
-// System.out.println("DB Connection successful: " + connection.getMetaData().getURL());
-// } catch (SQLException e) {
-// org.junit.jupiter.api.Assertions.fail("Failed to get database connection", e);
-// }
-// }
-//
-// @Test
-// @DisplayName("MyBatis Mapper를 통해 '홍길동' 사용자를 이메일로 조회")
-// void findUserByEmailWithMyBatis() {
-// // given
-// String testEmail = "hong.gildong@example.com";
-//
-// // when
-// Optional foundUser = userMapper.findByEmail(testEmail);
-//
-// // then
-// // 사용자가 존재하고, 이름이 '홍길동'인지 확인
-// assertThat(foundUser).isPresent();
-// assertThat(foundUser.get().getName()).isEqualTo("홍길동");
-// System.out.println("Successfully found user with MyBatis: " + foundUser.get().getName());
-// }
-//
-// @Test
-// @DisplayName("샘플 데이터가 올바르게 삽입되었는지 확인")
-// void verifyAllSampleDataInserted() {
-// // 사용자 데이터 확인
-// Optional hong = userMapper.findByEmail("hong.gildong@example.com");
-// assertThat(hong).isPresent();
-// assertThat(hong.get().getName()).isEqualTo("홍길동");
-//
-// Optional kim = userMapper.findByEmail("kim.chulsu@example.com");
-// assertThat(kim).isPresent();
-// assertThat(kim.get().getName()).isEqualTo("김철수");
-//
-// System.out.println("샘플 데이터 삽입 성공 - 홍길동, 김철수 확인");
-// }
-// }
diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/UserServiceApplicationTests.java b/apps/user-service/src/test/java/com/gltkorea/icebang/UserServiceApplicationTests.java
deleted file mode 100644
index 26cfc86b..00000000
--- a/apps/user-service/src/test/java/com/gltkorea/icebang/UserServiceApplicationTests.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.gltkorea.icebang;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.context.annotation.Import;
-
-@Import(TestcontainersConfiguration.class)
-@SpringBootTest
-class UserServiceApplicationTests {
-
- @Test
- void contextLoads() {}
-}
diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/controller/TestController.java b/apps/user-service/src/test/java/com/gltkorea/icebang/controller/TestController.java
deleted file mode 100644
index c29707ce..00000000
--- a/apps/user-service/src/test/java/com/gltkorea/icebang/controller/TestController.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.gltkorea.icebang.controller;
-
-import org.springframework.boot.test.context.TestComponent;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-@TestComponent
-@RestController
-public class TestController {
-
- @GetMapping("/api/health")
- public String health() {
- return "OK";
- }
-}
diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/domain/auth/controller/AuthControllerE2eTest.java b/apps/user-service/src/test/java/com/gltkorea/icebang/domain/auth/controller/AuthControllerE2eTest.java
deleted file mode 100644
index c5b184fd..00000000
--- a/apps/user-service/src/test/java/com/gltkorea/icebang/domain/auth/controller/AuthControllerE2eTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.gltkorea.icebang.domain.auth.controller;
-
-import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document;
-import static com.epages.restdocs.apispec.ResourceDocumentation.*;
-import static org.assertj.core.api.Assertions.*;
-import static org.springframework.restdocs.headers.HeaderDocumentation.*;
-import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
-import static org.springframework.restdocs.operation.preprocess.Preprocessors.*;
-import static org.springframework.restdocs.payload.PayloadDocumentation.*;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.springframework.http.*;
-import org.springframework.restdocs.payload.JsonFieldType;
-import org.springframework.test.annotation.DirtiesContext;
-import org.springframework.test.context.jdbc.Sql;
-
-import com.epages.restdocs.apispec.ResourceSnippetParameters;
-import com.gltkorea.icebang.support.E2eTestSupport;
-
-@Sql("classpath:sql/01-insert-internal-users.sql")
-@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
-class AuthControllerE2eTest extends E2eTestSupport {
-
- @Test
- @DisplayName("사용자 로그인 성공")
- void login_success() throws Exception {
- // given
- Map loginRequest = new HashMap<>();
- loginRequest.put("email", "admin@icebang.site");
- loginRequest.put("password", "qwer1234!A");
-
- // MockMvc로 REST Docs + OpenAPI 생성
- mockMvc
- .perform(
- post(getApiUrlForDocs("/v0/auth/login"))
- .contentType(MediaType.APPLICATION_JSON)
- .header("Origin", "https://admin.icebang.site")
- .header("Referer", "https://admin.icebang.site/")
- .content(objectMapper.writeValueAsString(loginRequest)))
- .andExpect(status().isOk())
- .andExpect(jsonPath("$.success").value(true))
- .andExpect(jsonPath("$.status").value("OK"))
- .andExpect(jsonPath("$.message").value("OK"))
- .andExpect(jsonPath("$.data").isEmpty())
- .andDo(
- document(
- "auth-login",
- preprocessRequest(prettyPrint()),
- preprocessResponse(prettyPrint()),
- resource(
- ResourceSnippetParameters.builder()
- .tag("Authentication")
- .summary("사용자 로그인")
- .description("이메일과 비밀번호로 사용자 인증을 수행합니다")
- .requestFields(
- fieldWithPath("email")
- .type(JsonFieldType.STRING)
- .description("사용자 이메일 주소"),
- fieldWithPath("password")
- .type(JsonFieldType.STRING)
- .description("사용자 비밀번호"))
- .responseFields(
- fieldWithPath("success")
- .type(JsonFieldType.BOOLEAN)
- .description("요청 성공 여부"),
- fieldWithPath("data")
- .type(JsonFieldType.NULL)
- .description("응답 데이터 (로그인 성공 시 null)"),
- fieldWithPath("message")
- .type(JsonFieldType.STRING)
- .description("응답 메시지"),
- fieldWithPath("status")
- .type(JsonFieldType.STRING)
- .description("HTTP 상태"))
- .build())));
- }
-}
diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/annotation/E2eTest.java b/apps/user-service/src/test/java/com/gltkorea/icebang/e2e/annotation/E2eTest.java
similarity index 89%
rename from apps/user-service/src/test/java/com/gltkorea/icebang/annotation/E2eTest.java
rename to apps/user-service/src/test/java/com/gltkorea/icebang/e2e/annotation/E2eTest.java
index 43290a4a..0840a996 100644
--- a/apps/user-service/src/test/java/com/gltkorea/icebang/annotation/E2eTest.java
+++ b/apps/user-service/src/test/java/com/gltkorea/icebang/e2e/annotation/E2eTest.java
@@ -1,4 +1,4 @@
-package com.gltkorea.icebang.annotation;
+package com.gltkorea.icebang.e2e.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/config/E2eTestConfiguration.java b/apps/user-service/src/test/java/com/gltkorea/icebang/e2e/config/E2eTestConfiguration.java
similarity index 97%
rename from apps/user-service/src/test/java/com/gltkorea/icebang/config/E2eTestConfiguration.java
rename to apps/user-service/src/test/java/com/gltkorea/icebang/e2e/config/E2eTestConfiguration.java
index 5b1c5ce9..7ebe181d 100644
--- a/apps/user-service/src/test/java/com/gltkorea/icebang/config/E2eTestConfiguration.java
+++ b/apps/user-service/src/test/java/com/gltkorea/icebang/e2e/config/E2eTestConfiguration.java
@@ -1,4 +1,4 @@
-package com.gltkorea.icebang.config;
+package com.gltkorea.icebang.e2e.config;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/e2e/scenario/UserRegistrationFlowE2eTest.java b/apps/user-service/src/test/java/com/gltkorea/icebang/e2e/scenario/UserRegistrationFlowE2eTest.java
new file mode 100644
index 00000000..f0fd3244
--- /dev/null
+++ b/apps/user-service/src/test/java/com/gltkorea/icebang/e2e/scenario/UserRegistrationFlowE2eTest.java
@@ -0,0 +1,299 @@
+package com.gltkorea.icebang.e2e.scenario;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.http.*;
+import org.springframework.test.context.jdbc.Sql;
+
+import com.gltkorea.icebang.e2e.support.E2eTestSupport;
+
+@Sql(
+ value = "classpath:sql/01-insert-internal-users.sql",
+ executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
+@DisplayName("사용자 등록 플로우 E2E 테스트")
+class UserRegistrationFlowE2eTest extends E2eTestSupport {
+
+ @SuppressWarnings("unchecked")
+ @Test
+ @DisplayName("관리자가 새 사용자를 등록하는 전체 플로우 (ERP 시나리오)")
+ void completeUserRegistrationFlow() throws Exception {
+ logStep(1, "관리자 로그인 (최우선)");
+
+ // 1. 관리자 로그인 (ERP에서 모든 작업의 선행 조건)
+ Map loginRequest = new HashMap<>();
+ loginRequest.put("email", "admin@icebang.site");
+ loginRequest.put("password", "qwer1234!A");
+
+ HttpHeaders loginHeaders = new HttpHeaders();
+ loginHeaders.setContentType(MediaType.APPLICATION_JSON);
+ loginHeaders.set("Origin", "https://admin.icebang.site");
+ loginHeaders.set("Referer", "https://admin.icebang.site/");
+
+ HttpEntity