데이터 추가, 삭제, 갱신
데이터 추가, 삭제, 갱신행 추가하기 - INSERT 명령어 SELECT * FROM sample41; 결과 Empty set (0.00 sec) 현재는 비어있는 테이블이다. sample41 열 구성 확인하기 명령어
데이터 추가, 삭제, 갱신행 추가하기 - INSERT 명령어 SELECT * FROM sample41; 결과 Empty set (0.00 sec) 현재는 비어있는 테이블이다. sample41 열 구성 확인하기 명령어
정렬과 연산정렬하기 - ORDER BY 기존 테이블 mysql> SELECT * FROM sample31;+------+------+---------------------------+| name | age | address |+------+------+---------------------------+| A씨 | 36 | 대구광역시 중구 || B씨 | 18 | 부산광역시 연제구 || C씨 | 25 | 서울특별시 중구 |+------+------+---------------------------+3 rows in set (0.00 sec) age를 기준으로 테이블 정렬하기 명령어 SELECT* FROM sample31 ORDER BY age; 나이를 기준으로 테이블sample31을 정렬하였다. 결과
테이블에서 데이터 검색use sample SELECT 명령어SELECT * FROM sample21; SELECT는 DML에 속하는 멸령으로 SQL에서 자주 사용된다.SELECT명령으로 데이터 베이스의 데이터를 읽어올 수 있다.*는 모든 열을 의미하는 메타문자이다.FROM은 처리 대상 테이블을 지정하는 키워드 결과+------+-----------+------------+---------------------------+| no | name | birthday | address |+------+-----------+------------+---------------------------+| 1 | 박준용 | 1976-10-18 | 대구광역시 수성구 || 2 | 김재진 | NULL | 대구광역시 동구 || 3 | 홍길동 | NULL | 서울특별시 마포구 |+------+-----------+------------+---------------------------+3 rows in set (0.00 sec) NULL은 데이터 값으로 아무것도 저장되어 있지 않은 상태를 의미한다. DESC 명령어
B Tree자식 노드가 최대 두개인 이진 트리와는 다르게 B-Tree 는 M 개의 자식 노드를 가질 수 있다. Node 의 Key 개수가 N 개면 자식 Node 의 개수는 N+1 개다. Node 내 Key 값은 항상 정렬된 상태 여야 한다. Root Node 는 항상 2개 이상의 자식 Node 를 갖는다. 모든 Leaf Node 들은 항상 같은 Level 에 있어야 한다. B treeB-트리는 데이터를 저장하고 검색하기 위한 트리 자료 구조로, 데이터베이스의 인덱스와 파일 시스템 등에서 널리 사용됩니다. B-트리는 각 노드에 여러 개의 자식을 가질 수 있으며, 이를 통해 대량의 데이터를 효율적으로 저장할 수 있습니다. B-트리는 일반적으로 다음과 같은 특징을 가집니다. 균형 트리: B-트리는 노드의 균형을 유지하여 검색, 삽입, 삭제 연산에 대한 시간 복잡도를 보장합니다. 각 노드는 여러 개의 자식을 가지며, 자식 노드의 개수가 비슷한 것이 특징입니다. 다단계 인덱스: B-트리는 매우 높은 성능으로 인덱스 검색을 수행하므로 대부분의 데이터베이스에서 인덱스 구조로 사용됩니다. B-트리는 다단계 인덱스를 구성하여 빠른 검색 성능을 제공합니다. 블록 단위 입출력: B-트리는 블록 단위로 입출력을 수행하여 입출력 연산을 최소화합니다. 이는 데이터베이스나 파일 시스템에서 대량의 데이터를 다룰 때 매우 효과적입니다. 삽입, 삭제 연산: B-트리는 노드의 균형을 유지하여 삽입, 삭제 연산의 시간 복잡도를 로그 시간으로 보장합니다. 이는 대규모 데이터를 다룰 때 매우 효과적입니다. B-트리는 데이터베이스, 파일 시스템, 검색 엔진 등에서 널리 사용되는 자료 구조입니다. 또한 B+트리와 같은 변형 형태도 있으며, 이러한 변형 형태는 대규모 데이터를 다룰 때 더욱 효과적입니다. B tree 검색 알고리즘 루트 노드에서 시작합니다. 현재 노드에서 키 값을 검색합니다. 검색한 키 값이 현재 노드에 있으면 해당 포인터를 따라 해당 자식 노드로 이동합니다. 검색한 키 값이 현재 노드에 없으면, 키 값이 들어갈 위치를 찾고 해당 위치의 자식 노드로 이동합니다. 자식 노드로 이동한 후, 2단계로 돌아가서 검색을 계속합니다.
데이터 베이스 - Index Index 란 오라클에서는 인덱스의 모든 컬럼이 NULL 인 경우 인덱스를 만들지 않는다. 데이터 베이스 - Index Scan Table Full Scan : 테이블 전체 탐색 Index Unique Scan : 인덱스 수직 탐색 Index Full Sacn : 인덱스 전체 탐색 Index Range Scan : 인덱스 범위 탐색 Index Skip Scan : 인덱스 스킵 탐색 Table Full Scan - 테이블 전체 스캔 인덱스 루트에서 시작해 수평적으로 리프 블럭까지 스캔하는 방식 Index Unique Scan 단 한건의 데이터를 찾을 때 사용하는 Scan 방식
DDL DML DCLDDL 데이터 베이스 스키마를 정의하기 하거나 조작하기 위한 명령어 명령어 설명 CREATE 데이터 베이스, 테이블을 생성하기 위한 명령어 ALTER 테이블을 수정하기 위한 명령어 DROP 데이터베이스, 테이블을 삭제하기 위한 명령어 RENAME TRUNCATE 데이터베이스를 초기화 시키기 위한 명령어 DML 데이터 베이스에 저장된 데이터를 조회, 수정, 삽입, 삭제하기 위한 언어 명령어 설명 SELECT 데이터를 조회 하기 위한 명령어 INSERT 데이터를 삽입하기 위한 명령어 UPDATE 데이터를 수정하기 위한 명령어 DELETE 데이터를 삭제하기 위한 명령어 DCL 데이터 베이스에 접근하거나 객체에 권한을 주는 역할을 하는 언어
목차 트랜잭션과 ACID 트랜잭션 격리수준 (Isolation Level) 트랜잭션과 ACID 원자성(Atomicity) 일관성(Consistency) 격리성(Isolation) 지속성(Durability) 원자성 보장 트랜잭션 원자성은 All or Nothing 으로 부분적으로 실행되거나 중단되지 않음을 보장한다. 즉, 분해가 불가능한 최소 단위인 하나의 원자처럼 동작한다는 의미 트랜잭션에 의한 변경 내용을 유지하면서, 이전에 Commit 된 시점의 데이터를 임시영역에 따로 저장함으로써 원자성을 보장한다. 현재 수행하고 있는 트랜잭션에 오류가 나면 현재 내역을 날려버리고 임시 영역에 저장했던 상태로 Rollback 을 한다. 이전 데이터들이 저장된 영역을 롤백 세그먼트라고 부른다. 현재 수행중인 트랜잭션에 의해 새롭게 변경되는 내역을 데이터베이스 테이블이라 부른다. 트랜잭션의 원자성은 롤백 세그먼트에 의해 보장이 된다. Consistency - 일관성 보장 트랜잭션 수행 전, 후 데이터 베이스 제약 조건 이나, 자료형 이 변하지 않음을 보장한다.
스프링 MVC 시작하기 - XML로 세팅하기 Web.xml 설정하기 root-context.xml 설정하기 servlet-context 설정하기 의존관계 설정하기<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>springMVCstep3</artifactId> <version>1.0-SNAPSHOT</version> <properties> <javax.servlet-version>4.0.1</javax.servlet-version> <javax.servlet.jsp-version>2.3.3</javax.servlet.jsp-version> <javax.servlet.jsp.jstl-version>1.2</javax.servlet.jsp.jstl-version> <org.springframework-version>5.2.2.RELEASE</org.springframework-version> <!-- <org.springframework-version>4.3.25.RELEASE</org.springframework-version> --> </properties> <!-- 라이브러리 셋팅 --> <dependencies> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${javax.servlet-version}</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>${javax.servlet.jsp-version}</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${javax.servlet.jsp.jstl-version}</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${org.springframework-version}</version> </dependency> </dependencies> <build> <finalName>springMVCstep3</finalName> <sourceDirectory>src/main/java</sourceDirectory> <testSourceDirectory>src/test/java</testSourceDirectory> <pluginManagement> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.1</version> <configuration> <warSourceDirectory>WebContent</warSourceDirectory> </configuration> </plugin> </plugins> </pluginManagement> </build> <!-- 라이브러리 버전관리 --></project> Web.xml 설정하기 톰캣 DispatcherServlet 을 스프링 DispatcherServlet 으로 바꾸기 Bean을 정의할 xml 파일을 정의하기 Listener 를 설정한다. 파라미터 인코더 를 설정한다. <!-- 현재 웹 애플리케이션에서 받아들이는 모든 요청에 대해 appServlet이라는 이름으로 정의되어 있는 서블릿을 사용하겠다. --><servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern></servlet-mapping><!-- 요청 정보를 분석해서 컨트롤러를 선택하는 서블릿을 지정한다. --><servlet> <servlet-name>appServlet</servlet-name> <!-- Spring MVC에서 제공하고 있는 기본 서블릿을 지정한다. --> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- Spring MVC 설정을 위한 xml 파일을 지정한다. --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup></servlet> <!-- Bean을 정의할 xml 파일을 지정한다. --><context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/root-context.xml</param-value></context-param> <!-- 리스너설정 --><listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>
21. 젠킨스를 이용해 배포하기플러그인 설치Jenkins 관리 > 플러그인 관리 Publish Over SSH를 설치해준다. 원격 서버 접속 설정하기
20. 프록시 서버 이용하기현재는 client 가 Web Application에 접근하기 위해서는 8080포트를 사용해야 한다. client가 쉽게 접근 할 수 있도록 80번 포트로 어플리케이션을 띄어야 하는데 ubuntu에서는 일반 사용자가 80번 포트를 사용할 수 있는 권한이 없다. 만약 80번 포트로 프로그램을 실행하게 되면 아래와 같은 권한 오류가 뜨게 된다. 그렇다고 어플리케이션을 띄울 때 마다 매번 sudo권한으로 실행시킬 수도 없는 노릇이다. 맥에서는 80번 포트로 잘 열리는데 우분투에서 오류가 떠서 당황 했다. 우분투에서 1024미만 포트는 일반 사용자가 사용할 수 없는 포트이다. Caused by: java.net.SocketException: Permission denied at java.base/sun.nio.ch.Net.bind0(Native Method) ~[na:na] at java.base/sun.nio.ch.Net.bind(Net.java:455) ~[na:na] at java.base/sun.nio.ch.Net.bind(Net.java:447) ~[na:na] at java.base/sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:227) ~[na:na] at java.base/sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:80) ~[na:na] at org.apache.tomcat.util.net.NioEndpoint.initServerSocket(NioEndpoint.java:228) ~[tomcat-embed-core-9.0.41.jar!/:9.0.41] at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:211) ~[tomcat-embed-core-9.0.41.jar!/:9.0.41] at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1159) ~[tomcat-embed-core-9.0.41.jar!/:9.0.41] at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1245) ~[tomcat-embed-core-9.0.41.jar!/:9.0.41] at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:603) ~[tomcat-embed-core-9.0.41.jar!/:9.0.41] at org.apache.catalina.connector.Connector.startInternal(Connector.java:1064) ~[tomcat-embed-core-9.0.41.jar!/:9.0.41] ... 29 common frames omitted nginx를 이용해 프록시 서버 만들어주기80번 포트를 사용하기 위해 Proxy 서버를 띄어 놓고 Proxy 서버로 요청이 들어오면 Spring Boot 프로그램으로 Forwarding 해주도록 설정을 할 것이다. sudo 명령어를 사용해 프로그램을 시키는 방법도 있지만, 매번하기에는 번거롭다는 단점도 있고 /etc/sudoers에 패스워드 권한을 풀어줄 수도 있지만 보안상의 문제가 있어서 가장 안전한 방법으로 Proxy 서버를 이용하기로 했다. nginx 설치하기
19. Build시 DB 연결 Bug Fix 및 Profile 설정Jenkins에서 build 오류Jenkins에서 Build를 진행하면 Test시 해당 오류가 발생하게 된다. Test를 진행하면서 DBConfigByYml 클래스내 필드를 Application-mysql.yml 를 이용해 채우게 되는데 Application-mysql.yml 파일이 Github에는 올라가 있지 않아 문제가 생기게 되는 것이다. > Task :testSampleBoardApplicationTests > contextLoads() FAILED java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132 Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException at ConstructorResolver.java:800 Caused by: org.springframework.beans.factory.BeanCreationException at AutowiredAnnotationBeanPostProcessor.java:405 Caused by: java.lang.IllegalArgumentException at PropertyPlaceholderHelper.java:1782021-02-24 16:17:02.458 INFO 1610 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'17 tests completed, 1 failed> Task :test FAILEDFAILURE: Build failed with an exception.* What went wrong:Execution failed for task ':test'.> There were failing tests. See the report at: file:///var/jenkins_home/workspace/sample-board/build/reports/tests/test/index.html* Try:Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.* Get more help at https://help.gradle.orgBUILD FAILED in 53s7 actionable tasks: 7 executedBuild step 'Invoke Gradle script' changed build result to FAILUREBuild step 'Invoke Gradle script' marked build as failureFinished: FAILURE 여러개의 @PropertySource 사용하기첫번째로 해결한 방법은 @PropertySource를 두개 사용하여 test를 진행할 시에는 H2 database를 바라보게 하고 운영시에는 MySQL을 바라 볼 수 있게 설정 파일을 두게 만들어 사용했다. @PropertySource는 순서에 따라 아래 값이 이전 값을 덮어 쓰게 된다. DBConfigByYml.java @Configuration@PropertySource(value = "classpath:application-h2.yml", factory = YamlPropertySourceFactory.class, ignoreResourceNotFound = true)@PropertySource(value = "classpath:application-mysql.yml", factory = YamlPropertySourceFactory.class, ignoreResourceNotFound = true)public class DBConfigByYml { @Value("${spring.datasource.driver-class-name}") private String driverClassName; @Value("${spring.datasource.url}") private String url; @Value("${spring.datasource.username}") private String username; @Value("${spring.datasource.password}") private String password; @Bean public DataSource dataSource() { return DataSourceBuilder.create() .driverClassName(driverClassName) .url(url) .username(username) .password(password) .build(); }} 여러개의 PropertySource 묶기
18. 외부로부터 설정 받기(yml)YamlPropertySourceFactory.java public class YamlPropertySourceFactory implements PropertySourceFactory { @Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { Properties propertiesFromYaml = loadYamlIntoProperties(resource); String sourceName = name != null ? name : resource.getResource().getFilename(); return new PropertiesPropertySource(sourceName, propertiesFromYaml); } private Properties loadYamlIntoProperties(EncodedResource resource) throws FileNotFoundException { try { YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean(); factory.setResources(resource.getResource()); factory.afterPropertiesSet(); return factory.getObject(); } catch (IllegalStateException e) { // for ignoreResourceNotFound Throwable cause = e.getCause(); if (cause instanceof FileNotFoundException) { throw (FileNotFoundException) e.getCause(); } throw e; } }} DBConfigByYml.java @Configuration@PropertySource(value = "classpath:application-mysql.yml", factory = YamlPropertySourceFactory.class)public class DBConfigByYml { @Value("${spring.datasource.driver-class-name}") private String driverClassName; @Value("${spring.datasource.url}") private String url; @Value("${spring.datasource.username}") private String username; @Value("${spring.datasource.password}") private String password; @Bean public DataSource dataSource(){ return DataSourceBuilder.create() .driverClassName(driverClassName) .url(url) .username(username) .password(password) .build(); }}
17. 외부로부터 설정 받기(property)Github에 프로젝트를 올릴때 데이터 베이스 접속 연결과 같은 민감한 정보는 다른 사람이 열람해서는 안되는 정보라 형상관리에서 제외한 상태로 올리게 된다. .gitignore **/application-mysql.yml**/application-mysql.properties 데이터베이스 접속을 위한 properties 만들기application-mysql.properties spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/{테이블}serverTimezone=UTC&characterEncoding=UTF-8spring.datasource.username={Username}spring.datasource.password={Password} TransactionManagementConfigurer은 Spring에서 데티어베이스 연결을 지원한다. DBConfig.java