추가(POST) 해도 세팅한 값만 오는 문제
-> 새로고침 하면 리셋됨 = 가짜 서버라 저장된 데이터 변화 X
파이썬 : GOAT
문법이 간결하고 개발 속도가 빠르다.
인스타그램이 Django임
Java는 그냥 시중에 돌아다니는 17버전 ㄱㄱ
1.
스프링 프로젝트 파일 다운로드
위 링크로 들어가서 초록색의 Code 버튼을 누르고 Download ZIP 버튼을 눌러 압축된 프로젝트를 다운로드합니다.
위 링크는 GitHub 로, 개발자들이 프로젝트를 올리고 공유하는 허브입니다!
파일 탐색기가 열리면, 방금 압축을 푼 폴더 (예: wishlist-backend-main)를 선택하고 OK를 누릅니다.
IntelliJ가 "Trust and Open Project?"라고 물으면 Trust Project 버튼을 눌러 프로젝트를 신뢰합니다.
IntelliJ가 프로젝트를 불러온 후, 오른쪽 하단에서 Gradle이 프로젝트를 동기화하고 의존성(라이브러리)을 다운로드하는 것을 기다려야 합니다. (1~3분 정도 소요될 수 있습니다.)
wishlist/
└── src/main/java/com/sparta/wishlist/
├── controller/ # 🤵 API 진입점
│ └── ItemController.java
│
├── service/ # 🧑🍳 비즈니스 로직 (핵심 요리)
│ ├── ItemService.java
│ └── ItemServiceImpl.java
│
├── repository/ # 🧊 데이터 저장소
│ ├── ItemRepository.java
│ ├── InMemoryItemRepository.java
│ └── DatabaseItemRepository.java
│
├── dto/ # 📝 데이터 전송 객체
│ ├── ItemRequestDto.java
│ └── ItemResponseDto.java
│
├── entity/ # 🍱 서버 자원
│ └── Item.java
│
├── exception/ # ⚠️ 예외 처리
│ ├── CustomException.java
│ ├── ErrorCode.java
│ ├── ErrorResponse.java
│ └── GlobalExceptionHandler.java
│
├── config/ # ⚙️ 설정
│ └── DatabaseConfig.java
│
└── WishlistApplication.java # 🚀 서버 실행 파일
src/main/java/com/sparta/wishlist/ : 프로젝트의 '진짜' Java 코드가 위치하는 소스(source) 폴더입니다. React의 src/와 같습니다.
controller/ : '주방 매니저'의 영역입니다. API 명세서처럼 클라이언트의 HTTP 요청(GET, POST 등)을 가장 먼저 받는 진입점(Endpoint)입니다.
ItemController.java : "주방 매니저"입니다. 주문서(DTO)를 검사하고, 실제 요리는 ItemService에게 시킵니다.
service/ : 🧑🍳 '메인 셰프'의 영역입니다. "상품을 수정하기 전에 존재하는지 확인하라"와 같은 핵심 비즈니스 로직을 담당합니다.
ItemService.java : '메인 셰프'가 지켜야 할 '규칙'(인터페이스)입니다. "저장하기", "조회하기" 기능이 있어야 함을 정의합니다.
ItemServiceImpl.java : '메인 셰프'의 '실제 행동'(구현체)입니다. ItemRepository를 호출하여 실제 로직을 수행합니다.
repository/ : 🧊 '저장소 관리인'의 영역입니다. 오직 데이터베이스와의 통신만 책임집니다.
ItemRepository.java : '저장소'가 지켜야 할 '규칙'(인터페이스)입니다. "데이터베이스에서 저장", "데이터베이스에서 조회" 기능 등을 정의합니다.
InMemoryItemRepository.java : '임시 저장소'(구현체)입니다. @Profile("memory")이 붙여주어, '메모리'라는 서버가 종료되면 휘발되는 저장소에서 작동합니다.
DatabaseItemRepository.java : '진짜 저장소'(구현체)입니다. @Profile("database")가 붙여주어, ' 데이터베이스'라는 저장소에 영구 관리되도록 작동합니다.
dto/ : Controller와 Service가 데이터를 주고받을 때 사용하는 전용 양식(DTO)입니다.
ItemRequestDto.java : 클라이언트로부터 받는 '주문서'(요청 DTO)입니다.
ItemResponseDto.java : 클라이언트에게 돌려줄 '영수증'(응답 DTO)입니다.
entity/ : 🍱 '서버 자원'를 정의하는 곳입니다.
Item.java : '상품'이란 무엇인가? (id, name, price...)를 정의하는 핵심 데이터 객체입니다. Repository가 데이터베이스와 통신할 때 이 객체를 사용합니다.
exception/ : ⚠️ '안전 관리자' 영역입니다. 앱 전체에서 발생하는 모든 에러를 관리합니다.
GlobalExceptionHandler.java : "상품을 찾을 수 없습니다(404)", "입력값이 비어있습니다(400)" 같은 예외가 발생하면, 이 '안전 관리자'가 모두 잡아채서 클라이언트에게 ErrorResponse.java 양식으로 응답합니다.
config/ : ⚙️ 프로젝트의 '설정' 파일이 모여있습니다.
DatabaseConfig.java : '데이터베이스'를 사용하기 위한 초기 연결 설정을 담당합니다.
WishlistApplication.java : 🚀 서버를 켰다 껐다 하는 '메인 전원' 스위치입니다. 이 파일을 실행(Run)하면 localhost:8080에서 서버가 시작됩니다.
src/main/resources/ : Java 코드가 아닌, 프로젝트의 '설정'이나 '자원' 파일이 모여있는 곳입니다.
application.properties : "지금 '임시 저장소'(memomory)를 쓸까, '진짜 저장소'(database)를 쓸까?"를 정하는 설정 스위치가 있는 파일입니다.
firebase-service-account.json : '데이터베이스'에 들어갈 수 있는 '보안 키(Key)'입니다.
Spring 서버는 Controller를 통해서 요청이 들어온다.
여기서 들어온 요청을 Service단에서 처리해준다.
Service단에서 처리한 비즈니스 로직에 대해서 조회(GET)하거나 저장하거나 수정(PUT)할 것이 있다면 Repository(일종의 냉장고. 부르고, 저장함)를 호출해서 DB와 직접 전송/통신해서 정보를 바꿔준다. 그 정보를 다시 Controller에 돌려준다.
이 과정에서 dto는 각 계층 간의 데이터가 오고 깔 때, 그 사이의 데이터를 저장하는 역할을 한다.
entity는 repository. 즉 데이터 저장소에 데이터를 어떤 식으로 저장해줄지에 대한 재료의 명세표라고 보면 된다.
exception는 일종의 예외 처리이다.(관리자 영역)
- 기본적으로 처리되는 것도 있고
config는 말 그대로 설정
새로운 기술 설정 파일을 추가하면 여기에 추가해야 함
WishlistApplication.Java는 Main 파일이라 생각하면 된다. 이걸 실행해야 나머지 것들이 실행되는 것이다.

폴더가 controller, service, repository, dto, entity 등으로 나뉘어 복잡해 보이지만, 데이터가 흐르는 길(순서)은 명확하다.
Postman으로 POST /items에 ‘새우깡’ JSON을 보내는 순간의 흐름을 '식당' 비유로 간략하게 따라가 봅시다.
이처럼 각자 역할이 명확히 분리되어 있어, 만약 셰프(Service)가 요리 레시피를 변경해 내용을 바꾸더라도, 주방 매니저(Controller)는 변경된 레시피에 대해서 몰라도 주문을 받고 음식을 서빙할 수 있습니다.
각자 역할이 명확히 분리되어 있기 때문에 한 역할이 변경사항이 생겨도 다른 역할은 건드릴 필요가 없어진다는 특징을 가집니다.
프론트엔드는 가짜 서버를 만들었다면
이번에는 진짜 서버를 만들어서 Postman으로 테스트를 할 것이다.
1. ../src/main/java/com.sparta.wishlist/controller/itemController.java

실행하면 빨간 줄이 4개 보임
-> 각 기능을 보고, 어떤 기능인지 파악해보자
1-1. 새 찜 상품 생성 => POST
: PostMapping("/items") = 이 앤드포인트(주소, /items)로 들어오는 Post 요청에 대해 매핑을 해준다. 이 다음에 있는 매서드들이 관리를 할거다.

1-2. 전체 찜 상품 조회 => GET

1-5. 찜 상품 단건 조회 => GET
1-3. 기존 찜 상품 수정 => PUT
1-4. 찜 상품 삭제 => DELETE
@PostMapping("/items")
public ResponseEntity saveItem(@Valid @RequestBody ItemRequestDto dto) throws ExecutionException, InterruptedException
{
ItemResponseDto responseDto = itemService.saveItem(dto);
return ResponseEntity.status(HttpStatus.CREATED).body(responseDto);
}
PostMapping 매서드에 /items 앤드포인트를 받으면 ResponseEntity의 ItemResponseDto 를 담은 형태로 리턴해줄거야. 그리고 이 아이템의 이름은 saveItem으로 할거야
ItemResponseDto : web-basic-backend-main\src\main\java\com\sparta\wishlist\dto의 ItemRequestDto.java를 열면

이다. 여기에는 price, category, description, link, image가 포함될거다.
이 dto는 그 아래에 있는 ItemResponseDto responseDto = itemService.saveItem(dto);이다.
savaItem의 body는 ItemRequestDto의 형식으로 dto를 하면 좋겠다.
saveItem(@Valid @RequestBody ItemRequestDto dto) 중...
-> ItemRequestDto
ItemResponseDto responseDto = itemService.saveItem(dto);은 이 매소드의 결과값을 ItemResponseDto에 저장한다는 의미이다.



백엔드에서 서버에
Postman에서 Mock server URL로 작성한 것을


WishlistApplication을 실행 시 localhost:8080으로 출력된 것으로 주소를 바꾼다
(mock server URL -> https://localhost:8080)
실제로 적용 됐는지 확인해보자
0. GET 실행(찜 목록 조회) -> 없음
여기에 추가해보자
1. POST 실행 -> 출력 : id=1
2. GET 실행(찜 목록 조회) id=1 -> 출력
3. DELETE 실행 -> 없음
4. GET 실행(찜 목록 조회) -> 없음
결과 : 실제 데이터에 영향을 준다.
추가로 더 해보자
5. POST 실행 -> 출력 : id=2
-> id가 2인 것은 1번이 삭제됐으니, 별다른 설정없이 실행하면 그 다음부터 숫자가 추가된다.
6. GET 실행('단건' 목록 조회) id=1 -> 출력 : 해당 상품 없음
-> 이전 가짜 응답이면 그냥 출력 됐음
7. GET 실행('단건' 목록 조회) id=2 -> 출력 : 5번에서 추가한 것이 뜸
PutMapping에서도 마찬가지임
8. PUT 실행(찜 상품 수정) id=1 -> 출력 : 해당 상품 없음
9. PUT 실행(찜 상품 수정) id=2 -> 출력 : 2번에 해당하는 내용이 수정됨(기계식 키보드, 12만원 -> 기계식 키보드 v2, 13.5만원)
web-basic-backend-main\src\main\resources\application.properties에서 바꾸면 된다.
3-2에서는 application.properties의 memory에서 돌아가고 있었음
!!! 메모리 위에서만 저장되기에 임시 저장이다.
인텔리제이를 껐다가 다시 키면 데이터가 없다.
이제 임시 저장이 아니라 데이터 저장이 필요하다.