Spring

[Spring 입문] 스프링 전체 흐름 정리

chungmani 2026. 6. 29. 22:38

 

스프링은 한마디로

사용자의 요청을 받아서 DB와 연결해 데이터를 처리하고 다시 응답하는 구조

 

이 전체 흐름은 아래 3-Layer 구조로 움직인다.


1. 전체 구조 한눈에 보기

 

2. Controller (입구 / 안내 데스크)

Controller는 사용자의 HTTP 요청을 받는 입구

@RestController
@RequiredArgsConstructor
public class MemoController {

    private final MemoService memoService;

    @PostMapping("/memos")
    public ResponseEntity<CreateMemoResponse> createMemo(@RequestBody CreateMemoRequest request) {
        return ResponseEntity.status(HttpStatus.CREATED).body(memoService.save(request));
    }

    @GetMapping("/memos/{memoId}")
    public ResponseEntity<GetMemoResponse> getOneMemo(@PathVariable Long memoId) {
        return ResponseEntity.status(HttpStatus.OK).body(memoService.findOne(memoId));
    }

    @GetMapping("/memos")
    public ResponseEntity<List<GetMemoResponse>> getAllMemos() {
        return ResponseEntity.status(HttpStatus.OK).body(memoService.findAll());
    }

    @PatchMapping("/memos/{memoId}")
    public ResponseEntity<UpdateMemoResponse> updateMemoContents(@PathVariable Long memoId, @RequestBody UpdateMemoRequest request) {
        return ResponseEntity.status(HttpStatus.OK).body(memoService.update(memoId, request));
    }

    @DeleteMapping("/memos/{memoId}")
    public ResponseEntity<Void> deleteMemo(@PathVariable Long memoId) {
        memoService.delete(memoId);
        return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
    }
}
 

역할

  • 요청 받기 (GET, POST, PUT, DELETE)
  • DTO로 데이터 전달
  • 응답 반환

핵심: 요청/응답만 담당, 로직은 없음

 


 3. Service (업무 처리 담당)

Service는 실제 일을 하는 곳

@Service
@RequiredArgsConstructor
public class MemoService {

    private final MemoRepository memoRepository;

    @Transactional
    public CreateMemoResponse save(CreateMemoRequest request) {
        Memo memo = new Memo(request.getContents());
        Memo savedMemo = memoRepository.save(memo);
        return new CreateMemoResponse(savedMemo.getId(), savedMemo.getContents());
    }

    @Transactional(readOnly = true)
    public GetMemoResponse findOne(Long memoId) {
        Memo memo = memoRepository.findById(memoId).orElseThrow(
                () -> new IllegalStateException("없는 메모입니다.")
        );

        return new GetMemoResponse(memo.getId(), memo.getContents());
    }

    @Transactional(readOnly = true)
    public List<GetMemoResponse> findAll() {
        List<Memo> memos = memoRepository.findAll();
        List<GetMemoResponse> dtos = new ArrayList<>();
        for (Memo memo : memos) {
            GetMemoResponse dto = new GetMemoResponse(memo.getId(), memo.getContents());
            dtos.add(dto);
        }
        return dtos;
    }

    @Transactional
    public UpdateMemoResponse update(Long memoId, UpdateMemoRequest request) {
        Memo memo = memoRepository.findById(memoId).orElseThrow(
                () -> new IllegalStateException("없는 메모입니다.")
        );
        memo.updateContents(request.getContents());
        return new UpdateMemoResponse(memo.getId(), memo.getContents());
    }

    @Transactional
    public void delete(Long memoId) {
        boolean existence = memoRepository.existsById(memoId);
        if (!existence) {
            throw new IllegalArgumentException("없는 메모입니다.");
        }

        // 존재하면
        memoRepository.deleteById(memoId);
    }
}
 

역할

  • 비즈니스 로직 처리
  • 데이터 가공
  • 여러 Repository 조합 가능

핵심: 실제 서비스 로직이 있는 곳

 


4. Repository (DB 창고)

Repository는 DB랑 직접 연결되는 곳

public interface MemoRepository extends JpaRepository <Memo, Long> {
}
 

역할

  • DB 저장
  • DB 조회
  • DB 삭제

핵심: DB랑 직접 대화하는 창고


5. Entity (DB 테이블과 연결된 객체)

Entity는 DB와 1:1로 연결되는 객체

@Getter
@Entity
@Table(name = "memos")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Memo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "contents", length = 255)
    private String contents;

    public Memo(String contents) {
        this.contents = contents;
    }

    public void updateContents(String contents) {
        this.contents = contents;
    }
}
 

역할

  • DB 테이블 구조 표현
  • 실제 저장되는 데이터

핵심: DB의 한 행(Row)을 자바 객체로 표현한 것


6. DTO (데이터 전달 상자)

DTO는 사용자와 데이터를 주고받기 위한 객체다.

@Getter
public class CreateMemoResponse {

    private final Long id;
    private final String contents;

    public CreateMemoResponse(Long id, String contents) {
        this.id = id;
        this.contents = contents;
    }
}
 

역할

  • 필요한 데이터만 전달
  • Entity 직접 노출 방지

핵심: 데이터 전달용 전용 박스