프로젝트/Kimstagram

[내멋대로 만드는 Kimstagram] 11. 유저 검색

kim-dev 2024. 1. 29. 15:38
반응형

지금까지 가입된 유저를 찾는 기능이 없었어서 계속 주소 창에서 주소를 입력해서 들어갔었는데 너무 불편해서(...)

이제서야 유저 검색 기능을 만들기로 했다.
사실 검색 자체는 굉장히 간단한 기능인 것 같아서... 빠르게 구현할 수 있을 듯?!


일단 간단히 유저 검색 폼을 만들어 주었다.
실제 인스타그램은 검색을 클릭하지 않아도 파바박 유저들이 나오던데... 프론트는 아직 문외한이라 거기까지는 일단 스킵 ㅜ
(사실 할 수는 있을 것 같은데 귀찮은 게 너무 크다)

뭐 이런 식으로 나오게... 만들었다.
아직 검색을 구현한 건 아니고, 대략 div만 넣어서 어떤 식으로 나올지 형태만 잡아주었다.

닉네임을 검색하면 아래에 저렇게 유저 목록이 쫘르륵 나타나게 하면 될 것!

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<head>
    <%@ include file="../../layout/indexHeader.jsp"%>
    <%@ include file="../../layout/menu.jsp"%>
    <%@ include file="../getPrincipal.jsp"%>

    <style>
        body {
            margin-left: 74px;
        }

        #Contents {
            position: relative;
            display: flex;
            justify-content: center;
        }

        #findDiv {
            position: absolute;
            top: 130px;
            width: 700px;
        }

        #findButton {
            width: 80px;
            margin-left: 10px;
            margin-right: 10px;
            color: #0095f6;
            cursor: pointer;
            font-weight: bold;
        }
        #findButton:hover {
            font-size: 17px;
            color: #1877f2;
        }
        #findButton:active {
            font-size: 16px;
            color: #4cb5f9;
        }

        #users {
            width: 700px;
            padding: 16px 20px;
            cursor: pointer;
            border-radius: 6px;
        }
        #users:hover {
            background-color: #f2f2f2;
        }
        #users:active {
            background-color: #fafafa;
        }

        #users_profileImg {
            width: 44px;
            height: 44px;
            border: 1px solid #ededed;
            border-radius: 50%;
            margin-right: 10px;
        }
    </style>
</head>

<body>
    <div id="Contents">
        <div id="findDiv">
            <div style="margin-right: auto; padding: 20px 0px">
                <span style="font-size: 26px; font-weight: bold">검색</span>
            </div>
            <div style="display: flex; flex-direction: row; margin-bottom: 20px">
                <input id="findInput" style="width: 600px; height: 36px; border: none; border-radius: 8px; background-color: #efefef" placeholder="  유저네임 입력">
                <div id="findButton" style="width: 80px; margin-left: 10px; margin-right: 10px; display: flex;  align-items: center; justify-content: center" onclick="findUsers()">검색</div>
            </div>

            <div id="usersDiv" style="height:500px; overflow-y: auto; overflow-x: hidden">

            </div>
        </div>
    </div>
</body>

<script src="/js/find.js"></script>


그리고 예전 포스트부터 베지터가 왜이렇게 많이 나오냐고 묻는다면...
테스트 계정 만드려고 프로필 사진을 검색하고 구하고 있었는데, 구글에 캐릭터 사진 검색하니 제일 먼저 발견한 게 저 베지터 사진이라서... 그냥 저걸 계속 쓰고 있다... ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

여튼 저 div를 반복해서 띄우면 될 것이다.
그러면 유저이름을 입력해서 검색하는 js 함수를 아래와 같이 구현하였다.

function findUsers () {
    var usernameInput = document.getElementById('findInput').value;
    if (usernameInput === "") {
        alert("유저네임을 입력해주세요.");
    } else {
        let data = {
           username: usernameInput
        }
        $.ajax({
            type: "GET",
            url: "/findUser",
            data: data,
            contentType: "application/json; charset=utf-8",
        }).done(function(accounts) {

            var usersDiv = document.getElementById('usersDiv');
            usersDiv.innerHTML = "";

            accounts.forEach(function(account) {

                const users = document.createElement("div");
                users.id = "users";
                users.onclick = function () {
                    gotoProfile(account.username);
                }

                    const users_contents = document.createElement("div");
                    users_contents.id = "users_contents";
                    users_contents.style.display = "flex";
                    users_contents.style.flexDirection = "row";

                        const users_profileImg = document.createElement("img");
                        users_profileImg.id = "users_profileImg";
                        if (account.use_profile_img === 1) {
                            users_profileImg.src = "/dynamicImage/profile/" + account.username + "/profile.jpg";
                        } else {
                            users_profileImg.src = "/dynamicImage/profile/default.jpg";
                        }
                        users_contents.appendChild(users_profileImg);

                        const users_namesInfo = document.createElement("div");
                        users_namesInfo.id = "users_namesInfo";
                        users_namesInfo.style.display = "flex";
                        users_namesInfo.style.flexDirection = "column";

                            const users_username = document.createElement("span");
                            users_username.id = "users_username";
                            users_username.style.fontSize = "14px";
                            users_username.style.fontWeight = "bold";
                            users_username.style.marginBottom = "-2px";
                            users_username.innerText = account.username;
                            users_namesInfo.appendChild(users_username);

                            const users_name = document.createElement("span");
                            users_name.id = "users_name";
                            users_name.style.fontSize = "14px";
                            users_name.style.color = "#737373";
                            users_name.innerText = account.name;
                            users_namesInfo.appendChild(users_name);

                        users_contents.appendChild(users_namesInfo);

                        const users_followers = document.createElement('div');
                        users_followers.id = "users_followers";
                        users_followers.style.fontSize = "14px";
                        users_followers.style.color = "#737373";
                        users_followers.style.paddingTop = "19px";
                        users_followers.style.marginLeft = "4px";
                        users_followers.innerText = "• 팔로워 " + account.follower + "명";
                        users_contents.appendChild(users_followers);

                    users.appendChild(users_contents);

                usersDiv.appendChild(users);
            });
        }).fail(function (error) {
            alert("에러 발생 (콘솔 확인)");
            console.log(error);
        });
    }
}

 

그리고 이제 "/findUser"의 GET 컨트롤러를 만들어 줘야겠조???
이 컨트롤러는 username의 일부를 받아서, 그걸 포함하는 모든 유저들을 ArrayList로 반환하면 된다.
즉 JPA로 LIKE와 와일드카드 %를 사용해야 하는데, 이 기능 역시 JPA에서는 제공해주고 있다!

@GetMapping("/findUser")
public ArrayList<Account> find(@RequestParam String username) {
    ArrayList<Account> result = homeService.find(username);

    return result;
}
@Transactional
public ArrayList<Account> find(String username) {
    ArrayList<Account> accounts = accountRepository.findAllByUsernameLike("%" + username + "%");

    return accounts;
}

그냥 JPA 구문 뒤에 'Like'를 붙여주면, 와일드카드와 LIKE 연산을 사용할 수 있다는 점!


이렇게 로직을 작성해 준다면, 이제 유저 검색은 모두 끝난다.
username의 일부를 데이터로 담아서 GET 요청을 보낸 후,
서버에서는 그 데이터를 받아서 JPA 쿼리 처리 후 해당하는 Account 객체들을 ArrayList로 담아 클라이언트에게 응답한다.
그리고 클라이언트 측에서 해당 응답 데이터를 보여주게 된다!