Normaltic 모의해킹 취업반 스터디 8기 - 2주차

containerxox·2025년 4월 22일
post-thumbnail

✅ Database

 

( Database의 역할 및 구조 )

  • 데이터를 저장한다.
  • WAS와 소통 (WEB-WAS-DB)

📌 Database 쉽게 이해하기
    ◉ ( DB 구조 )
        ✓ Database == 엑셀 파일
        ✓ Table == 엑셀 시트
        ✓ Column == 열, 데이터 종류, 카테고리
        ✓ Row == 행, 가로 데이터



🕹️ 예시

  • '순번'이라는 Column, '이름'이라는 Column, '점수'라는 Column 가 있다.



💁 현재 Docker에 설치된 mysql이라는 DB에 접속해보자.
( mysql이라는 DB를 웹 페이지에서 관리할 수 있도록 만든 시스템이 phpMyAdmin )
→ 일단 Docker를 실행시키자




( phpMyAdmin으로 MySQL 테이블 생성 및 관리 )

 

☑️ phpMyAdmin 접속

URL: 192.168.35.69:1018/phpmyadmin 검색! → 사용자명, 암호 입력



① Database 생성

‣ 좌측의 새로운 클릭하면 Database 생성할 수 있다.
‣ 언어담당 입력란에는 utf8-general_ci로 설정한다.

나는 test라는 Database를 생성했다.




② Table 생성

‣ 이름 입력란에 생성할 Table명을 적어준다.
‣ 생성할 Table의 컬럼 수를 적어준다.
‣ 실행 버튼 클릭

나는 test_table이라는 Table을 생성했다.
그리고 컬럼 수는 4개로 설정했다.



③ 테이블 구조 설계

‣ 생성할 컬럼 명을 적기
PRIMARY KEY을 설정할 컬럼 정하기
‣ 저장 버튼 클릭

나는 idx, name, score, pass라는 컬럼을 생성했다.
idx는 primary로 설정하고 AI(Auto increment)를 설정했다.


💡 PRIMARY KEY를 설정하는 이유
✓ PRIMARY KEY는 테이블에서 각 행(row)을 유일하게 구분하기 위한 컬럼
✓ 한 테이블에 딱 하나만 설정 가능하고, 중복되면 안되고, NULL도 혀용되지 X
1. 데이터를 고유하게 식별하기 위해 :
→ 예를 들어, 회원 테이블에서 id가 있어야 같은 이름의 사람이라고 구분이 가능하다.
2. 빠르게 찾기 위해 (성능 향상) :
→ PRIMARY KEY로 인덱스가 자동생성되며, 검색이나 JOIN 속도가 빨라진다.
3. 무결성 유지 :
→ 중복된 데이터가 들어오는 걸 막아준다.


💡 AUTO_INCREMENT란?
✓ AUTO_INCREMENT는 숫자가 자동으로 1씩 증가하면서 값이 채워지는 개념
✓ 매번 직접 숫자 입력할 필요 없이, 새로운 데이터가 들어올 때마다 자동으로 번호를 붙여줘서 편리
✓ 주로 PRIMARY KEY로 설정한 컬럼에 많이 쓴다.



④ 데이터 삽입

‣ 생성된 각 컬럼의 값을 넣어준다.
‣ 실행 버튼 클릭
‣ 우측의 테이블명을 클릭하면 데이터가 삽입된 테이블 확인할 수 있다.

idx 컬럼에는 값을 비워두었다. (왜냐, auto_increment로 인해 1부터 자동으로 숫자 증가)
name 컬럼에는 normaltic 입력
score 컬럼에는 100 입력
pass 컬럼에는 1234 입력

현재 생성된 test_table의 구조와 값




💁 지금까지는 GUI환경에서 DB를 조작했어.
이제는 SQL 쿼리를 이용해서 DB 조작해보자!

💡쿼리(Query) 란?

✓ 쿼리는 데이터베이스에 보내는 요청문
✓ 즉, 데이터베이스에게 원하는 작업(검색, 추가, 수정 삭제 등)을 SQL 언어로 명령하는 것을 의미한다.

예를 들면:
→ "이 테이블에서 이름이 '은지'인 사람 찾아줘!"
→ "새로운 회원을 등록할게!"
→ "이 사람의 전화번호를 바꿔줘!"
→ "이 데이터를 삭제할게!"
이런 요청들을 SQL 문장(=쿼리)로 작성해서 DB에 보내는 것이다.



📌 SQL 쿼리로 데이터 조작하기( select, insert, 정교한 select(where구문) )

  • SELECT : 데이터 조회
    select [컬럼이름] from [테이블이름]
     

    예시 1) select name from test_table
    ↳ test_table이라는 테이블에서 name이라는 칼럼을 조회


     
    예시 2) select name, pass from test_table
    ↳ test_table이라는 테이블에서 name과 pass라는 컬럼을 조회

     
    예시 3) select * from test_table
    ↳ test_table이라는 테이블에서 모든 칼럼을 조회



  • INSERT : 데이터 삽입
    insert into [테이블이름] (컬럼이름) value (값)
     

    예시 1) insert into test_table (name, score, pass) value ('doldol', '80', '2222')
    ↳ test_table의 name, score, pass 컬럼에 각각 'doldol', '80', '2222' 값을 삽입


     
    예시 2) insert into test_table value (NULL,'doldol', '80', '2222')
    ↳ test_table의 모든 컬럼에 (inx, name, score, pass 컬럼)에 값을 삽입



  • 정교한 SELECT : where 구문
    select ~~~ from [테이블명] where [조건]
     

    예시 1) select name,pass from test_table where name='normaltic'
    ↳ test_table에서 name과 pass 컬럼을 조회 (단, name이 normaltic인 것만!)

     
    예시 2) select name,pass from test_table where name='normaltic' and pass='1234'
    ↳ test_table에서 name과 pass 컬럼을 조회 (단, name이 normaltic이고 pass='1234'인 것만!)

    예시 3) select name,pass from test_table where name='normaltic' or pass='1234'
    ↳ test_table에서 name과 pass 컬럼을 조회 (단, name이 normaltic이거나 pass='1234'인 것만!)




💁WASDB를 연동해보자!
→ 즉, PHPMySQL을 연동하는거야~!
연동하게 되면 WAS에서 SQL쿼리를 DB에 전송하여 제어 가능해진다!
( PHP 코드에 SQL쿼리를 작성하면 돼! )

▶ ( WAS와 DB 연결 및 쿼리 실행 )

☑️ WAS와 DB 연결

① db_test.php 생성 & 코드 작성
student@segfault:~/webDev/webApp$ vim db_test.php
 

💡mysqli_connect()함수란?
mysqli_connect(host, username, password, dbname);
• WAS가 DB와 소통(연동)하려면 DB와의 커넥터가 필요하다.( mysqli_connect()함수가 커넥터 역할 )
mysqli_connect()MySQL 데이터베이스 서버에 접속하기 위해 사용하는 함수
• 접속이 성공하면 DB 연결 객체(리소스)를 반환
• 접속이 실패하면 false를 반환
 
💡DB 연결 객체(리소스)란?
mysqli_connect()함수는 DB에 접속이 성공하면,
그 DB와 연결 정보를 담은 "통로 객체"를 반환한다.
→ 이 객체를 가지고 나중에 쿼리 실행, 데이터 가져오기, 연결 종료 등의 작업이 가능해진다.
→ 즉, PHP에서는 mysqli_connect()로 얻은 이 리소스를 가지고 DB 작업을 한다!
쉽게 말해, DB 연결객체 = 전화 통화 연결선:
mysqli_connect()는 DB에 전화를 거는거고,
‣ 연결이 성공되면 통화선(객체)이 생김
‣ 그 통화선(객체)을 통해 "쿼리 실행", "데이터 가져오기" 등과 같은 요청을 함.
 
📢 추가 공부
큰 기업의 경우, 컴퓨터를 3개를 쓴다.
(하나는 WEB Server용, 하나는 WAS Server용, 하나는 Database용)
그렇기 때문에 실무에서는 localhost에 DB의 IP주소를 넣어준다.
그러나 지금 같은 경우는 컴퓨터 1대에 VM을 통해 WEB-WAS-DB를 실행하고 있으므로
DB의 IP주소를 localhost라고 한 것이다.

⬇️ < db_test.php 코드 내용 >

<?php
	define('DB_SERVER', 'localhost'); #db서버는 localhost다.
	define('DB_USERNAME', 'admin');
	define('DB_PASSWORD', 'student1234')
	define('DB_NAME','test')
    
	// DB서버 접속 완료하여 커넥터(티켓)을 받으면
	// db_conn 변수에 커텍터(티켓)을 저장.
	$db_conn = mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_NAME);
?>



② DB 서버에 접속이 잘 됬는지 확인하기
else-if문을 통해
접속이 완료되면 DB connect Ok를 출력하고
접속이 실패하면 DB connect Fail을 출력한다.
 
DB 서버 접속 성공 ↓

 

📢 추가 공부

  • WAS는 DB와 소통하려면 로그인을 해야 한다!
  • 따라서, WAS는 ID와 PW를 알고 있어야 한다!
  • 즉, WAS에는 ID와 PW가 저장되어 있다!
  • 그렇기 때문에, WEB서버가 해킹되면, DB도 해킹되었다고 볼 수 있다!

⬇️ < db_test.php 코드 내용 >

<?php
        define('DB_SERVER', 'localhost');
        define('DB_USERNAME', 'admin');
        define('DB_PASSWORD', 'student1234');
        define('DB_NAME','test');

        $db_conn=mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_NAME);

        if($db_conn){
                echo "DB connect OK";
        }else{
                echo "DB connect Fail";
        }
?>




☑️ mysqli_query() 실행부터 데이터 꺼내는 전체 흐름

mysqli_query()로 쿼리 실행하고 결과 가져오기

  • 결과 출력 ↓

    ➡️ object(mysqli_result)
    : mysqli_query()가 반환한 객체는 mysqli_result라는 클래스의 객체라는 뜻
    ➡️ current_field => int(0)
    : 현재 읽고 있는 컬럼의 번호 (0부터 시작)
    : 처음 쿼리 실행 직후엔 아직 아무 필드도 읽지 않았기 때문에 0
    ➡️ field_count => int(3)
    : 쿼리 결과에 포함된 컬럼(필드)의 개수
    ➡️lengths => NULL
    : 현재 레코드(행)의 각 필드 값의 길이
    ➡️ num_rows => int(2)
    : 조회된 행(row)의 총 개수
    ➡️ type => int(0)
    : 쿼리 타입 정보 (내부적으로 사용)
    : 보통 0은 MYSQLI_STORE_RESULT라는 타입 (기본)
     

    💡var_dump()함수란?
    : PHP에서 어떤 변수의 "내부구조"를 그대로 출력해주는 함수
     
    💡mysqli_query()함수란?
    mysqli_query(DB연결객체, SQL쿼리문)

    • 반환값: 2가지로 나뉨!
      ↳ SQL문이 SELECT/ SHOW등이면,
      반환값은 mysqli_result()객체 ( 이 객체 안에는 "조회된 여러 행(row)"이 들어있음 )
      ↳ SQL문이 INSERT/ UPDATE/DELETE등이면,
      반환값은 true 또는 false


      ⚠️ 쿼리를 실행했다고 해서, 데이터까지 바로 읽은 건 아니다!
      $sql = "SELECT * FROM test_table";
      $result = mysqli_query($conn, $sql);
      → DB한테 test_table에서 모든 데이터를 가져와줘라고 요청을 보낸 상태
      → DB가 결과를 result 객체 안에 담아준 상태이다.
      하지만!
      👉 아직 그 결과 안의 행(row)이나 열(column)을 진짜 꺼내서 읽은 건 아니다!
      그래서 current_field가 0이라는 뜻은 "아직 컬럼 데이터를 한 줄 도 꺼내서 읽은 적이 없다는 의미"
       
      💁 비유로 쉽게 이해하기
      mysqli_query()는 책을 책장에서 거내서 테이블 위에 올려놓은 상태
      ‣ 하지만, 아직 책 속 내용을 읽지는 않았다.
      fetch()함수를 써야 실제 페이지(행/열)을 읽기 시작하는 것이다!

⬇️ < db_test.php 코드 내용 >

<?php
      define('DB_SERVER', 'localhost');
      define('DB_USERNAME', 'admin');
      define('DB_PASSWORD', 'student1234');
      define('DB_NAME','test');
		
		#DB 서버 접속하기
      $db_conn=mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_NAME);
		
		# DB 서버 접속 성공 여부 출력
      if($db_conn){
              echo "DB connect OK";
      }else{
              echo "DB connect Fail";
      }
		
      $sql = "select * from test_table";

      $result = mysqli_query($db_conn,$sql);

      var_dump($result);  #결과를 출력해보자.
?>



②-1. 쿼리 결과에서 데이터 가져오기 ( mysqli_fetch_array() 함수 사용 )

💡mysqli_fetch_array()함수란?
: mysqli_query()로 받은 결과에서 한 행(row)씩 꺼내서 배열 형태로 반환해주는 함수
: 결과에서 하나의 row를 가져옴.

⬇️ < db_test.php 코드 내용 >

<?php
	define('DB_SERVER', 'localhost'); #db서버는 localhost다.
	define('DB_USERNAME', 'admin');
	define('DB_PASSWORD', 'student1234')
	define('DB_NAME','test')

	$db_conn = mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_NAME);


	
	$sql = "select * from test_table";

	$result = mysqli_query($db_conn,$sql); 
# 
	$row = mysqli_fetch_array($result);
	
	var_dump($row);
?>

②-2. 그 다음 row를 가져오고 싶다면?( mysqli_fetch_array() 함수 사용 )

⬇️ < db_test.php 코드 내용 >

<?php
	define('DB_SERVER', 'localhost'); #db서버는 localhost다.
	define('DB_USERNAME', 'admin');
	define('DB_PASSWORD', 'student1234')
	define('DB_NAME','test')

	$db_conn = mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_NAME);


	
	$sql = "select * from test_table";

	$result = mysqli_query($db_conn,$sql);  
# 
	$row = mysqli_fetch_array($result);
	
	var_dump($row); //첫번째 row 출력
	
	$row = mysqli_fetch_array($result);
	
	var_dump($row); //두번째 row 출력
?>



(위처럼 여러 개를 가져오지 않고) row 변수에서 이름만 가져오기

➡️첫 번째 row에서 name 칼럼의 값을 가져와 출력함.

⬇️ <span style="color:#9648db">< `db_test.php` 코드 내용 ></span>
<?php
	define('DB_SERVER', 'localhost'); #db서버는 localhost다.
	define('DB_USERNAME', 'admin');
	define('DB_PASSWORD', 'student1234')
	define('DB_NAME','test')

	$db_conn = mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_NAME);

	$sql = "select * from test_table";

	$result = mysqli_query($db_conn,$sql); 
# 
	$row = mysqli_fetch_array($result);
	
	echo "Name : " . $row['name'];
	# php에서 .은 두 개의 문자열을 연결해준다.
?>



☑️ 실습

😊 doldol의 비밀번호를 화면에 출력해보자!

<?php
      define('DB_SERVER', 'localhost');
      define('DB_USERNAME', 'admin');
      define('DB_PASSWORD', 'student1234');
      define('DB_NAME','test');

      $db_conn=mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_NAME);

      $sql = "select * from test_table";

      $result = mysqli_query($db_conn,$sql);

      $row = mysqli_fetch_array($result);

      $result = mysqli_query($db_conn,$sql);

      $row = mysqli_fetch_array($result);

      echo "doldol's PW: ".$row['pass'];
?>



☑️ mysqli_connect(), mysqli_query(), mysqli_fetch_array() 요약 표

  • mysqli_connect(dbIPaddress, username, password, dbname)

    ‣ ( 역할 )

    : DB에 접속을 시도하는 함수
    : WAS가 MySQL DB와 연결할 수 있도록 함

    ‣ ( 반환 값 )

    연결 성공 시 → 연결 객체 반환
    연결 실패 시 → false 반환

    ‣ ( 예시 )
    $conn = mysqli_connect("localhost", "root", "pw", "db");



  • mysqli_query()

    ‣ ( 역할 )

    : SQL 쿼리를 실행하는 함수
    : 조회/삽입/수정/삭제 등 모든 SQL 작업에 사용

    ‣ ( 반환 값 )

    select결과 객체 반환
    그 외 → true/false

    ‣ ( 예시 )
    $result = mysqli_query($conn, "SELECT * FROM users");



  • mysqli_fetch_array(결과 객체)

    ‣ ( 역할 )

    : 쿼리 결과에서 한 행(row)을 꺼내서 배열로 반환

    ‣ ( 반환 값 )

    배열 (연관+숫자 인덱스) 또는 false

    ‣ ( 예시 )
    $row = mysqli_fetch_array($result);



  • 요약 흐름

    1️⃣ mysqli_connect()
    → DB에 접속해서 $conn이라는 연결 객체 생성

    2️⃣ mysqli_query()
    → SQL을 실행해서 $result라는 결과 객체 생성

    3️⃣ mysqli_fetch_array()
    → $result에서 데이터를 한 줄(row)씩 배열 형태로 꺼냄

0개의 댓글