벌써 9월..?
오늘로 SQL 수업이 끝나고 Spring Boot로 넘어갔다.
CREATE TABLE TB_학생일반정보
(
SELECT S.STUDENT_NO AS `학번`,
S.STUDENT_NAME AS `학생이름`,
S.STUDENT_ADDRESS AS `주소`
FROM tb_student S
);
표준 문법은 CREATE TABLE 이름 AS SELECT ...지만, MariaDB에서는 AS를 생략하고 테이블명 뒤에 괄호로 SELECT를 감싸는 것만으로도 똑같이 동작한다. VIEW는 저장 공간이 없는 가상 테이블이지만, CTAS는 그 순간의 SELECT 결과를 그대로 복사해서 진짜 물리 테이블을 만든다는 점이 다르다.
DB 회사마다(Oracle, MariaDB, DB2 등) 연결하는 방식과 내부 구조가 제각각이다. 이 구조에 딱 맞춰 코드를 짜두면, 나중에 다른 DB로 옮길 때 그 코드를 통째로 다시 짜야 한다. 그래서 자바에서는 java.sql 패키지로 표준 인터페이스(JDBC)를 정의해두고, 각 DB 회사가 이 표준을 구현한 드라이버(.jar)를 제공하는 구조로 이 문제를 푼다. 개발자는 표준 API만 알면 어떤 DB든 같은 방식으로 다룰 수 있다.
드라이버 같은 외부 라이브러리는 mvnrepository.com에서 검색해서 받을 수 있는데, 순수 자바 프로젝트에서는 직접 받아서 lib/ 폴더에 넣어야 하고, Gradle을 쓰는 프로젝트에서는 build.gradle에 의존성만 적으면 자동으로 받아온다.
private static final String DRIVER = "org.mariadb.jdbc.Driver";
private static final String URL = "jdbc:mariadb://localhost:3306/lgcns";
public MariadbDao() {
Class.forName(DRIVER); // 1. 드라이버 로딩
}
public List<DepartmentResponseDTO> departments() {
String sql = "select * from department";
conn = DriverManager.getConnection(URL, USER, PASSWORD); // 2. 연결
pstmt = conn.prepareStatement(sql); // 3. SQL 준비
rset = pstmt.executeQuery(); // 4. 실행
while (rset.next()) { // 5. 결과 처리
list.add(DepartmentResponseDTO.builder()
.dept_id(rset.getString(1))
.dept_name(rset.getString(2))
.loc_id(rset.getString(3))
.build());
}
conn.close(); // 6. 연결 종료
return list;
}
- 드라이버관리 및 연결 작업 - Driver Loading
- 연결 작업 - Connection
- SQL 문장을 수행을 위한 작업 - Statement(query)
- 실행 작업 - execute
- 결과를 핸들링하는 작업 - ResultSet
- 연결 종료 = close
SELECT는 executeQuery()로 실행해서 ResultSet을 받고, INSERT/UPDATE/DELETE는 executeUpdate()로 실행해서 영향받은 행 수(int)를 받는다는 게 핵심 구분이다.
ResultSet은 처음 받았을 때 커서가 첫 행보다 앞에 있어서, rset.next()를 먼저 호출해야 값을 읽을 수 있는 상태가 된다. 그리고 rset.getString(1)의 1은 SQL 컬럼 순서(1부터 시작)지, 자바 배열 인덱스(0부터)가 아니다.
String sql = "update department set dept_name = ? where dept_id = ?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, request.getDept_name());
pstmt.setString(2, request.getDept_id());
return pstmt.executeUpdate();
SQL에 값을 바로 쓰지 않고 ?를 자리표시자로 넣어두고, setString(순서, 값)으로 채운다. 처음엔 setString(1, ...)의 1을 dept_name 컬럼 위치로 착각하기 쉬운데, 실제로는 SQL 문자열 안에서 몇 번째 ?인지를 가리킨다 — dept_name = ?이 첫 번째라서 1, dept_id = ?가 두 번째라서 2다. 이렇게 값을 분리하는 방식은 SQL 인젝션 방지에도 도움이 된다.
SELECT 하나, UPDATE 하나 처리할 때마다 이 6단계를 매번 통째로 다시 타이핑해야 한다는 게 직접 짜보니 꽤 번거로웠다. 이 과정을 대신 처리해주는 게 MyBatis(SQL은 직접 쓰되 매핑을 자동화)와 JPA/Hibernate(SQL 자체를 자동 생성, 객체 중심)다.
VS Code에서 Ctrl+Shift+P(명령어 팔레트)로 Spring Initializr를 실행해서 프로젝트를 만들었다. 이번에 고른 의존성은 DevTools, Configuration Processor, Lombok, Spring Web, Spring Data JPA, MyBatis, MariaDB Driver 7개다. 프로젝트에 필요한 라이브러리를 매번 수동으로 찾아 넣는 대신, build.gradle에 의존성 목록만 적으면 Gradle이 알아서 받아온다.
# application.yml (서버 기동 시 가장 먼저 읽힘)
spring:
profiles:
default: dev
application.yml이 가장 먼저 읽히는 설정 파일이고, 여기 지정한 프로필 이름(dev)에 맞춰 application-dev.yml이라는 이름의 파일을 자동으로 이어서 읽는다. 개발 환경과 배포 환경에서 서버 포트나 DB 접속 정보가 달라질 수 있어서, 이렇게 파일을 분리해두면 프로필 값 하나만 바꿔서 설정을 통째로 전환할 수 있다.
직접 해본 것:
Spring Boot 과정을 시작하기 위한 환경 세팅을 했다.
#LGCNS #LGCNS6기 #개발자 #LGCNSINSPIRECAMP