학습 키워드
- Layered Architecture (Controller, Service, Repository)
- DTO (Data Transfer Object)
- JPA 영속성 컨텍스트 (Persistence Context)
- JWT (JSON Web Token) & Signature
- 트랜잭션 (Transaction) @Transactional
학습 한 내용
계층 구조(Layered Architecture): 유지보수와 책임의 분리
단순히 코드를 나누는 게 아니라 각 계층이 서로의 내부 구현을 몰라도 되게끔 하는 '관심사의 분리'다.
- Controller: 클라이언트의 요청(Request)을 받고 응답(Response)을 처리하는 엔드포인트. 유저가 보낸 값이 규격에 맞나 검증(Validation)하고 서비스에 전달한다.
- Service: 비즈니스 로직의 핵심 단위. "아이템 사용 시 데이터 정합성 체크" 같은 실제 기획 로직이 여기서 실행된다. Go에서 직접 짰던 비즈니스 로직들이 모이는 곳이며, 트랜잭션의 단위가 된다.
- Repository: 데이터 접근 계층(DAO). JPA를 사용하여 DB와 객체를 매핑하고 실제로 데이터를 읽고 쓰는 역할을 한다.
DTO(Data Transfer Object): 데이터 노출 최소화와 캡슐화
DB의 테이블 구조를 그대로 담은 엔티티(Entity)를 외부에 노출하면 보안이 취약해지고 API 스펙이 DB 구조에 종속된다.
- DTO: 계층 간 데이터 교환을 위한 객체. 딱 필요한 필드만 정의해서 사용하므로 데이터 오염을 막고, API 응답의 유연성을 확보한다.
JPA 영속성 컨텍스트: 애플리케이션과 DB 사이의 캐시 계층
애플리케이션이 DB에 데이터를 꽂기 전, 엔티티를 관리하는 일종의 메모리 보관소다.
- 1차 캐시: 동일 트랜잭션 내에서 같은 데이터를 조회하면 DB를 거치지 않고 메모리에서 바로 반환하여 성능을 최적화한다.
- 더티 체킹 (Dirty Checking): 트랜잭션 종료 시 엔티티의 상태 변화를 감지해 자동으로 Update 쿼리를 생성한다. 덕분에 개발자가 명시적으로 수정 쿼리를 짤 필요가 없다.
JWT(JSON Web Token): Stateless~ 한 인증 방식의 핵심
- Header & Payload: 토큰의 타입과 사용자 정보(Claim)가 담긴 부분. Base64로 인코딩되어 누구나 볼 수 있으므로 보안상 민감한 정보(비밀번호 등)는 담지 않는다.
- Signature: 서버의 Secret Key로 생성한 검증용 해시값. 클라이언트가 페이로드를 수정해도 이 시그니처가 일치하지 않으면 서버에서 즉시 거부한다. 덕분에 서버는 별도의 세션 저장소 없이도 유저를 인증할 수 있다.
트랜잭션(Transaction): 데이터 정합성 보장을 위한 원자성(Atomicity)
여러 작업이 하나의 논리적 단위로 묶여서 "전부 성공하든지, 하나라도 실패하면 전체 취소(Rollback)" 되는 것을 보장한다.
- 돈 차감부터 아이템 지급까지 한 세트로 묶어 데이터가 꼬이는 것을 방지한다. 스프링에선
@Transactional 어노테이션만으로 AOP(관점 지향 프로그래밍)를 통해 이 복잡한 제어 로직을 대신 처리해 준다.