도커 실습 9 - 마이크로 서비스 회원정보 연동 > 클라우드네이티브

본문 바로가기

[실습] 도커 실습 9 - 마이크로 서비스 회원정보 연동

필기자
2025-11-04 18:06 526 0

본문

목차
  • 마이크로 서비스 회원정보 연동

마이크로 서비스 회원정보 연동
  • task 테이블 수정
  • tasks-list.php 수정
  • task-add.php 수정
  • task-edit.php 수정
  • task-delete.php 수정
  • task-search.php 수정
  • task-single.php 수정
  • app.js 수정

task 테이블 수정
  • 기존  task 테이블을 튜닝하여 user 세션과 연결 구조 정의

CREATE TABLE `task` (
  `idx` INT NOT NULL AUTO_INCREMENT,
  `email` VARCHAR(50) NOT NULL,
  `task_name` VARCHAR(255) NOT NULL,
  `task_description` TEXT,
  `task_datetime` DATETIME DEFAULT NULL,
  PRIMARY KEY (`idx`),
  KEY `idx_email` (`email`)
) 


20251104182359_c0ee6dfabfc9cddfc61c5f9ece40468e_hiqm.png

tasks-list.php 수정
  • task테이블에서 user의 email을 기반으로 쿼리 작성
  • 기존 정리된 필드명 리턴


<?php
include_once("./database.php");   // DB 연결 설정 파일 포함
$ret = array();                   // 반환용 배열 초기화
session_start();                  // 세션 시작 (로그인 정보 확인용)

// ==============================
// ① 로그인 여부 확인
// ==============================
if (!isset($_SESSION['useremail']) || $_SESSION['useremail'] == "") {
    // 세션에 이메일이 없으면 로그인 안 된 상태
    $ret['result'] = "no";
    $ret['msg'] = "로그인을 해주십시오.";
    echo json_encode($ret, JSON_UNESCAPED_UNICODE);
    exit;
}

// ==============================
// ② 사용자 이메일 기준으로 task 데이터 조회
// ==============================
$email = mysqli_real_escape_string($connection, $_SESSION['useremail']); // SQL 인젝션 방지
$query = "SELECT * FROM task WHERE email = '{$email}'";                  // 해당 사용자 task만 조회
$result = mysqli_query($connection, $query);                             // 쿼리 실행

if (!$result) {
    // DB 오류 시 처리
    $ret['result'] = "no";
    $ret['msg'] = "데이터베이스 조회 오류";
    echo json_encode($ret, JSON_UNESCAPED_UNICODE);
    exit;
}

// ==============================
// ③ 결과를 JSON 형태로 구성
// ==============================
$json = [];
while ($row = mysqli_fetch_assoc($result)) {
    // mysqli_fetch_assoc()은 컬럼명을 key로 갖는 연관배열 반환
    // 따라서 그대로 JSON 배열에 추가하면 컬럼명 = JSON 키로 유지됨
    $json[] = $row;
}

// ==============================
// ④ 응답 데이터 구성 및 출력
// ==============================
$ret['result'] = "ok";                          // 처리 성공
$ret['msg'] = "정상적으로 데이터를 가져왔습니다.";  // 메시지
$ret['tasks'] = $json;                          // task 목록 데이터
$ret['username'] = $_SESSION['username'];       // 세션의 사용자 이름

// JSON으로 최종 출력 (한글 깨짐 방지 옵션)
echo json_encode($ret, JSON_UNESCAPED_UNICODE);
?>


task-add.php 수정


<?php
include('database.php');
session_start();

if (isset($_POST['task_name']) && isset($_POST['task_description'])) {
    $task_name = mysqli_real_escape_string($connection, $_POST['task_name']);
    $task_description = mysqli_real_escape_string($connection, $_POST['task_description']);
    $email = mysqli_real_escape_string($connection, $_SESSION['useremail']); // 로그인 세션 이메일

    $query = "INSERT INTO task (email, task_name, task_description, task_datetime)
              VALUES ('$email', '$task_name', '$task_description', NOW())";

    $result = mysqli_query($connection, $query);

    if (!$result) {
        die('Query Failed: ' . mysqli_error($connection));
    }

    echo "Task Added Successfully";
}
?>


task-edit.php 수정

<?php
include('database.php');
session_start();

if (isset($_POST['idx'])) {
    $task_name = mysqli_real_escape_string($connection, $_POST['task_name']);
    $task_description = mysqli_real_escape_string($connection, $_POST['task_description']);
    $idx = (int)$_POST['idx'];
    $email = mysqli_real_escape_string($connection, $_SESSION['useremail']); // 로그인한 사용자만 수정 가능

    $query = "UPDATE task 
              SET task_name = '$task_name', 
                  task_description = '$task_description' 
              WHERE idx = '$idx' AND email = '$email'";

    $result = mysqli_query($connection, $query);

    if (!$result) {
        die('Query Failed: ' . mysqli_error($connection));
    }

    echo "Task Updated Successfully";
}
?>


task-delete.php 수정

<?php
include('database.php');
session_start();

if (isset($_POST['idx'])) {
    $idx = (int)$_POST['idx']; // 정수형 변환으로 보안 강화
    $email = mysqli_real_escape_string($connection, $_SESSION['useremail']); // 로그인 사용자 이메일

    // 자기 자신의 task만 삭제 가능하도록 제한
    $query = "DELETE FROM task WHERE idx = $idx AND email = '$email'";
    $result = mysqli_query($connection, $query);

    if (!$result) {
        die('Query Failed: ' . mysqli_error($connection));
    }

    echo "Task Deleted Successfully";
}
?>

task-search.php 수정

<?php
include('database.php');
session_start();

$search = $_POST['search'];

if (!empty($search)) {
    $email = mysqli_real_escape_string($connection, $_SESSION['useremail']); // 로그인 사용자 확인
    $search = mysqli_real_escape_string($connection, $search);              // 검색어 인젝션 방지

    // 해당 사용자(email) 기준으로 task_name LIKE 검색
    $query = "SELECT * FROM task 
              WHERE email = '$email' 
              AND task_name LIKE '{$search}%'";

    $result = mysqli_query($connection, $query);

    if (!$result) {
        die('Query Error: ' . mysqli_error($connection));
    }

    $json = array();
    while ($row = mysqli_fetch_assoc($result)) {
        $json[] = array(
            'idx' => $row['idx'],
            'task_name' => $row['task_name'],
            'task_description' => $row['task_description'],
            'task_datetime' => $row['task_datetime']
        );
    }

    echo json_encode($json, JSON_UNESCAPED_UNICODE);
}
?>

task-single.php 수정

<?php
include('database.php');
session_start();

if (isset($_POST['idx'])) {
    $idx = (int)$_POST['idx']; // 숫자형 강제 변환
    $email = mysqli_real_escape_string($connection, $_SESSION['useremail']); // 로그인 사용자 이메일

    $query = "SELECT * FROM task WHERE idx = {$idx} AND email = '{$email}'";
    $result = mysqli_query($connection, $query);

    if (!$result) {
        die('Query Failed: ' . mysqli_error($connection));
    }

    $json = array();
    while ($row = mysqli_fetch_assoc($result)) {
        $json[] = array(
            'idx' => $row['idx'],
            'email' => $row['email'],
            'task_name' => $row['task_name'],
            'task_description' => $row['task_description'],
            'task_datetime' => $row['task_datetime']
        );
    }

    // 단일 행만 반환
    echo json_encode($json[0], JSON_UNESCAPED_UNICODE);
}
?>


app.js 수정

  • 수정후 반드신 클리어캐시 할 것


const hostName = window.location.hostname;
const hostNameServerUrl = '/task/';
$(document).ready(function() {
    let edit = false;
    console.log('jquery is working!');
    fetchTasks();
    $('#task-result').hide();
    var url = window.location.href;
    var searchValue = new URL(url).searchParams.get("search");
    $(function() {
        if (searchValue) {
            $('#search').val(searchValue).trigger("keyup");
        }
    });
    // 검색 기능
    $('#search').keyup(function() {
        if ($('#search').val()) {
            let search = $('#search').val();
            $.ajax({
                url: hostNameServerUrl + 'task-search.php',
                data: { search },
                type: 'POST',
                success: function(response) {
                    if (!response.error) {
                        let tasks = JSON.parse(response);
                        let template = '';
                        tasks.forEach(task => {
                            template += `
                                <li taskId="${task.idx}">
                                    <a href="#" class="task-item">${task.task_name}</a>
                                </li>
                            `;
                        });
                        $('#task-result').show();
                        $('#container').html(template);
                    }
                }
            });
        }
    });
    // 등록 및 수정 처리
    $('#task-form').submit(e => {
        e.preventDefault();
        const postData = {
            task_name: $('#name').val(),
            task_description: $('#description').val(),
            idx: $('#taskId').val()
        };
        const url = edit === false ? 'task-add.php' : 'task-edit.php';
        console.log(postData, url);
        $.post(hostNameServerUrl + url, postData, (response) => {
            console.log(response);
            $('#task-form').trigger('reset');
            fetchTasks();
        });
    });
    // 목록 불러오기
    function fetchTasks() {
        $.ajax({
            url: hostNameServerUrl + 'tasks-list.php',
            type: 'GET',
            dataType: "json",
            success: function(tasks) {
                if (tasks.result == "ok") {
                    const list = tasks.tasks;
                    let template = '';
                    list.forEach(task => {
                        template += `
                            <tr taskId="${task.idx}">
                                <td>${task.idx}</td>
                                <td><a href="#" class="task-item">${task.task_name}</a></td>
                                <td>${task.task_description}</td>
                                <td>${task.task_datetime}</td>
                                <td>
                                    <button class="task-delete btn btn-danger" data-taskId="${task.idx}">Delete</button>
                                </td>
                            </tr>
                        `;
                    });
                    $('#tasks').html(template);
                    $('.user-name').remove();
                    $(".table-bordered").before("<p class='user-name'>" + tasks.username + "님의 할일</p>");
                } else {
                    alert(tasks.msg);
                    window.location.href = "/login.html";
                }
            }
        });
    }
    // 폼 초기화
    function initForm() {
        edit = false;
        $('#name').val("");
        $('#description').val("");
        $('#taskId').val("");
        $('#task-result').hide();
    }
    // 단일 Task 조회
    $(document).on('click', '.task-item', (e) => {
        e.preventDefault();
        var element = $(this)[0].activeElement.parentElement.parentElement;
        var idx = $(element).attr('taskId');
        if (!idx) {
            element = $(this)[0].activeElement.parentElement;
            idx = $(element).attr('taskId');
        }
        if (idx) {
            $.post(hostNameServerUrl + 'task-single.php', { idx }, (response) => {
                const task = JSON.parse(response);
                $('#name').val(task.task_name);
                $('#description').val(task.task_description);
                $('#taskId').val(task.idx);
                edit = true;
            });
        }
    });
    // Task 삭제
    $(document).on('click', '.task-delete', (e) => {
        if (confirm('Are you sure you want to delete it?')) {
            const element = $(this)[0].activeElement.parentElement.parentElement;
            const idx = $(element).attr('taskId');
            $.post(hostNameServerUrl + 'task-delete.php', { idx }, (response) => {
                if (response == 'Task Deleted Successfully') {
                    initForm();
                    fetchTasks();
                    $("#search").trigger("keyup");
                }
                alert(response);
            });
        }
    });
});

 


index.html 수정

  • 수정후 반드신 클리어캐시 할 것


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Todo App</title>
<!-- BOOTSTRAP 4  -->
<link rel="stylesheet" href="https://bootswatch.com/4/lux/bootstrap.min.css">
</head>
<body>
    <!-- NAVIGATION  -->
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <a class="navbar-brand" href="#">Tasks App</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false"
            aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav ml-auto">
                <form class="form-inline my-2 my-lg-0">
                    <input name="search" id="search" class="form-control mr-sm-2"
                        type="search" placeholder="Search" aria-label="Search">
                    <button class="btn btn-success my-2 my-sm-0" type="submit">Search</button>
                </form>
        </div>
    </nav>
    <div class="container">
        <div class="row p-4">
            <div class="col-md-5">
                <div class="card">
                    <div class="card-body">
                        <!-- FORM TO ADD TASKS -->
                        <form id="task-form">
                            <div class="form-group">
                                <input type="text" id="name" placeholder="Task Name"
                                    class="form-control">
                            </div>
                            <div class="form-group">
                                <textarea id="description" cols="30" rows="10"
                                    class="form-control" placeholder="Task Description"></textarea>
                            </div>
                            <input type="hidden" id="taskId">
                            <button type="submit"
                                class="btn btn-primary btn-block text-center">Save Task
                            </button>
                        </form>
                    </div>
                </div>
            </div>
            <!-- TABLE  -->
            <div class="col-md-7">
                <div class="card my-4" id="task-result">
                    <div class="card-body">
                        <!-- SEARCH -->
                        <ul id="container"></ul>
                    </div>
                </div>
                <table class="table table-bordered table-sm">
                    <thead>
                        <tr>
                            <td>Id</td>
                            <td>Task Name</td>
                            <td>Task Description</td>
                        </tr>
                    </thead>
                    <tbody id="tasks"></tbody>
                </table>
                <div><button id="logout" class="btn btn-warning">로그아웃</button></div>
            </div>
        </div>
    </div>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"
        integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
        crossorigin="anonymous"></script>
    <script>
        $(function(){
            $("#logout").click(function(){
                $.ajax({
                    url: '/user/logout.php',
                    type: 'POST',
                    dataType: "json", // 서버에서 받는 데이터 타입
                    success: function(data) {
                        //const tasks = JSON.parse(response);
                       
                        if(data.result == "ok"){
                            alert(data.msg)
                            window.location.href = "/login.html";
                        }else{
                            alert(data.msg);
                        }
                    }
                });            
            });
        });
    </script>
    <!-- Frontend Logic -->
    <script src="app.js"></script>
</body>
</html>


20251104185441_c0ee6dfabfc9cddfc61c5f9ece40468e_t93o.png

댓글목록0

등록된 댓글이 없습니다.
게시판 전체검색