프레임워크 = 코드 관리 도구의 모음


[검색창], [사이드바], [동영상 카드], [댓글] 같은 여러 개의 컴포넌트로 이루어져 있죠.[동영상 카드] 컴포넌트를 여기저기 재사용할 수 있고, 수정이 필요할 때 해당 부품만 고치면 되니 관리가 매우 쉬워집니다.


이전 수업에서 React가 UI를 '컴포넌트'로 분리했다면, Spring은 역할에 따라 코드를 분리합니다.
🤵 '주방 매니저' - Controller (컨트롤러)
손님(클라이언트)이 요청한 **POST /items, GET /items 과 같은 API 엔드포인트가 도착하는 진입점이자, 요리한 음식을 다시 손님에게 응답하기 위한 출발점을 하는 역할을 합니다.**서비스에게 시키고, 자기는 '주문 받기/서빙 하기'만 합니다.🧑🍳 '메인 셰프' - Service (서비스)
리포지토리에게 ‘데이터 저장/조회’를 시킵니다.🍱 ’음식’ - Entity (엔터티)
서비스가 처리하는 상품(서버 자원)을 의미합니다.🧊: '저장소' - Repository (리포지토리)
서비스가 "상품 줘"라고 하면, DB에서 상품을 꺼내줍니다.서비스가 "상품 저장해"라고 하면, DB에 상품을 저장합니다.이 구조를 `레이어드 아키텍처(계층형 아키텍처)` 이라고 하며 각 계층인 컨트롤러, 서비스, 레포지토리가 계층을 이루어 손님이 요청한 음식을 요리하고 다시 손님에게 전달할 때까지 과정을 수행합니다.
이 구조의 최대 장점은 부품 교체입니다. 저장소(Repository)를 메모리에서 데이터베이스로 바꿔도, 주방 매니저(Controller)와 메인 셰프(Service)는 코드를 한 줄도 바꿀 필요가 없습니다!
하나씩 살펴봅시다. (📌 외울 필요는 없어요! Spring 학습 때 충분히 알아가 보아요.)
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)'입니다.
파일이 controller, service, repository, dto, entity 등으로 나뉘어 복잡해 보이지만, 데이터가 흐르는 길(순서)은 명확합니다.
Postman으로 POST /items에 ‘새우깡’ JSON을 보내는 순간의 흐름을 '식당' 비유로 간략하게 따라가 봅시다.
1. ➡️ [Request] 주문 접수 from (홀)
POST /items로 ‘새우깡’ JSON을 담아 요청(주문)합니다.Controller (매니저): 주문을 받고, 주문서(ItemRequestDto)가 문제 없는지 검사합니다.Controller: "셰프님, 이 '주문서(DTO)'대로 처리해주세요"라고 Service에게 넘깁니다.2. ⚙️ [Processing] 요리 (주방)
Service (셰프): ‘주문서(DTO)’를 "주방에서 쓸 상품(Entity)"로 변환합니다.Service: "저장소에 이 '상품(Entity)'대로 저장해주세요"라고 Repository를 호출합니다.Repository (저장소): "저장소에 ‘상품(Entity)’을 저장하고, id가 발급된 최종본을 Service에게 돌려줍니다.3. ⬅️ [Response] 서빙 to (홀)
Service (셰프): 저장된 "상품(Entity)"을 "손님용 영수증(ItemResponseDto)"으로 다시 변환합니다.Controller (매니저): "영수증(DTO)"과 "주문 성공(201 Created)"했다는 상태로 손님(Client)에게 응답합니다.이처럼 각자 역할이 명확히 분리되어 있어, 만약 셰프(Service)가 요리 레시피를 변경해 내용을 바꾸더라도, 주방 매니저(Controller)는 변경된 레시피에 대해서 몰라도 주문을 받고 음식을 서빙할 수 있습니다.
각자 역할이 명확히 분리되어 있기 때문에 한 역할이 변경사항이 생겨도 다른 역할은 건드릴 필요가 없어진다는 특징을 가집니다.
데이터베이스(Database)는 식당의 초대형 냉장고이자 창고 와 같습니다.
단순히 데이터를 저장 하는 것을 넘어, 데이터를 관리하기 위한 전문 시스템(프로그램)입니다.
아래와 같은 특성을 가지고 있습니다.
영속성(Durability)구조화(Structure)동시성(Concurrency)무결성/일관성(Integrity/Consistency)질의(Query)이 '냉장 창고'를 관리하는 소프트웨어를 DBMS (Database Management System)라고 부르며, 이 DBMS는 크게 두 가지 방식으로 나뉩니다.












react 프로젝트를 만들었지만 서버나 데이터가 없어서 아무런 동작도 되지 않음
그래서 mock server(가짜 서버)를 통해 테스트 진행
백엔드를 완성했지만 DB연동이 안되어있고 메모리상에만 값이 저장 되어있었기 때문에 새로고침하면 다 날라가는 이슈 발생
Firebase를 활용한 DB를 통해 백엔드와 DB 연결해서 이슈 해결
마지막으로 프론트와 백엔드를 URL주소를 통해서 합친 다음
클라이언트가 Spring 서버에 직접 요청을 하는 것까지 구현