2025. 3. 2. 22:41ㆍSpring Microservice
🎯 1. Spring Boot 컨트롤러의 역할
Spring Boot에서 컨트롤러는 서비스 엔드포인트를 노출하고 HTTP 요청을 처리하는 핵심 역할을 합니다.
🔹 RESTful API의 핵심 원칙
✅ HTTP/HTTPS 사용 → 서비스 호출은 HTTP 프로토콜을 통해 수행
✅ 표준 HTTP 메서드 활용 → GET
, POST
, PUT
, DELETE
✅ JSON 기반 데이터 직렬화 → JSON을 통해 데이터를 주고받음
✅ HTTP 상태 코드 활용 → 200(성공), 404(찾을 수 없음), 500(서버 오류) 등
🏗 2. Spring Boot 컨트롤러 클래스 구현
📝 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.optimagrowth</groupId>
<artifactId>licensing-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Licensing Service</name>
<description>OStock Licensing Service</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
컨트롤러는 @RestController
와 @RequestMapping
을 활용해 REST API 엔드포인트를 정의합니다.
📝 LicenseController.java
package com.optimagrowth.license.controller;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(value="v1/organization/{organizationId}/license")
public class LicenseController {
}
🔹 @RestController
→ REST API를 제공하는 컨트롤러로 선언
🔹 @RequestMapping
→ 모든 엔드포인트의 기본 URL 설정
📄 3. License 모델 클래스
라이선스 정보를 저장하는 POJO(Plain Old Java Object) 클래스입니다.
📝 License.java
package com.optimagrowth.license.model;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter @ToString
public class License {
private int id;
private String licenseId;
private String description;
private String organizationId;
private String productName;
private String licenseType;
}
✅ Lombok 활용 (@Getter
, @Setter
, @ToString
) → 불필요한 코드 생략
⚙ 4. LicenseService 클래스 (비즈니스 로직)
비즈니스 로직을 담당하며 CRUD(Create, Read, Update, Delete) 기능을 수행합니다.
📝 LicenseService.java
package com.optimagrowth.license.service;
import java.util.Random;
import org.springframework.stereotype.Service;
import com.optimagrowth.license.model.License;
@Service
public class LicenseService {
public License getLicense(String licenseId, String organizationId){
License license = new License();
license.setId(new Random().nextInt(1000));
license.setLicenseId(licenseId);
license.setOrganizationId(organizationId);
license.setDescription("Software product");
license.setProductName("Ostock");
license.setLicenseType("full");
return license;
}
public String createLicense(License license, String organizationId){
license.setOrganizationId(organizationId);
return String.format("Created license: %s", license.toString());
}
public String updateLicense(License license, String organizationId){
license.setOrganizationId(organizationId);
return String.format("Updated license: %s", license.toString());
}
public String deleteLicense(String licenseId, String organizationId){
return String.format("Deleting license with id %s for the organization %s", licenseId, organizationId);
}
}
🔹 @Service
→ 서비스 계층을 정의하여 비즈니스 로직 분리
🔹 랜덤 값으로 ID를 생성해 샘플 데이터를 반환
🔗 5. REST API 엔드포인트 구현
컨트롤러에서 GET
, POST
, PUT
, DELETE
요청을 처리하는 CRUD API를 구현합니다.
📝 LicenseController.java
package com.optimagrowth.license.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.optimagrowth.license.model.License;
import com.optimagrowth.license.service.LicenseService;
@RestController
@RequestMapping(value="v1/organization/{organizationId}/license")
public class LicenseController {
@Autowired
private LicenseService licenseService;
// 🟢 GET: 라이선스 조회
@GetMapping(value="/{licenseId}")
public ResponseEntity<License> getLicense(
@PathVariable("organizationId") String organizationId,
@PathVariable("licenseId") String licenseId) {
License license = licenseService.getLicense(licenseId, organizationId);
return ResponseEntity.ok(license);
}
// 🟡 POST: 라이선스 생성
@PostMapping
public ResponseEntity<String> createLicense(
@PathVariable("organizationId") String organizationId,
@RequestBody License request) {
return ResponseEntity.ok(licenseService.createLicense(request, organizationId));
}
// 🔵 PUT: 라이선스 업데이트
@PutMapping
public ResponseEntity<String> updateLicense(
@PathVariable("organizationId") String organizationId,
@RequestBody License request) {
return ResponseEntity.ok(licenseService.updateLicense(request, organizationId));
}
// 🔴 DELETE: 라이선스 삭제
@DeleteMapping(value="/{licenseId}")
public ResponseEntity<String> deleteLicense(
@PathVariable("organizationId") String organizationId,
@PathVariable("licenseId") String licenseId) {
return ResponseEntity.ok(licenseService.deleteLicense(licenseId, organizationId));
}
}
🔹 @GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
→ 각 HTTP 메서드에 맞는 API 구현
🔹 @RequestBody
→ JSON 데이터를 객체로 변환
※ 실행 결과
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
[32m :: Spring Boot :: [39m [2m (v3.4.3)[0;39m
[2m2025-03-03T11:11:06.358+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [ main] [0;39m[36mc.o.license.LicensingServiceApplication [0;39m [2m:[0;39m Starting LicensingServiceApplication using Java 17.0.9 with PID 35688 (C:\development\Workspace\codes\spring_boot3\springmsinaction\ch02\licensing-service\target\classes started by inthe in C:\development\Workspace\codes\spring_boot3\springmsinaction\ch02\licensing-service)
[2m2025-03-03T11:11:06.362+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [ main] [0;39m[36mc.o.license.LicensingServiceApplication [0;39m [2m:[0;39m No active profile set, falling back to 1 default profile: "default"
[2m2025-03-03T11:11:07.335+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [ main] [0;39m[36mo.s.b.w.embedded.tomcat.TomcatWebServer [0;39m [2m:[0;39m Tomcat initialized with port 8080 (http)
[2m2025-03-03T11:11:07.345+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [ main] [0;39m[36mo.apache.catalina.core.StandardService [0;39m [2m:[0;39m Starting service [Tomcat]
[2m2025-03-03T11:11:07.345+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [ main] [0;39m[36mo.apache.catalina.core.StandardEngine [0;39m [2m:[0;39m Starting Servlet engine: [Apache Tomcat/10.1.36]
[2m2025-03-03T11:11:07.385+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [ main] [0;39m[36mo.a.c.c.C.[Tomcat].[localhost].[/] [0;39m [2m:[0;39m Initializing Spring embedded WebApplicationContext
[2m2025-03-03T11:11:07.386+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [ main] [0;39m[36mw.s.c.ServletWebServerApplicationContext[0;39m [2m:[0;39m Root WebApplicationContext: initialization completed in 976 ms
[2m2025-03-03T11:11:07.876+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [ main] [0;39m[36mo.s.b.a.e.web.EndpointLinksResolver [0;39m [2m:[0;39m Exposing 1 endpoint beneath base path '/actuator'
[2m2025-03-03T11:11:07.937+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [ main] [0;39m[36mo.s.b.w.embedded.tomcat.TomcatWebServer [0;39m [2m:[0;39m Tomcat started on port 8080 (http) with context path '/'
[2m2025-03-03T11:11:07.949+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [ main] [0;39m[36mc.o.license.LicensingServiceApplication [0;39m [2m:[0;39m Started LicensingServiceApplication in 1.999 seconds (process running for 2.658)
[2m2025-03-03T11:11:08.565+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [on(9)-127.0.0.1] [0;39m[36mo.a.c.c.C.[Tomcat].[localhost].[/] [0;39m [2m:[0;39m Initializing Spring DispatcherServlet 'dispatcherServlet'
[2m2025-03-03T11:11:08.565+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [on(9)-127.0.0.1] [0;39m[36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Initializing Servlet 'dispatcherServlet'
[2m2025-03-03T11:11:08.566+09:00[0;39m [32m INFO[0;39m [35m35688[0;39m [2m--- [Licensing Service] [on(9)-127.0.0.1] [0;39m[36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Completed initialization in 1 ms
🛠 6. API 테스트 (Postman 활용)
📌 Postman을 사용해 API를 테스트한 결과
🟢 1) GET 요청 (라이선스 조회)
GET http://localhost:8080/v1/organization/optimaGrowth/license/0235431845
🟡 2) POST 요청 (라이선스 생성)
POST http://localhost:8080/v1/organization/optimaGrowth/license
✅ Body (JSON)
{
"licenseId": "0235431845",
"organizationId": "optimaGrowth",
"description": "Software product",
"productName": "Ostock",
"licenseType": "complete"
}
🔵 3) PUT 요청 (라이선스 업데이트)
PUT http://localhost:8080/v1/organization/optimaGrowth/license
✅ Body (JSON)
{
"licenseId": "0235431845",
"organizationId": "optimaGrowth",
"description": "Software product",
"productName": "Ostock",
"licenseType": "complete"
}
🔴 4) DELETE 요청 (라이선스 삭제)
DELETE http://localhost:8080/v1/organization/optimaGrowth/license/0235431845
🎉 7. 결론
✅ Spring Boot 기반 RESTful API 마이크로서비스 개발 완료!
✅ @RestController
, @RequestMapping
, @PathVariable
, @RequestBody
등을 활용해 CRUD API 구성
✅ Postman을 활용한 API 테스트 성공 🚀
💡 다음 단계 → 다국어 지원(국제화) 기능 추가! 🌍🔥
'Spring Microservice' 카테고리의 다른 글
Implementing Spring HATEOAS to display related links (0) | 2025.03.03 |
---|---|
Adding internationalization into the licensing service (0) | 2025.03.02 |
The developer’s tale: Building a microservice with Spring Boot and Java (0) | 2025.03.02 |
3.Building microserviceswith Spring Boot (0) | 2025.03.02 |
Getting started with the skeleton project (0) | 2025.03.02 |