스파르타클럽 | 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를 이용하여 웹 상의 클라이언트의 요청을 응답해주는 통신을 하는 일종의 컴퓨터
- 웹 서버의 기본 동작 원리
- 브라우저를 통해 HTTP Request로 웹사이트를 웹서버에 요청함
- 웹 서버는 요청을 승인하고 HTTP Response를 통해 웹사이트 데이터를 브라우저에 전송함
- 브라우저는 서버에서 받아온 데이터를 이용해 웹사이트를 브라우저에 그려냄
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 문서와 같은 정적인 콘텐츠를 사용자에게 전달
- 역할
- 정적인 콘텐츠(HTML 등)를 브라우저로 전달
- 브라우저로부터 "로그인해서 마이페이지를 요청"과 같은 동적인 요청이 들어왔을 때 웹 서버 자체적으로 처리하기 어렵기 때문에 해당 요청을 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라는 개념이 존재함
- 동작 과정
- 브라우저는 서버에게 자신이 원하는 페이지(URL 등)을 요청(Request)함
- 서버는 브라우저가 원하는 페이지가 있는지 확인하고 해당 페이지에 대한 데이터를 실어 응답(Response)함
- 브라우저는 서버에게 전달 받은 데이터를 기반으로 브라우저에 그려줌
🧩 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를 사용하여 웹 페이지를 동적으로 생성하는 서버 측 프로그램 또는 그 사양
- 서블릿의 동작 과정
- 사용자가 Client(브라우저)를 통해 서버에 HTTP Request(API 요청)을 함
- 요청을 받은 Servlet 컨테니어는
HttpServletRequest,HttpServletResponse객체를 생성함 - 설정된 정보를 통해 어떠한 Servlet에 대한 요청인지 찾음
- 해당 Servlet에서 service 메서드를 호출한 뒤 브라우저의 요청 method에 따라
doGet또는doPost등의 메서드를 호출함 - 호출한 메서드들의 결과를 그대로 반환하거나 동적 페이지를 생성한 뒤
HttpServletResponse객체에 응답을 담아 Client(브라우저)에 반환함 - 응답이 완료되면 생성한
HttpServletRequest,HttpServletResponse객체를 소멸함
Front Controller
- Spring은 직접 무수한 Servlet을 구현할 필요 없이
DispatcherServlet을 사용해 Front Controller 패턴 방식으로 API 요청을 효율적으로 처리함 - 동작 과정
- Client(브라우저)에서 HTTP 요청이 들어오면
DispatcherServlet객체가 요청을 분석함 DispatcherServlet객체는 분석한 데이터를 토대로 Handler mapping을 통해 Controller를 찾아 요청을 전달함- 예:
GET /api/hello→HelloController의hello()함수
- 예:
- 해당 Controller는 요청에 대한 처리를 완료 후 처리에 대한 결과, 즉 데이터(Model)과 View 정보를
DispatcherServlet에 전달함 DispatcherServlet는 ViewResolver를 통해 View에 Model을 적용하여 View를 Client에게 응답으로 전달함
- Client(브라우저)에서 HTTP 요청이 들어오면
🧩 메모장 프로젝트 설계
- 프로젝트 생성


- 클라이언트 코드 (
/static/index.html) - 정적 이미지 (
/static/images/*.png) - 메모장 기능 설계
- 접속 하자마자 메모 전체 목록 조회하기
- GET API 사용해서 메모 목록 불러오기
- 메모 생성하기
- POST API 사용해서 메모 신규 생성하기
- 생성된 메모 반환
- 메모 변경하기
- PUT API 사용해서 메모 내용 변경하기
- 사용자가 클릭한 메모가 DB에 존재하는지 확인하기
- 해당 메모 내용 변경
- 메모 삭제하기
- DELETE API 사용해서 메모 삭제하기
- 사용자가 삭제하려는 메모가 DB에 존재하는지 확인하기
- 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 '합불'
);

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;

🧩 JDBC란?
JDBC의 등장 배경
- 애플리케이션 서버에서 DB에 접근하기 위해서는 여러 작업이 필요함
- DB에 연결하기 위해 커넥션을 연결
- SQL문을 작성한 후 커넥션을 통해 SQL을 요청
- 요청한 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와 연결할 수 있다.
'내일배움캠프' 카테고리의 다른 글
| [내일배움캠프] JPA와 Entity, 영속성 컨텍스트 (0) | 2026.04.06 |
|---|---|
| [내일배움캠프] IoC, DI, Bean (0) | 2026.04.06 |
| [내일배움캠프 사전캠프] 동시성 이슈 해결하기 (0) | 2026.04.03 |
| [내일배움캠프 사전캠프] 페이지네이션과 N+1 문제 (0) | 2026.04.02 |
| [내일배움캠프 사전캠프] JPA 연관관계 매핑 (0) | 2026.04.01 |