이 문서는 Morpheus Gateway 애플리케이션(msp-gw-boot-web
)을 실행하고 설정하는 데 필요한 환경 구성, 라이선스, 의존성, 설정 파일(application.yml
)에 대해 설명합니다.
Morpheus Gateway는 REST API 서버, App 배포, 이벤트 로깅, 파일 처리 등 다양한 기능을 제공하는 미들웨어 솔루션으로, 올바르게 작동하기 위해 필수 설정이 선행되어야 합니다.
위 환경 외 버전에서는 동작이 보장되지 않을 수 있습니다.
특히 JDK 17 이상, Spring Boot 3.x와는 호환되지 않습니다.
Gateway가 정상적으로 구동되기 위해서는 프로젝트별 Application ID에 해당하는 라이센스 파일이 반드시 필요합니다.
라이센스 파일은 license.cer
, license.key
두 파일이 모두 존재해야 하며, 짝이 맞지 않으면 유효성 검증에 실패합니다
이 두 파일은 애플리케이션이 시작될 때 자동으로 로딩되며, 다음 조건들을 기준으로 유효성을 검증합니다:
라이선스 기본 파일 경로는
src/main/resources/WEB-INF/config/
이며, 만약 라이센스 파일 유효성 검증에 실패 할 경우 Gateway의 모든 기능을 사용할 수 없습니다. 라이센스 파일 신청 방법은 아래 링크에서 확인 가능합니다. [MADP] 서버 라이선스 설정 가이드
Gateway 제품은 kr.morphues.msp-starter-gateway 라이브러리 의존성 추가가 필수적이며, 필요한 기능에 따라 추가적으로 라이브러리 의존성 추가를 진행합니다.
만약 인하우스 배포가 필요하여 Appstore 기능을 사용하고자 하신다면msp-gateway-appstore
라이브러리가, App 위변조 기능을 사용하고자 하신다면msp-gateway-prevent-forgery
라이브러리가 필수입니다.
해당 라이브러리 의존성 추가가 누락된 경우 해당 기능에 대한 API 호출 시 404 에러가 발생합니다.
<repositories>
<repository>
<id>msp-framework-repository</id>
<url>https://repo.morpheus.kr:8443/nexus/content/repositories/releases</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>kr.morpheus</groupId>
<artifactId>msp-starter-gateway</artifactId>
<version>1.1.7-SNAPSHOT</version>
</dependency>
<!-- 선택 사항: AppStore 기능 -->
<dependency>
<groupId>kr.morpheus</groupId>
<artifactId>msp-gateway-appstore</artifactId>
<version>1.1.7-SNAPSHOT</version>
</dependency>
<!-- 선택 사항: 위변조 방지 기능 -->
<dependency>
<groupId>kr.morpheus</groupId>
<artifactId>msp-gateway-prevent-forgery</artifactId>
<version>1.1.7-SNAPSHOT</version>
</dependency>
</dependencies>
msp-gw-boot-web에서 application.yml 설정 파일을 정확하게 이해하고 Morphues Gateway에서 DB 연결, 리소스 업데이트, 이벤트 로그, 앱스토어 등을 설정하는 방법을 안내합니다. application.yml 파일은 Spring Boot 애플리케이션의 동작을 제어하는 등 중요한 역할을 하는 YAML 형식의 파일이며 Spring Boot는 이 파일을 기반으로 Application을 실행합니다. msp-gw-boot-web/src/main/resources 경로에서 application.yml 파일을 확인할 수 있습니다.
server:
port: 28080
servlet:
encoding:
charset: UTF-8
enabled: true
force: true
context-path: /msp-gw
logging:
level:
root: info
org.springdoc: info
org.springframework: info
kr.msp: trace
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
messages:
basename: message/messages
msp:
gateway:
datasource:
driver-class-name: oracle.jdbc.OracleDriver
url: jdbc:oracle:thin:@127.0.0.11521:UDB
username: lab
password: lab
mybatis:
platform: oracle #oracle, oracle9i, postgresql, oracle, mssql, informix, db2
resource-update:
use-force-https: true
https-port: 443
download-url:
download-type: filename
event-log:
path: /Users/uracle/temp/log/msp-gw/eventlogs/
enabled: true
cron: 0 0/30 * * * ?
app-store:
service-path: http://127.0.0.1/msp-admin/
bin-path: apk
upload-path: /apps/msp-admin/
file:
upload:
location: /Users/uracle/temp/trash/upload
http:
server:
url: http://localhost:9090
legacy:
url: http://localhost:28080/msp-gw/api/file/download/
download: /Users/uracle/temp/trash/download/
주요 섹션 및 설명
server.port
: 애플리케이션이 실행될 포트를 지정합니다.server.servlet.encoding
: 서블릿의 인코딩 설정을 정의합니다. UTF-8로 설정되어 있으며, 인코딩을 강제 적용하도록 설정되어 있습니다.server.servlet.context-path
: 애플리케이션의 기본 컨텍스트 경로를 설정합니다. 여기서는 /msp-gw로 설정되어 있습니다.spring.mvc
: 뷰 리졸버 설정으로, JSP 파일의 경로와 확장자를 지정합니다. /WEB-INF/jsp/ 경로에 .jsp 확장자를 가진 파일을 뷰로 사용합니다.msp.gateway
: gateway 라이브러리에서 사용하는 값을 정의한 섹션입니다.
msp.gateway.datasource
: 데이터베이스 연결 설정을 정의합니다. Oracle 데이터베이스 드라이버와 연결 URL, 사용자명, 비밀번호가 설정되어 있습니다. 지원하는 데이터베이스는 oracle, oracle9i, postgresql, oracle, mssql, informix, db2입니다.msp.gateway.mybatis
: MyBatis 설정으로, 사용하는 데이터베이스 플랫폼을 지정합니다. Mapper XML설정을 별도로 하지 않았을 경우, 해당 mybatis값을 통해 Mapper XML 경로가 자동으로 설정됩니다. 기본값은 다음과 같습니다. classpath*:/sqlmap/{msp.gateway.mybatis.platform}/**/*.xml
msp.gateway.resource-update
: 리소스 업데이트 관련 설정입니다. HTTPS 사용 여부와 포트를 지정합니다. download-url의 경우 지정하지 않을 경우 클라이언트의 접속 URL을 사용합니다.msp.gateway.event-log
: 이벤트 로그 설정으로, 로그 경로와 활성화 여부, 크론 표현식을 사용한 스케줄링을 정의합니다.msp.gateway.app-store
: AppStore 관련 설정입니다. 바이너리 경로, 업로드 경로, 서비스 경로를 지정합니다.애플리케이션에서 직접 데이터베이스 연결정보를 설정하여 사용하는 방식입니다. 지원하는 DBMS는 oracle, mysql, mssql, db2, informix, oracle9i, postgresql이며, 각 DBMS에 해당하는 driver-class-name
및 url
은 아래와 같습니다.
driver-class-name: oracle.jdbc.OracleDriver
url: jdbc:oracle:thin:@localhost:1521/XE
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
url: jdbc:sqlserver://localhost:1433;databaseName=test
driver-class-name: com.ibm.db2.jcc.DB2Driver
url: jdbc:db2://localhost:50000/test
driver-class-name: com.informix.jdbc.IfxDriver
url: jdbc:informix-sqli://localhost:9088/test:informixserver=ol_informix
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/test
아래의 예시는 oracle을 연결하는 예시입니다. 이 설정을 통해 Gateway 코어 라이브러리는 자동으로 Mybatis 설정을 구성합니다. 먼저 pom.xml에서 oracle 라이브러리 의존성을 추가합니다.
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>21.9.0.0</version>
</dependency>
msp.gateway.datasource 섹션에 driver-class-name, url, username, password를 정의합니다.
Note: mapper 경로는 sqlmap/**/**/*.xml 형식으로, 변경하지 않도록 주의합니다.
msp:
gateway:
datasource:
driver-class-name: oracle.jdbc.OracleDriver
url: jdbc:oracle:thin:@localhost:1521/XE
username: my_username
password: my_password
msp.gateway.datasource에 DB연결을 정의하면, msp-gateway 라이브러리에 있는 GatewayMybatisConfiguration
클래스에 의해 자동으로 Mybatis를 위한 SqlSessionFactory와 SqlSessionTemplate 설정이 진행됩니다. Mapper camel-case 옵션은 default로 설정되어 있습니다.
아래의 예시는 H2를 연결하는 예시입니다. H2는 테스트용 또는 학습용으로 사용되는 가벼운 데이터베이스입니다. schema.sql, data.sql을 준비합니다.
src/main/resources/
├── schema.sql <-- 테이블/시퀀스 생성 DDL
└── data.sql <-- 초기 INSERT 문
pom.xml에서 h2 라이브러리 의존성을 추가합니다.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
msp.gateway.datasource 섹션에 driver-class-name, url, username, password를 정의합니다.
msp:
gateway:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:test;MODE=Oracle
username: sa
password:
애플리케이션 시작 시 schema.sql, data.sql을 통해 자동으로 테이블을 생성하고 데이터를 초기화하기 위해 다음과 같은 초기화 클래스를 작성해야 제대로 동작합니다.
DataSourceInitializerConfiguration.java
@Configuration(proxyBeanMethods = false)
public class DataSourceInitializerConfiguration {
@Bean
SqlDataSourceScriptDatabaseInitializer sqlDataSourceScriptDatabaseInitializer(GatewayDataSourceContext context) {
SqlInitializationProperties sqlInitializationProperties = new SqlInitializationProperties();
// schema.sql과 data.sql의 위치를 설정
sqlInitializationProperties.setSchemaLocations(Collections.singletonList("classpath:schema.sql"));
sqlInitializationProperties.setDataLocations(Collections.singletonList("classpath:data.sql"));
return new SqlDataSourceScriptDatabaseInitializer(context.getDataSource(), sqlInitializationProperties);
}
}
gateway는 datasource뿐 아니라, JDNI 연결 방식도 지원합니다.
JNDI란? 애플리케이션 서버에 정의된 데이터베이스 연결정보를 참조하는 방식으로, 애플리케이션이 데이터베이스 연결 설정을 직접 관리하지 않고 애플리케이션 서버(Tomcat, WebLogic 등)가 제공하는 JDNI 리소스를 참조하여 데이터베이스에 연결하는 방식
Tomcat 기준으로 server.xml이나 context.xml 파일에서 JNDI 설정을 진행합니다.
<Context path="/">
<Resource name="jdbc/msp_mysql"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/[Database]?characterEncoding=UTF-8"
username="[DB 사용자]"
password="[DB 비밀번호]"
testOnBorrow="true"
minIdle="5"
maxActive="100"
maxIdle="10"
maxWait="-1"
/>
</Context>
application.yml에서 msp.gateway.datasource.jndi-name과 context.xml의 Resource name과 일치하도록 작성합니다.
msp:
gateway:
datasource:
jndi-name: jdbc/msp_mysql
기본적으로 msp.gateway.datasource를 통해 데이터베이스를 연결하지만 추가적인 데이터베이스 연결이 필요할 경우 applicaiton.yaml 파일에 spring.datdasource 섹션을 통해 신규 datasource설정을 추가합니다. 아래 예시는 oracle과 h2를 연결하는 예제입니다.
# DB Connection 1
spring:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:test;MODE=Oracle
username: sa
password:
sql:
init:
schema-locations: classpath:h2/schema.sql
data-locations: classpath:h2/data.sql
mode: always
mybatis:
mapper-locations: classpath:/sqlmap/h2/**/*.xml
# DB Connection 2
msp:
gateway:
datasource:
driver-class-name: oracle.jdbc.OracleDriver
url: jdbc:oracle:thin:@127.0.0.1:1521:UDB
username: lab
password: lab
mybatis:
mapper-locations: classpath:/sqlmap/oracle/**/*.xml
리소스 파일 버전을 확인하여 최신 리소스 파일 정보를 조회하는 기능으로, 다운로드 설정이 필요합니다.
msp:
gateway:
resource-update:
use-force-https: true
https-port: 443
download-url:
download-type: filename
use-force-https
: 리소스 zip 파일 다운로드 URL은 요청 프로토콜에 관계없이 항상 HTTPS로 제공 유무(true/false)https-port
: https 사용 시 기본 포트가 아닌 경우 port 지정download-url
: 리소스 다운로드 URL (미지정 시 클라이언트의 접속 URL 사용)download-type
: 리소스 다운로드 방식 선택
filename
: 기본 값으로, NAS 또는 HTTP 서버를 사용하여 zip 파일을 직접 다운로드. (파일 이름 포함으로, GET 방식입니다)file_id
: WAS에 파일 ID를 전송하여 다운로드. (zip 파일 이름 사용하지 않습니다.)gateway는 API 요청에 대한 파라미터 및 요청API URL을 기록하는 이벤트 로깅 기능이 있습니다. enabled 옵션이 true일 경우 동작하며, 기록 시점은 API요청 후 로직 처리가 완료된 후 입니다.
msp:
gateway:
event-log:
path: /Users/uracle/temp/log/msp-gw/eventlogs/
enabled: true
cron: 0 0/30 * * * ?
path
: 이벤트 로그가 쌓일 경로enabled
: 이벤트 로그 사용 여부(true/false)cron
: 이벤트 로그 배치 주기이벤트 로그 사용 여부가 true일 경우 Spring Boot Scheduler가 동작하여 이벤트 로그 저장 경로(path)에 stat_{yyyyMMdd}.log 형식의 파일이 생성됩니다. 로그 내용은 아래와 같습니다.
0|1.0|TEST_APP|26|Android|111111223333338|SM-N960F|01099999999|/api/res/auto-update||PostmanRuntime/7.36.0|0:0:0:0:0:0:0:1|2024-01-16 10:40:12||||com.uracle.push.demo
각 항목에 대한 설명은 다음과 같습니다.
|번호|앱 버전|앱 이름|시스템 버전|시스템 이름|디바이스 아이디|디바이스 모델|전화번호|회사 코드|서비스 코드|사용자 에이전트|호스트|생성 일시|사용자 아이디|사용자 이름|페이지 이름|앱 아이디
구분자(‘|’)를 기준으로 파싱하여 하루 뒤에 Database에 저장됩니다. 읽은 파일은 stat_{yyyyMMdd}.log.stored_yyyyMMddHH24mmss_index
형식으로 변경됩니다.
stat_20240227.log.stored_20240228160100_1
인하우스 배포 기능을 사용하실 경우, App Store 설정이 필요합니다.
msp:
gateway:
app-store:
service-path: http://127.0.0.1/msp-admin/
bin-path: apk
upload-path: /apps/msp-admin/
bin-path
: binary 경로service-path
: 스토어에서 배포한 앱을 다운받을수 있는 Web Admin URL 주소(Admin페이지 주소 + ContextRoot)upload-path
: 스토어에서 배포할 앱이 저장될 물리적인 디렉토리 경로(웹서버 WEB-INF가 있는 부모 디렉토리 풀경로)file:
upload:
location: /Users/uracle/temp/upload
http:
server:
url: http://localhost:9090
legacy:
url: http://localhost:8080/msp-gw/api/file/download/
download: /Users/uracle/temp/download/
push:
url: http://127.0.0.1:8380
file.upload.location
: 파일 업로드 및 다운로드 시 사용할 로컬 경로 (참고: FileService.java
)http.server.url
: RestTemplate을 사용하여 API 프록시 요청 시 사용할 서버 URL (참고: HttpProxyController.java
)http.legacy.url
: 레거시 시스템에서 파일을 다운로드 할 기본 URL (참고: HttpProxyDownloadService.java
)http.legacy.download
: 레거시 시스템에서 다운로드한 파일을 저장할 로컬 경로 (참고: HttpProxyDownloadService.java
)http.push.url
: 푸시 서비스 API에 대한 프록시 요청 시 사용할 기본 URL (참고: PushController.java
)/msp-gw-boot-web
├── pom.xml # Maven 프로젝트 설정 파일
├── README.md # 프로젝트 설명 문서
├── src # 소스 코드 디렉토리
│ ├── main
│ │ ├── java
│ │ │ └── kr
│ │ │ └── msp
│ │ │ ├── WebApplication.java # Spring Boot 애플리케이션 진입점
│ │ │ ├── config
│ │ │ │ ├── PropertyConfig.java # 설정 프로퍼티 로더
│ │ │ │ └── WebConfig.java # 웹 MVC 관련 설정
│ │ │ ├── example
│ │ │ │ ├── basic
│ │ │ │ │ ├── SampleController.java # 샘플 REST 컨트롤러
│ │ │ │ │ ├── SampleMapper.java # 샘플 MyBatis 매퍼 인터페이스
│ │ │ │ │ ├── SampleService.java # 샘플 비즈니스 로직 서비스
│ │ │ │ │ ├── dto
│ │ │ │ │ │ └── User.java # 사용자 DTO
│ │ │ │ │ └── util
│ │ │ │ │ └── PropertiesUtil.java # 환경 설정 유틸 클래스
│ │ │ │ ├── file
│ │ │ │ │ ├── FileInfo.java # 파일 메타정보 DTO
│ │ │ │ │ ├── FileProperties.java # 파일 처리 관련 프로퍼티
│ │ │ │ │ └── FileService.java # 파일 처리 서비스
│ │ │ │ └── http
│ │ │ │ ├── HttpProperties.java # HTTP 관련 프로퍼티 설정
│ │ │ │ ├── controller
│ │ │ │ │ ├── HttpProxyController.java # 프록시 API 컨트롤러
│ │ │ │ │ └── PushController.java # 푸시 API 컨트롤러
│ │ │ │ ├── dto
│ │ │ │ │ ├── HttpResponse.java # 프록시 응답 DTO
│ │ │ │ │ ├── PushResult.java # 푸시 결과 DTO
│ │ │ │ │ ├── PushSendResult.java # 푸시 전송 결과 DTO
│ │ │ │ │ ├── RequestParameter.java # 프록시 요청 파라미터
│ │ │ │ │ └── Result.java # 공통 결과 DTO
│ │ │ │ ├── service
│ │ │ │ │ ├── HttpProxyDownloadService.java # 레거시 파일 다운로드 서비스
│ │ │ │ │ ├── HttpProxyLegacyService.java # 레거시 파일 핸들러
│ │ │ │ │ ├── HttpProxyService.java # HTTP 프록시 비즈니스 로직
│ │ │ │ │ └── PushService.java # 푸시 메시지 전송 서비스
│ │ │ │ └── tcp
│ │ │ │ ├── TcpAliveManager.java # TCP 연결 상태 관리
│ │ │ │ └── TcpAliveThread.java # TCP Alive 스레드
│ │ ├── resources
│ │ │ ├── application.yml # 애플리케이션 설정 파일
│ │ │ ├── log4j2.xml # 로그 설정 파일
│ │ │ ├── sqlmap
│ │ │ │ └── oracle
│ │ │ │ └── sample
│ │ │ │ └── sample.xml # 샘플 Mapper XML (SQL 정의)
│ │ │ ├── static
│ │ │ │ └── css
│ │ │ │ └── sample.css # 샘플 스타일시트
│ │ │ └── WEB-INF
│ │ │ └── config
│ │ │ ├── license.cer # 라이선스 인증서 파일
│ │ │ └── license.key # 라이선스 키 파일
│ │ └── webapp
│ │ └── WEB-INF
│ │ └── jsp
│ │ ├── index.jsp # 메인 페이지 JSP
│ │ └── userList.jsp # 사용자 리스트 JSP
msp-gw-boot-web에서 제공하는 샘플 REST API 목록과 설명입니다. 사용자 정보 조회, 파일 업로드, HTTP 프록시, 푸시 메시지 연동 등의 기능을 예시로 제공합니다.
Package | API URL | HTTP Method | 설명 |
---|---|---|---|
kr.msp.example.basic | / |
GET | index.jsp 페이지를 반환하는 기본 메인 엔드포인트입니다. 브라우저 테스트 용도로 사용됩니다. |
/api/basic/sample/userList |
GET | SAMPLE_USER 테이블 전체 데이터를 조회하고 userList.jsp로 전달하여 화면에 렌더링합니다. | |
/api/basic/sample/{id} |
GET | 경로 변수 id에 해당하는 사용자 정보를 조회하고, 결과를 JSON 형태로 반환합니다. 데이터가 없으면 204 No Content 응답을 반환합니다. | |
/api/basic/sample/list |
GET | 사용자 정보를 Map 형태의 리스트 (List<Map<String, Object>>)로 반환합니다. 동적 필드 구조가 필요한 경우에 적합합니다. | |
/api/basic/sample/dto/list |
GET | 사용자 정보를 User DTO 형태의 리스트 (List<User>)로 반환합니다. 정적 타입 기반 API 설계에 적합합니다. | |
/api/basic/sample/config |
GET | application.yml 설정 값을 조회하는 디버깅용 API입니다. 운영환경에서는 노출을 제한하는 것이 권장됩니다. | |
kr.msp.example.file | /api/file/upload |
POST | multipart/form-data 방식으로 파일을 업로드합니다. 파일은 file.upload.location 경로에 저장됩니다. |
/api/file/download/{fileExtension}/{fileId} |
GET | 지정된 파일 ID에 해당하는 파일을 다운로드합니다. fileExtension은 클라이언트에서의 저장 확장자입니다. | |
kr.msp.example.http | /api/proxy/sample |
POST | 내부 RestTemplate을 통해 외부 API 서버에 요청을 프록시합니다. 테스트 또는 연동용으로 사용됩니다. |
/api/http/legacy/proxy |
POST | http.legacy.url 설정을 기반으로 레거시 시스템에 API 또는 파일 요청을 수행합니다. | |
/api/proxy/download/{fileExtension}/{fileId} |
GET | 레거시 시스템에서 지정된 파일을 다운로드합니다. 다운로드 경로는 http.legacy.download 설정을 따릅니다. | |
/api/push/user/regist |
POST | 푸시 서비스 가입 및 사용자 등록 요청을 외부 PUSH 서비스로 프록시합니다. | |
/api/push/send |
POST | 외부 푸시 시스템에 푸시 메시지를 전송하는 API입니다. 대상과 메시지 정보를 JSON으로 전달해야 합니다. |
이 예제는 Morpheus Gateway의 커스텀 Request/Response 구조를 기반으로, 도서 목록을 조회하는 REST API를 구현하는 방법을 설명합니다. 해당 예제에서 사용하는 도서 관련 데이터는 해당 사이트에서 참고하였습니다. https://www.databasestar.com/sample-bookstore-database/
클라이언트가 서버로 요청을 보낼 때, RequestHeader와 바디를 조합한 Request 객체를 사용합니다. 서버는 요청을 처리한 후, ResponseHeader(상태코드 포함)와 바디를 조합한 Response 객체로 응답합니다. 응답 헤더의 resultCode는 ResponseCode enum을 사용하여 상태를 명확히 전달합니다. 모든 객체는 제네릭 및 빌더 패턴을 통해 유연하게 확장 및 사용 가능합니다.
요청 객체: Request<RequestHeader, BookParameter>
RequestHeader
에는 단말기 정보, 앱 정보, 사용자 정보 등 공통 요청 헤더 정보가 포함됩니다.BookParameter
는 검색 조건(예: 도서 제목, 저자 등)을 포함하는 도메인 객체입니다.응답 객체: ResponseEntity<Response<ResponseHeader, List<BookList>>>
ResponseHeader
: 처리 결과 코드 및 메시지를 포함body
: 실제 도서 정보 리스트예시 JSON 요청:
{
"head": {
},
"body": {
"title": "life" //책 제목에 life가 포함된 책을 검색합니다
}
}
예시 Controller:
@PostMapping(value = "/api/book/list")
public ResponseEntity<Response<ResponseHeader, List<BookList>>> getBooKList(
Request<RequestHeader, BookParameter> request) {
List<BookList> bookList = bookService.getBookList(request.getBody());
ResponseHeader responseHeader = new ResponseHeader();
responseHeader.setResultCode(ResponseCode.OK);
responseHeader.setResultMessage(Const.SUCCESS);
return ResponseEntity.ok(new Response<>(responseHeader, bookList));
}
RequestHeader
에는 클라이언트의 요청 정보 → Request 클래스의 head
에 담습니다.
BookParameter
는 책 정보 조회 시 조건을 담은 DTO 객체 → Request 클래스의 body
에 담습니다.
ResponseHeader
(결과코드(result_code), 결과 메시지(result_msg)를 포함한 객체) → Response의 head에 담습니다.
BookList
는 데이터베이스에서 조회한 책 정보를 담는 DTO 객체 → Response의 body에 담습니다.
예시 JSON 응답:
{
"head": {
"result_code": "200",
"result_msg": "조회 성공"
},
"body": [
{
"bookId": "4",
"title": "What Life Was Like in the Jewel in the Crown: British India AD 1600-1905",
"isbn13": "34406054602",
"languageName": "English",
"numPages": "168",
"publicationDate": "1999-09-01",
"publisherName": "Time Life Medical",
"authorName": "Time-Life Books"
},
{
"bookId": "6",
"title": "Life Is a Dream and Other Spanish Classics (Eric Bentley's Dramatic Repertoire) - Volume II",
"isbn13": "73999140774",
"languageName": "English",
"numPages": "298",
"publicationDate": "2000-04-01",
"publisherName": "Applause Theatre and Cinema Book Publishers",
"authorName": "Eric Bentley"
}
]
}
인터페이스 객체인 BookMapper는 데이터 접근을 위한 객체이며 생성자를 통해 주입합니다.
호출부분은 Controller의 List<BookList> bookList = bookService.getBookList(request.getBody());
이며 getBookList() 메서드는 bookMapper객체의 getBookList(request.getBody())
메서드를 호출하여 조회한 결과를 반환하게 됩니다. 반환 타입은 List<BookList>
형태입니다.
방법 1) msp.gateway.datasource 섹션을 통해 DB연결을 정의한 경우 반드시 아래와 같이 작성합니다.
@Service
public class BookService {
private final SqlSessionTemplate sqlSessionTemplate;
public BookService(SqlSessionTemplate sqlSessionTemplate){
this.sqlSessionTemplate = sqlSessionTemplate;
}
public List<BookList> getBookList(BookParameter bookparameter) {
BookMapper bookMapper = sqlSessionTemplate.getMapper(BookMapper.class);
return bookMapper.getBookList(bookparameter);
}
}
방법 2) spring.datasource를 섹션을 통해 DB연결을 정의한 경우, 방법1 또는 아래와 같이 작성이 가능합니다.
@Service
public class BookService {
private final BookMapper bookMapper;
public BookService(BookMapper bookMapper) {
this.bookMapper = bookMapper;
}
public List<BookList> getBookList(BookParameter bookparameter) {
return bookMapper.getBookList(bookparameter);
}
}
BookMapper 인터페이스는 데이터베이스에서 책 목록을 조회하는 기능을 정의합니다. BookService 클래스가 이 인터페이스를 구현하여, 실제 데이터 접근 로직을 구현합니다.
@Mapper
public interface BookMapper {
List<BookList> getBookList(BookParameter bookparameter);
}
book.xml은 Mybatis를 사용하여 데이터베이스에서 책 목록을 조회하는 Mapper XML파일 입니다. 이 쿼리문은 책과 관련된 여러 테이블을 조인하여 책 정보, 언어 정보, 출판사 정보, 저자 정보를 가져오며, title의 속성값이 null또는 빈 문자열이 아닐경우 title 필드에 대한 LIKE 조건을 추가하며, 최대 10건의 결과만 반환하도록 작성되어있습니다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.msp.example.mapper.BookMapper">
<select id="getBookList" parameterType="kr.msp.example.dto.BookParameter" resultType="kr.msp.example.dto.BookList">
select book.book_id
, book.title
, book.isbn13
, language.language_name
, book.num_pages
, book.publication_date
, publisher.publisher_name
, author.author_name
from
book book, book_language language, publisher publisher, book_author book_author, author author
where book.language_id = language.language_id
and book.publisher_id = publisher.publisher_id
and book.book_id = book_author.book_id
and book_author.author_id = author.author_id
<if test="title != null and title != ''">
and book.TITLE LIKE '%' || #{title} || '%'
</if>
order by book_id
limit 10
</select>
</mapper>
REST API로 조회한 도서 목록을 JSP 뷰에서 표 형태로 출력하는 방법을 설명합니다. Controller에서 전달된 bookList 데이터를 JSTL을 통해 렌더링합니다.
bookList.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<html>
<head>
<style>
table, td, th {
border : 1px solid black;
border-collapse : collapse;
padding: 8px;
}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>도서 목록</title>
</head>
<body>
<h2>도서 목록</h2>
<table>
<thead>
<tr>
<th>도서 ID</th>
<th>제목</th>
<th>ISBN</th>
<th>언어</th>
<th>페이지 수</th>
<th>출판일</th>
<th>출판사</th>
<th>저자</th>
</tr>
</thead>
<tbody>
<c:forEach var="book" items="${bookList}">
<tr>
<td>${book.bookId}</td>
<td>${book.title}</td>
<td>${book.isbn13}</td>
<td>${book.languageName}</td>
<td>${book.numPages}</td>
<td>${book.publicationDate}</td>
<td>${book.publisherName}</td>
<td>${book.authorName}</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
bookList.jsp 페이지를 호출하는 간단한 controller를 작성합니다.
해당 REST API는 GET방식으로 호출되며, URL은 http://${SERVER_HOST}:${SERVER_PORT}/${SERVER_CONTEXT}/book/list/view
입니다.
@GetMapping(value = "/book/list/view")
public ModelAndView getBookListView() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("bookList", bookService.getBookList());
modelAndView.setViewName("bookList");
return modelAndView;
}
line 4 - bookList 이름으로 서비스로부터 받아온 사용자 목록 데이터를 modelAndView 객체에 추가하며, 뷰에서 bookList 데이터를 사용할 수 있습니다. line 5 - 뷰 이름은 bookList.jsp로 매핑됩니다. line 6 - 설정된 ModelAndView 객체를 반환합니다.
spring:
mvc:
view:
prefix: /WEB-INF/jsp/
suffix: .jsp
위 설정에 따라 modelAndView.setViewName("bookList")는 /WEB-INF/jsp/bookList.jsp를 의미합니다.
다음 경로에 bookList.jsp 파일을 위치시켜야 합니다
src/main/webapp/WEB-INF/jsp/bookList.jsp