# GitHub Copilot Instructions

> **8**: t |@ \X  h |x `CLAUDE.md`| 0<\ i.
>    `CLAUDE.md`| Ȥ0 |\  X, t | 0Tt8.

---

# EAPIM Portal - \ h

t |@ AI T) ܤ4(GitHub Copilot, Claude Code )  t  X T| ` L 8X hD i.

## \ 

**EAPIM Portal**@ @D \ 0|t API 8   ܤ\. API D  ,  ], API  	, 8T, L 0D X  0 .

**0  :**
- Spring Boot 2.7.18 with Spring MVC and Thymeleaf
- Java 8 (targetCompatibility: 1.8)
- Gradle 7.x L ܤ\
- Oracle 12c pt0t (JNDI| \ t pt0)
- Spring Security (@ x)
- JPA/Hibernate 5.6.15 with Envers ( )
- MapStruct (DTO Q), Lombok (|t p)

## L 9

### ` tX 
- gradlew   - offline gradle  
- msi-gf63 0 /c/eactive/workspaces/shell-scripts/kjb-gradle.sh \ gradle  (jdk, gradle  X  8  gradle X l)

```bash
# dev \|\  (0)
gradle bootRun

#  \|\ 
gradle bootRun --args='--spring.profiles.active=stage'
```

### L

```bash
# Spring Boot    WAR L
gradle bootWar
# %: build/libs/eapim-portal-boot.war

# ` tX  \  WAR L (JEUS/WebLogic)
gradle war
# %: build/libs/eapim-portal.war

# t  L
gradle clean build
```

### L

```bash
#  L 
gradle test

# 䄬@ h L 
gradle test --info

#  L t 
gradle test --tests "com.eactive.apim.portal.apps.user.AccountControllerTest"

# (4 m L 
gradle test --tests "*Controller*"
```

### 

```bash
#  \| Ux
gradle printProfile

#  8 $ Ux
gradle printSourceSets

# Docker t L
./build_docker.sh
```

## DM

### @  lp

t \ Gradle composite build| t 3X x  Xti:

1. **elink-online-core-jpa** (`../eapim-online/elink-online-core-jpa`)
   - Gateway pt0 x  JPA 
   - API 8    
   - (: `com.eactive.eai.data.entity.onl.*`

2. **elink-portal-common** (`../elink-portal-common`)
   -   8     
   - 0  l, QueryDSL 
   -  x x  H  

3. **kjb-safedb** (`../kjb-safedb`)
   - @ SafeDB T8T |t
   - pt0t   pt0 T8T
   - T8T ( D 8, API  ) D

### ( lp

Tܔ 0  5t D **0 **( `) )<\ l1):

```
com.eactive.apim.portal/
   apps/                      # 0 
      agreements/            # API } 
      apis/                  # API t\ & 8
      apiservice/            # API D Q
      app/                   # API   
      approval/              # x l\
      auth/                  # x
      community/             # FAQ, m, Q&A, 48X
      dashboard/             #  & 
      file/                  # | \/\
      login/                 # \x/\D
      proxy/                 # API L Forward Proxy
      sample/                #  T 1
      user/                  #   
   common/                    #   
   config/                    # Spring $
   gateway/                   # Gateway DB  
       data/                  # Gateway 
```

 0 @ |<\ LD hi:
- `controller/` - Spring MVC d (@Controller)
- `service/` - DȤ \ (@Service, @Transactional)
- `repository/` - Spring Data JPA 
- `dto/` - pt0   (Lombok @Data)
- `mapper/` - MapStruct x0t (entity  DTO X)

### t pt0t DM

` tX@ P X Oracle pt0t| i:

1. **EMS Database** (Portal/Admin)
   - JNDI: `jdbc/dsOBP_EMS`
   - Schema: `EMSADM`
   - Entities: `com.eactive.apim.portal.apps.*`
   - : 8 , p, API , x

2. **Gateway Database** (API Specs)
   - JNDI: `jdbc/dsOBP_AGW`
   - Schema: `AGWADM`
   - Entities: `com.eactive.eai.data.entity.onl.*`
   - : API 8, D, T

$: `config/PortalDatasourceConfiguration.java`
-  pt0t  EntityManager
- Atomikos JTA| \  X
- X \: `/Log/eapim/portal/`

### $ \|

X $ |: `src/main/resources/application-{profile}.yml`

- **dev**:  X (Oracle at 192.168.240.177:1599, DevTools \1T, SQL \E)
- **stage**: Lt X (JNDI pt0, proxy to inter-dapiwas01)
- **prod**:  X (JNDI pt0, proxy to inter-apiwas00,  \1T)
- **gf63**: GlassFish 6.3 0
- **kjb_rinjae**: x  X

 $:
- 8X D: 15
- | \ \ : 8MB
- D 8 : 90|
- x p TTL: 5 (300)
-  x D: true

##  0  DȤ \

###    (`apps/user/`)

P     :
1. **  (Staff)**: 8    
2. **0  (Enterprise)**: x API D

 |ttt:
-    tT| x    x  \1T
- D 8 E  (90| ,  Y)
- \x (   
- 4t   

### API    (`apps/app/`)

API  x l\@ h  ):
- 0    `AppRequestController`| t  
-    `ApprovalController`| t x/$
-  / X 
-  eLink Gateway ClientID/ClientSecret 

### x l\ (`apps/approval/`)

L m  \  x ܤ\:
-  ] x
- API  1/
- 4 

: `Approval`, `Approver`, `ApprovalStatus` (WAITING, APPROVED, REJECTED)

### API L (`apps/proxy/`, `apps/sample/`)

- Gateway \X Forward Proxy
- /Q \Et  API L0
-  X  T 1
- API 8| \ Swagger UI i

###   (Hibernate Envers)

   | t `AbstractAuditingEntity`| Ui:
- `createdBy`, `createdDate`
- `lastModifiedBy`, `lastModifiedDate`
- `@Audited` xLtX<\  t%  
- Spring Data Envers| \ t% p

##   (4

###  0   X0

1. `apps/` X ( 1 (: `apps/newfeature/`)
2. `controller/`, `service/`, `repository/`, `dto/`, `mapper/`\ lpT
3. `repository/entity/` JPA  1 (`AbstractAuditingEntity` U)
4. `dto/` Lombok `@Data`| \ DTO 1
5. `mapper/` MapStruct | x0t 1
6. `@Service`@ `@Transactional`D \ D 5 l
7. `@Controller`@ `@RequestMapping`D \ d 1
8. `src/main/resources/templates/views/newfeature/` Thymeleaf \  
9. `src/main/resources/page-route.yml` | $

### MapStruct DTO Q

 H\ DTO XD t MapStruct :

```java
@Mapper(componentModel = "spring")
public interface UserMapper {
    PortalUserDto toDto(PortalUser entity);
    PortalUser toEntity(PortalUserDto dto);
    List<PortalUserDto> toDtoList(List<PortalUser> entities);
}
```

1 l `build/generated/sources/annotationProcessor/java/main/` X

### H  x

H $: `config/PortalConfigSecurity.java`
- @ x  : `PortalAuthenticationManager`
- `changeSessionId()`| \ 8X   )
-  0 pD \ CSRF )
- Lucy D0| \ XSS )

` 5:
```
ROLE_USER  [ROLE_INQUIRY, ROLE_ACCOUNT]
ROLE_CORP_USER  [ROLE_INQUIRY, ROLE_APP, ROLE_ACCOUNT]
ROLE_CORP_MANAGER  [ROLE_API_KEY_REQUEST, ROLE_INQUIRY, ROLE_APP,
                      ROLE_ACCOUNT, ROLE_CORP_API, ROLE_DASHBOARD,
                      ROLE_USER_MANAGER]
```

### pt0t 

Spring Data JPA  T  :

```java
public interface PortalUserRepository extends JpaRepository<PortalUser, Long> {
    Optional<PortalUser> findByEmail(String email);

    @Query("SELECT u FROM PortalUser u WHERE u.status = :status")
    List<PortalUser> findByStatus(@Param("status") UserStatus status);
}
```

\  QueryDSL :
```java
QPortalUser user = QPortalUser.portalUser;
return queryFactory.selectFrom(user)
    .where(user.email.eq(email)
        .and(user.status.eq(UserStatus.ACTIVE)))
    .fetchOne();
```

### X  

\ propagation h `@Transactional` :
- 0: `REQUIRED` (0t X 8Xp \ 1)
- }0  : \T| t `@Transactional(readOnly = true)`
-  pt0t: Atomikos JTA  <\  X 

###  

`common/exception/`X  \ x :
- `@ControllerAdvice`   `GlobalExceptionHandler`
- @ x `RuntimeException` U
- Thymeleaf    AJAX Д JSON X

### \E

`application.yml`X \E $:
```yaml
logging:
  file:
    path: /Log/App/eapim/
  level:
    com.eactive.apim.portal: DEBUG
    org.hibernate.SQL: DEBUG ( X)
```

LombokX `@Slf4j`@ h SLF4J :
```java
@Slf4j
@Service
public class UserService {
    public void someMethod() {
        log.debug(" T");
        log.info(" T");
        log.error(" T", exception);
    }
}
```

## L  t

### L lp

`src/test/java/com/eactive/apim/portal/`X L:
- `BaseWebTest` - Spring Boot L M|   0 t
- d L `BaseWebTest` U
- i L `@SpringBootTest` 
- Žx d L `@WebMvcTest` 

### |x L (4

```java
@SpringBootTest
@AutoConfigureMockMvc
class UserControllerTest extends BaseWebTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    void testUserRegistration() throws Exception {
        mockMvc.perform(post("/user/register")
                .param("email", "test@example.com")
                .with(csrf()))
            .andExpect(status().isOk())
            .andExpect(view().name("user/register-success"));
    }
}
```

### SafeDB L

L 0<\ SafeDB T8T  D\1T). D\ :
```bash
gradle test -Dsafedb=/path/to/safedb
```

##  m

### \  

t 8@ \ D X i:
- Thymeleaf \@ \  t 
- pt0t \  pt0 h (UTF-8)
- \  T \| (`messages_ko.properties`)
- \    t (`.md`)

### Forward Proxy $

API L Gateway\X Forward Proxy :
- Dev: `http://localhost:10000`
- Stage: `http://inter-dapiwas01:10000`
- Prod: `http://inter-apiwas00:10000`

$: `apps/proxy/service/ProxyService.java`

### D 8 E

`PortalUserValidator` :
- \ 8
-  8, 8, +, 8 h D
-  8   
- \ 3 D 8   
- 90|  

### 8X  

-  | 8X 
- 8X D: 15
- \x  8X   )
- Redis/Ehcache| \ 8X t0 (Lt/)

### | \ \

- \  | l0: 8MB
- `FileService` ȩ U $
- |   X: `/Log/App/eapim/files/`
- \  XSS 

## 0

### ` tX  

WAR | 8X :
- **JEUS** (`jeus-web-dd.xml` D)
- **WebLogic** (`weblogic.xml` D)
- **GlassFish 6.3** (`gradle-gf63.sh` )
- **Tomcat** (Spring Boot )

### JNDI $ D

Lt/ X JNDI  $:
- `jdbc/dsOBP_EMS`  Portal pt0t
- `jdbc/dsOBP_AGW`  Gateway pt0t

### X 

```bash
#  ݬm: 0 $ $|t
JAVA_OPTS="-Xmx2g -Xms1g -Dspring.profiles.active=prod"
```

### Docker 0

```bash
# WAR L
gradle bootWar

# Docker t L
./build_docker.sh

# Lt 
docker run -p 8080:8080 \
  -e JAVA_OPTS="-Dspring.profiles.active=prod" \
  -v /Log:/Log \
  eapim-portal:latest
```

##  ( 

L m D   :
- **Gateway API 8**: `elink-online-core-jpa`  Ux
- **  **: `elink-portal-common`  Ux
- **T8T**: `kjb-safedb`  Ux
- **Admin 8**: `../eapim-admin/`  ( \
- **Online 8**: `../eapim-online/`  ( \

##   

-   t (\ ): `.md`
- L l: `build-gf63.sh`, `deploy_portal.sh`, `deploy_portal2.sh`
- Docker: `Dockerfile`, `build_docker.sh`
- SQL l: `../kjb-eapim-sql/`
