내일배움캠프

[내일배움캠프] Spring 입문 1주차

munsik22 2026. 4. 6. 15:59
 

스파르타클럽 | AI시대, 미래를 돌파하는 힘

누구나 잠재력을 깨워 나아가도록. IT 커리어의 모든 성장 과정을 스파르타클럽에서

academia.spartaclub.kr

🧩 Gradle이란 무엇일까

Gradle

  • 빌드: 소스 코드를 실행 가능한 결과물로 만드는 일련의 과정
  • Gradle: 빌드 자동화 시스템 → 간편하게 Java 소스 코드를 실행 가능한 jar 파일로 만들 수 있음

build.gradle

  • build.gradle: Gradle 기반의 빌드 스크립트
  • 소스 코드를 빌드하고 라이브러리들의 의존성을 쉽게 관리 가능
  • groovy 또는 kotlin으로 스크립트 작성
  • 개발을 하면서 필요한 라이브러리들을 dependencies 부분에 작성하면 Gradle이 해당 라이브러리들을 Maven Repository와 같은 외부 저장소에서 자동으로 다운로드 함
  • 다른 라이브러리들과의 의존성을 자동으로 관리해주기 때문에 라이브러리들간의 충돌 걱정 없이 개발에만 집중 가능

🧩 서버란 무엇일까

네트워크

  • 네트워크: 여러 대의 컴퓨터 또는 장비가 서로 연결되어서 정보를 주고 받을 수 있게 도와주는 기술
  • 컴퓨터, 라우터, 스위치, 허브 등의 장비들이 각각의 역할을 수행하여 정보를 주고 받음
  • 서로 정보를 주고 받기 위해서는 IP 주소, 서브넷 마스크, 게이트웨이 등의 정보를 설정하고 네트워크 프로토콜을 이용해 통신함
  • 우리는 사용자가 요청을 했을 때 해당 요청에 대한 응답을 수행하는 프로그램(=서버)를 개발하게 될 것임
  • 사용자의 요청에서 시작해 우리가 만든 서버에 도착하고 다시 사용자에게까지 되돌아가는 흐름을 잘 파악하고 있다면 서버 개발에 도움이 될 것임

Client와 Server

  • IP 주소: 사용자의 요청이 해당 서버에 정확하게 도달할 수 있게 제공되는 정보 (예: 192.168.0.123)
  • 거대한 네트워크망에서 각자의 컴퓨터를 식별하기 위한 위치 주소
  • 네트워크상에서의 데이터 송/수신은 이 주소를 기준으로 이루어짐
  • 네트워크에서 정보를 요청받고 전달하려면 주소에 해당하는 IP(192.168.0.123)와 받는 사람에 해당하는 포트번호(8080)가 필요함

웹 서버

  • 웹 서버: 인터넷을 통해 HTTP를 이용하여 웹 상의 클라이언트의 요청을 응답해주는 통신을 하는 일종의 컴퓨터
  • 웹 서버의 기본 동작 원리
    1. 브라우저를 통해 HTTP Request로 웹사이트를 웹서버에 요청함
    2. 웹 서버는 요청을 승인하고 HTTP Response를 통해 웹사이트 데이터를 브라우저에 전송함
    3. 브라우저는 서버에서 받아온 데이터를 이용해 웹사이트를 브라우저에 그려냄

API

  • API(Application Programming Interface): 다른 소프트웨어 시스템과 통신하기 위해 따라야 하는 규칙
  • 개발자는 다른 애플리케이션이 프로그래밍 방식으로 애플리케이션과 통신할 수 있도록 API를 표시하거나 생성함
  • 인터페이스: 서로 다른 두 개의 시스템, 장치 사이에서 정보나 신호를 주고받는 경우 접점이나 경계면을 의미함

RESTful API

  • REST(REpresentational State Transfer): API 작동 방식에 대한 조건을 부과하는 소프트웨어 아키텍처
  • REST API: REST 아키텍처 스타일을 따르는 API
  • RESTful 웹 서비스: REST 아키텍처를 구현하는 웹 서비스
  • API의 리소스 식별자를 중복 없이 고유하게 잘 만들고, 해당 API에 적절하게 HTTP 메서드를 사용했다면 RESTful하게 설계했다고 볼 수 있다.

Apache Tomcat

Web Server와 Web Application Server(WAS)

  • Web Server: 브라우저에서 URL을 입력하여 어떠한 페이지를 요청했을 때 HTTP의 요청을 받아들여 HTML 문서와 같은 정적인 콘텐츠를 사용자에게 전달
    • 역할
      1. 정적인 콘텐츠(HTML 등)를 브라우저로 전달
      2. 브라우저로부터 "로그인해서 마이페이지를 요청"과 같은 동적인 요청이 들어왔을 때 웹 서버 자체적으로 처리하기 어렵기 때문에 해당 요청을 WAS에 전달
    • 종류: Apache, Nginx 등
  • WAS: 웹 서버와 같이 HTTP 기반으로 동작하며, 웹 서버에서 할 수 있는 기능 대부분을 WAS에서도 처리 가능
    • 로그인, 회원가입을 처리하거나 게시물을 조회, 정렬하는 등 가양한 로직들을 수행하는 프로그램을 동작시킬 수 있음
    • 종류: Tomcat, JBoss 등

Apache Tomcat

  • Tomcat: 동적인 처리를 할 수있는 웹 서버를 만들기 위한 웹 컨테이너
  • Apache Tomcat: Apache와 Tomcat이 합쳐진 형태로, 정적+동적 데이터를 효율적으로 처리 가능

Spring과 Spring Boot

  • Spring 프레임워크: AOP, IoC/DI 등과 같은 핵심 기능을 가지고 있는 프레임워크
    • 하지만 이러한 핵심 기능들을 사용하기 위해서는 복잡한 XML 설정이 필요했음
  • SpringBoot: 기존의 XML 설정 대신 Java의 어노테이션 기반의 설정을 적극적으로 활용해 Spring을 아주 간편하게 사용할 수 있음
    • 외부 라이브러리나 하위 프레임워크들의 의존성 관리가 매우 쉬워짐
    • 기본적으로 Apache Tomcat을 내장하고 있어 따로 다운로드하고 설정할 필요가 없음

🧩 HTTP란 무엇일까?

HTTP

  • 데이터를 주고 받는 양식을 정의한 통신 규약 중 하나
  • 매우 범용적인 양식을 가지고 있어 전 세계에서 제일 널리 쓰이는 통신 규약
  • 통신 규약: 컴퓨터끼리 데이터를 주고 받을 때 정해둔 약속

어떻게 HTTP로 데이터를 주고 받을까?

  • HTTP에는 언제나 Request, Response라는 개념이 존재함
  • 동작 과정
    1. 브라우저는 서버에게 자신이 원하는 페이지(URL 등)을 요청(Request)함
    2. 서버는 브라우저가 원하는 페이지가 있는지 확인하고 해당 페이지에 대한 데이터를 실어 응답(Response)함
    3. 브라우저는 서버에게 전달 받은 데이터를 기반으로 브라우저에 그려줌

🧩 Spring MVC란?

MVC 디자인 패턴

  • MVC: Model-View-Controller의 약자로, 소프트웨어 디자인 패턴 중 하나
  • Model
    • 데이터와 비스니스 로직을 담당
    • 데이터베이스와 연동하여 데이터를 저장하고 불러오는 등의 작업을 수행함
  • View
    • 사용자 인터페이스를 담당
    • 사용자가 보는 화면과 버튼, 폼 등을 디자인하고 구현함
  • Controller
    • Model과 View 사이의 상호작용을 조정하고 제어함
    • 사용자의 입력을 받아 Model에 전달하고, Model의 결과를 바탕으로 View를 업데이트함
  • MVC 패턴은 소프트웨어를 구성하는 요소들을 분리함으로써 코드의 재사용성과 유지보수성을 높이고 개발자들간의 협업을 용이하게 함

Spring MVC

  • Spring Web MVC: Servlet API를 기반으로 구축된 독창적인 웹 프레임워크
  • DispatcherServlet이 중앙에서 HTTP 요청을 처리해주는데 이는 Front Controller 패턴으로 설계되어 있음
  • Spring에서 MVC 디자인 패턴을 적용해 HTTP 요청을 효율적으로 처리함
  • Servlet(서블릿): Java를 사용하여 웹 페이지를 동적으로 생성하는 서버 측 프로그램 또는 그 사양
  • 서블릿의 동작 과정
    1. 사용자가 Client(브라우저)를 통해 서버에 HTTP Request(API 요청)을 함
    2. 요청을 받은 Servlet 컨테니어는 HttpServletRequest, HttpServletResponse 객체를 생성함
    3. 설정된 정보를 통해 어떠한 Servlet에 대한 요청인지 찾음
    4. 해당 Servlet에서 service 메서드를 호출한 뒤 브라우저의 요청 method에 따라 doGet 또는 doPost 등의 메서드를 호출함
    5. 호출한 메서드들의 결과를 그대로 반환하거나 동적 페이지를 생성한 뒤 HttpServletResponse 객체에 응답을 담아 Client(브라우저)에 반환함
    6. 응답이 완료되면 생성한 HttpServletRequest, HttpServletResponse 객체를 소멸함

Front Controller

  • Spring은 직접 무수한 Servlet을 구현할 필요 없이 DispatcherServlet을 사용해 Front Controller 패턴 방식으로 API 요청을 효율적으로 처리함
  • 동작 과정
    1. Client(브라우저)에서 HTTP 요청이 들어오면 DispatcherServlet 객체가 요청을 분석함
    2. DispatcherServlet 객체는 분석한 데이터를 토대로 Handler mapping을 통해 Controller를 찾아 요청을 전달함
      • 예: GET /api/helloHelloControllerhello() 함수
    3. 해당 Controller는 요청에 대한 처리를 완료 후 처리에 대한 결과, 즉 데이터(Model)과 View 정보를 DispatcherServlet에 전달함
    4. DispatcherServlet는 ViewResolver를 통해 View에 Model을 적용하여 View를 Client에게 응답으로 전달함

🧩 메모장 프로젝트 설계

  • 프로젝트 생성

  • 클라이언트 코드 (/static/index.html)
  • 정적 이미지 (/static/images/*.png)
  • 메모장 기능 설계
    1. 접속 하자마자 메모 전체 목록 조회하기
      1. GET API 사용해서 메모 목록 불러오기
    2. 메모 생성하기
      1. POST API 사용해서 메모 신규 생성하기
      2. 생성된 메모 반환
    3. 메모 변경하기
      1. PUT API 사용해서 메모 내용 변경하기
      2. 사용자가 클릭한 메모가 DB에 존재하는지 확인하기
      3. 해당 메모 내용 변경
    4. 메모 삭제하기
      1. DELETE API 사용해서 메모 삭제하기
      2. 사용자가 삭제하려는 메모가 DB에 존재하는지 확인하기
      3. DB에서 해당 메모 삭제
  • API 테이블
기능 Method URL Return
메모 생성하기 POST /api/memos MemoResponseDto
메모 조회하기 GET /api/memos List<MemoResponseDto>
메모 변경하기 PUT /api/memos/{id} Long
메모 삭제하기 DELETE /api/memos/{id} Long

🧩 CRUD 구현하기

DTO

  • DTO(Data Transfer Object): 데이터 전송 및 이동을 위해 생성되는 객체
  • Client에서 보내오는 데이터를 객체로 처리할 때 사용됨
  • Server의 계층간의 이동에도 사용됨
  • DB와의 소통을 담당하는 Java 클래스를 그대로 Client에 반환하는 것이 아니라 DTO로 한번 변환한 후 반환할 때도 사용됨
  • 요청 DTO는 RequestDto, 응답 DTO는 ResponseDto라는 이름을 붙임 (※ 달라질 수 있음)

Create, Read 구현

  • 메모 데이터를 저장하는 Memo 클래스 (/entity/Memo.java)
@Getter @Setter
@NoArgsConstructor
public class Memo {
    private Long id;
    private String username;
    private String contents;

    public Memo(MemoRequestDto requestDto) {
        this.username = requestDto.getUsername();
        this.contents = requestDto.getContents();
    }
}
  • 메모 컨트롤러 (/controller/MemoController.java)
@RestController
@RequestMapping("/api")
public class MemoController {

    private final Map<Long, Memo> memoList = new HashMap<>();

    @PostMapping("/memos")
    public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto) {
        Memo memo = new Memo(requestDto);

        Long maxId = !memoList.isEmpty() ? Collections.max(memoList.keySet()) + 1 : 1;
        memo.setId(maxId);

        memoList.put(memo.getId(), memo);

        return new MemoResponseDto(memo);
    }

    @GetMapping("/memos")
    public List<MemoResponseDto> getMemos() {
        return memoList.values().stream()
                .map(MemoResponseDto::new).toList();
    }
}
  • 메모 응답 DTO (/dto/MemoResponseDto.java)
@Getter
public class MemoResponseDto {
    private final Long id;
    private final String username;
    private final String contents;

    public MemoResponseDto(Memo memo) {
        this.id = memo.getId();
        this.username = memo.getUsername();
        this.contents = memo.getContents();
    }
}

Update, Delete 구현

  • 메모 요청 DTO (/dto/MemoRequestDto.java)
@Getter
public class MemoRequestDto {
    private String username;
    private String contents;
}
  • MemoController 수정
@PutMapping("/memos/{id}")
public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
    if(memoList.containsKey(id)) {
        Memo memo = memoList.get(id);

        memo.update(requestDto);
        return memo.getId();
    } else {
        throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
    }
}

@DeleteMapping("/memos/{id}")
public Long deleteMemo(@PathVariable Long id) {
    if(memoList.containsKey(id)) {
        memoList.remove(id);
        return id;
    } else {
        throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다.");
    }
}
  • Memo 수정
    public void update(MemoRequestDto requestDto) {
        this.username = requestDto.getUsername();
        this.contents = requestDto.getContents();
    }

🧩 RDBMS와 SQL

RDBMS

  • 데이터베이스: 데이터의 집합
  • DBMS: 데이터베이스 관리/운영 시스템
  • RDBMS: 테이블(행+열)이라는 최소 단위로 구성된 관계형 데이터베이스 (예: MySQL)

SQL

  • SQL(Structured Query Language): RDBMS에서 데이터베이스를 관리하기 위해 사용되는 언어
  • DDL(Data Definition Language): 테이블이나 관계의 구조를 생성하는 데 사용
    • CREATE: 새로운 데이터베이스 및 테이블을 생성
    • ALTER: 데이터베이스 및 테이블을 수정
    • DROP: 데이터베이스 및 테이블을 전체 삭제
    • TRUNCATE: 데이터베이스 및 테이블을 초기 상태로 초기화
  • DCL(Data Control Language): 데이터의 사용 권한을 관리하는 데 사용
    • GRANT: 사용자 또는 ROLE에 대한 권한 부여
    • REVOKE: 사용자 또는 ROLE에 부여한 권한 회수
  • DML(Data Manipulation Language): 테이블에 데이터를 검색/삽입/수정/삭제하는 데 사용
    • INSERT: 테이블에 새로운 행 추가
    • SELECT: 테이블의 행 선택
    • UPDATE: 테이블의 행 내용 수정
    • DELETE: 테이블의 행 삭제

CREATE 제약조건

  • AUTO_INCREMENT: 컬럼의 값이 중복되지 않게 1씩 자동으로 증가하게 해줘 고유번호를 생성
  • NOT NULL: 해당 필드는 NULL 값을 저장할 수 없음
  • UNIQUE: 해당 필드는 서로 다른 값을 가져야 함
  • PRIMARY KEY: 해당 필드가 NOT NULL과 UNIQUE 제약 조건의 특징을 모두 가짐
  • FOREIGN KEY: 하나의 테이블을 다른 테이블에 의존하게 만들며 데이터의 무결성을 보장함
  • CASCADE: FOREIGN KEY로 연관된 데이터를 삭제/변경 가능

🧩 SQL 실습

CREATE

-- MAJOR 테이블
CREATE TABLE IF NOT EXISTS MAJOR
(	
	major_code varchar(100) primary key comment '주특기코드', 
	major_name varchar(100) not null comment '주특기명',
	tutor_name varchar(100) not null comment '튜터'
);

-- STUDENT 테이블
CREATE TABLE IF NOT EXISTS STUDENT
(
	student_code varchar(100) primary key comment '수강생코드', 
	name varchar(100) not null comment '이름',
	birth varchar(8) null comment '생년월일',
	gender varchar(1) not null comment '성별',
	phone varchar(11) null comment '전화번호',
	major_code varchar(100) not null comment '주특기코드',
	foreign key(major_code) references major(major_code)
);

-- EXAM 테이블
CREATE TABLE IF NOT EXISTS EXAM
(
	student_code varchar(100) not null comment '수강생코드', 
	exam_seq int not null comment '시험주차', 
	score decimal(10,2) not null comment '시험점수',
	result varchar(1) not null comment '합불'
);

Show Diagrams

ALTER

ALTER TABLE EXAM ADD PRIMARY KEY(student_code, exam_seq);
ALTER TABLE EXAM ADD CONSTRAINT exam_fk_student_code FOREIGN KEY(student_code) REFERENCES STUDENT(student_code);

INSERT

INSERT INTO MAJOR VALUES('m1', '스프링', '남병관');
INSERT INTO MAJOR VALUES('m2', '노드', '강승현');
INSERT INTO MAJOR VALUES('m3', '플라스크', '이범규');
INSERT INTO MAJOR VALUES('m4', '루비온레일즈', '차은서');
INSERT INTO MAJOR VALUES('m5', '라라벨', '구름');
INSERT INTO MAJOR VALUES('m6', '리엑트', '임민영');
INSERT INTO MAJOR VALUES('m7', '뷰', '김서영');
INSERT INTO MAJOR VALUES('m8', '엥귤러', '한현아');

UPDATE

INSERT INTO STUDENT VALUES('s0', '수강생', '20220331', 'M', '01000000005', 'm1');

UPDATE STUDENT SET major_code= 'm2' where student_code= 's0';

SQL 검사기 쪽에서 초기화 문제가 발생했는데, 캐시 무효화 및 다시 실행을 통해 해결할 수 있었다.

DELETE

DELETE FROM STUDENT WHERE student_code = 's0';

SELECT

SELECT * FROM STUDENT;
SELECT * FROM STUDENT WHERE STUDENT_CODE = 's1';
SELECT name, major_code FROM STUDENT WHERE student_code = 's1';

JOIN

  • JOIN: 나누어진 테이블을 하나로 합치기 위해 데이터베이스가 제공하는 기능
  • ON 이라는 키워드를 통해 기준이 되는 컬럼을 선택하여 2개의 테이블을 합침
  • JOIN을 할 때에는 적어도 하나의 컬럼을 서로 공유하고 있어야 하기 때문에, 테이블에 외래키가 설정되어 있다면 해당 컬럼을 통해 JOIN을 하면 조건 충족 가능
  • 다만 JOIN을 하기 위해 외래 키를 설정하는 것이 항상 좋은 선택이 아닐 수도 있음
    • 외래 키를 설정하면 데이터 무결성을 확인하는 추가 연산이 발생함
    • 무결성을 지켜야하기 때문에 상황에 따라 개발하는데 불편함
  • 항상 테이블에 모든 제약조건을 걸어야 하는 것은 절대 아니고, 프로젝트에 따라 가장 효율적인 제약조건을 적용해야 함
SELECT s.name, s.major_code, m.major_name FROM STUDENT s JOIN MAJOR m ON s.major_code = m.major_code;
SELECT s.name, s.major_code, m.major_name FROM STUDENT s, MAJOR m WHERE s.major_code = m.major_code;

두 SQL문의 결과는 같다

🧩 JDBC란?

JDBC의 등장 배경

  • 애플리케이션 서버에서 DB에 접근하기 위해서는 여러 작업이 필요함
    1. DB에 연결하기 위해 커넥션을 연결
    2. SQL문을 작성한 후 커넥션을 통해 SQL을 요청
    3. 요청한 SQL에 대한 결과를 응답 받음
  • 기존에 사용하던 MySQL 서버를 PostgreSQL 서버로 변경한다면 커넥션 연결, SQL 전달, 결과 응답 방법이 모두 다를 수 있기 때문에 DB 연결 로직들을 전부 수정해야 함
    • 이러한 문제를 해결하기 위해 JDBC 표준 인터페이스가 등장하였음
  • JDBC(Java DataBase Connectivity): DB에 접근할 수 있도록 Java에서 제공하는 API
    • JDBC에 연결하는 DB의 JDBC 드라이버를 제공하면 DB 연결 로직을 변경할 필요없이 DB 변경 가능
    • 따라서 드라이버만 교체하면 쉽게 DB 변경이 가능함
  • JdbcTemplate: 커넥션 연결, statement 준비 및 실행, 커넥션 종료 등 반복적이고 중복되는 작업들을 대신 처리해주는 코드

JdbcTemplate 사용방법

  • application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/memo
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  • build.gradle 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
runtimeOnly 'com.mysql:mysql-connector-j'
  • memo 데이터베이스 및 테이블 생성
create database memo;

-- Intellij 연결 후
create table memo
(
    id       bigint       not null auto_increment,
    contents varchar(500) not null,
    username varchar(255) not null,
    primary key (id)
);
  • MemoController 수정
    private final JdbcTemplate jdbcTemplate;

    public MemoController(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @PostMapping("/memos")
    public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto) {
        Memo memo = new Memo(requestDto);

        KeyHolder keyHolder = new GeneratedKeyHolder();

        String sql = "INSERT INTO memo (username, contents) VALUES (?, ?)";
        jdbcTemplate.update( con -> {
                    PreparedStatement preparedStatement = con.prepareStatement(sql,
                            Statement.RETURN_GENERATED_KEYS);

                    preparedStatement.setString(1, memo.getUsername());
                    preparedStatement.setString(2, memo.getContents());
                    return preparedStatement;
                },
                keyHolder);

        Long id = keyHolder.getKey().longValue();
        memo.setId(id);

        MemoResponseDto memoResponseDto = new MemoResponseDto(memo);

        return memoResponseDto;
    }
    
    /* ... */
  • ORM을 사용하면 JdbcTemplate보다도 더 간단하게 DB와 연결할 수 있다.