spring boot 3.1.6 버전
java 17 버전을 사용했습니다
Node 20.9.0 버전
Next.js는 14.0.3 버전 사용했습니다
H2 데이터베이스를 임시로 사용했는데 로컬 DB 나아가서 클라우드 DB까지 데이터를 연결해보겠습니다
먼저 서로다른 플렛폼에서 데이터를 주고 받기위해선
CORS 오류를 해결해야합니다
# application.properties
spring.mvc.cors.mapping=/**
spring.mvc.cors.allowed-origins=*
spring.mvc.cors.allowed-methods=GET,POST,PUT,DELETE
spring.mvc.cors.allowed-headers=*
앱 설정에서 먼저 위 코드를 작성해서 CORS 오류를 해결해줍니다
먼저 JPA를 설치하기위해
다음 코드를 작성하고 Gradle
lombok, JPA, h2를 설치해줍니다
dependencies {
...
implementation('org.projectlombok:lombok')
annotationProcessor('org.projectlombok:lombok')
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.h2database:h2'
}
폴더 구조 입니다 과거에 폴더 구조를 확립했을때가 있었는데 까먹어서 data란 폴더를 만들고 진행했습니다
@Entity를 사용하여 이름과 ID(식별자)만 있는 엔티티를 만들어줍니다
@Entity
@Setter
@Getter
public class TestEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
private String name;
public TestEntity(){
// Jpa 필요한 기본 생성자
}
public TestEntity(String name) {
this.name= name;
}
}
lombok을 이용하여 간단하게 getter setter를 만들어준 뒤 @GeneratedValue 를 이용하여 자동으로 ID값을 유니크하게 설정하게 했습니다
Repository를 만들때 확장의 타입을 Entity로 설정합니다
그리고 findByname 이라는 List를 만들어서 검색가능하게 만듭니다
public interface TestEntityRepository extends JpaRepository<TestEntity,Long> {
// 사용자의 쿼리 방법을 구술할 페이지
// 이름으로 엔터티를 찾는 사용자 정의 쿼리 방법
List<TestEntity> findByName(String name);
}
Service 단에서는 2가지 서비스를 구현합니다
1. 저장하는 서비스
2. 이름을 기준으로 검색하는 서비스
@Service
public class TestEntityService {
private final TestEntityRepository testEntityRepository;
@Autowired
public TestEntityService(TestEntityRepository testEntityRepository){
this.testEntityRepository = testEntityRepository;
}
// 비즈니스 로직을 작성하는칸
public TestEntity saveEntity(String name){
TestEntity newEntity = new TestEntity();
newEntity.setName(name);
return testEntityRepository.save(newEntity);
}
// 사용자 정의 쿼리 방법을 사용하여 이름으로 엔터티를 찾습니다.
public List<TestEntity> findTestEntityByName(String name){
return testEntityRepository.findByName(name);
}
}
2개의 API주소를 만들어서 컨트롤러에서 구현했습니다
1번은 Json 형식으로 아이디를 저장하고 2번은 해당 아이디를 조회합니다
@RestController
@RequestMapping("/api")
public class TestEntityController {
private final TestEntityService testEntityService;
@Autowired
public TestEntityController(TestEntityService testEntityService){
this.testEntityService = testEntityService;
}
@CrossOrigin(origins = "http://localhost:3000")
@PostMapping(value = "/entities", consumes = "application/json")
public ResponseEntity<TestEntity> saveEntity(@RequestBody Map<String, String> requestBody){
String name = requestBody.get("name");
if(name == null || name.isEmpty()){
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
TestEntity saveEntity = testEntityService.saveEntity(name);
return new ResponseEntity<>(saveEntity, HttpStatus.CREATED);
}
@GetMapping("/entities")
public ResponseEntity<List<TestEntity>> findTestEntityByName(@RequestParam String name){
List<TestEntity> entities = testEntityService.findTestEntityByName(name);
return new ResponseEntity<>(entities, HttpStatus.OK);
}
}
post로 Json 형식으로 받을땐 RequestBody 를 사용하고 Get으로 주소창에서 받아올땐 RequestParam 을 사용했습니다
프론트에서는 데이터를 입력할 수 있는 간단한 페이지 구성과 데이터를 Request하는 actions를 만들어줬습니다
interface TestEntity {
id: number;
name: string;
}
export const setName = async (name : string): Promise<TestEntity | undefined> => {
try{
const response = await axios.post<TestEntity>(
'http://localhost:8080/api/entities',
{name : name}
)
const responseData = response.data;
console.log('Set Name API Response:', responseData);
return responseData
}
catch (error : any){
console.error('Set Name Error:', error.message);
throw error;
}
}
export default function Home() {
const [inputValue, setInputValue] = useState('');
const handleInputChange = (e : any) => {
setInputValue(e.target.value);
}
const handleApiCall = async () => {
try {
const data = await setName(inputValue);
console.log('API Response:',data)
} catch(error) {
console.error('Error:',error)
}
}
const test = getData()
return (
<main>
<div>
<label>
Enter Name:
<input type="text" value={inputValue} onChange={handleInputChange}/>
</label>
<button onClick={handleApiCall}>OK</button>
</div>
</main>
)
}
데이터를 받아오고 화면에 뿌려주는 페이지그리고 삭제 버튼을 만들어서 누르면 삭제되는 기능을 만들어보려고 합니다