[Java] JSP 연습 문제 2 (flag변수)

1. 조건

  • 주어진 데이터를 활용해서 화면에 표시
  • 리스트에서 노래제목을 클릭하면 해당 노래 세부사항을 표시하는 화면으로 이동
  • 검색어를 입력하면 해당하는 노래 제목이 있을 경우 해당하는 노래 세부사항 페이지로 이동

메인 메인

검색 or 클릭을 통해 result 페이지로 넘어갈 때, 하나는 값이 들어오지 않는데 이를 구분해 넘어가는 게 중요했다.


2. 정답 코드

수업에서의 정답 코드

1. Main page

<%@ page import="java.util.*" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>멜롱-아이유</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
  <style>
    a {
      text-decoration: none;
    }
    a:hover {
      text-decoration: none;
    }

    #wrap {
      width: 1200px;
      margin: auto;
    }

    header {
      height: 100px;
    }
    header .logo {
      width: 150px;
    }
    header .search {
      width: 1050px;
    }
    header .search .search-bar {
      width: 450px;
    }

    nav {
      height: 40px;
    }

    footer {
      height: 200px;
    }
  </style>
</head>
<body>
  <%
    Map<String, Object> artistInfo = new HashMap<>();
    artistInfo.put("name", "아이유");
    artistInfo.put("debute", 2008);
    artistInfo.put("agency", "EDAM엔터테인먼트");
    artistInfo.put("photo", "http://image.genie.co.kr/Y/IMAGE/IMG_ALBUM/081/867/444/81867444_1616662460652_1_600x600.JPG");

    List<Map<String, Object>> musicList = new ArrayList<>();

    Map<String, Object> musicInfo = new HashMap<>();
    musicInfo.put("id", 1);
    musicInfo.put("title", "팔레트");
    musicInfo.put("album", "Palette");
    musicInfo.put("singer", "아이유");
    musicInfo.put("thumbnail", "https://upload.wikimedia.org/wikipedia/ko/b/b6/IU_Palette_final.jpg");
    musicInfo.put("time", 217);
    musicInfo.put("composer", "아이유");
    musicInfo.put("lyricist", "아이유");
    musicList.add(musicInfo);
  %>

  <div id="wrap" class="container">
    <header class="d-flex align-items-center">
      <div class="col-2">
        <h3 class="text-success">Melong</h3>
      </div>
      <div class="col-10">
        <form method="get" action="/lesson02/quiz10_1.jsp">
          <div class="input-group">
            <input type="text" name="search" class="form-control col-6">
            <div class="input-group-append">
              <button class="btn btn-info" type="submit">검색</button>
            </div>
          </div>
        </form>
      </div>
    </header>

    <nav>
      <ul class="nav">
        <li class="nav-item"><a href="#" class="nav-link text-dark font-weight-bold">멜롱차트</a></li>
        <li class="nav-item"><a href="#" class="nav-link text-dark font-weight-bold">최신음악</a></li>
        <li class="nav-item"><a href="#" class="nav-link text-dark font-weight-bold">장르음악</a></li>
        <li class="nav-item"><a href="#" class="nav-link text-dark font-weight-bold">멜롱DJ</a></li>
        <li class="nav-item"><a href="#" class="nav-link text-dark font-weight-bold">뮤직어워드</a></li>
      </ul>
    </nav>

    <section class="contents">
      <div id="infoBox" class="container d-flex border border-success">
        <div>
          <img src="<%= artistInfo.get("photo") %>" alt="표지" width="150">
        </div>
        <div class="ml-3">
          <div class="font-weight-bold">
            <h3><%= artistInfo.get("name") %></h3>
          </div>
          <div><%= artistInfo.get("agency") %></div>
          <div><%= artistInfo.get("debute") %> 데뷔</div>
        </div>
      </div>

      <div>
        <h3 class="mt-3">곡 목록</h3>
        <table class="table text-center">
          <thead>
            <tr>
              <th>no</th>
              <th>title</th>
              <th>album</th>
            </tr>
          </thead>
          <tbody>
            <%
              for (Map<String, Object> song : musicList) {
            %>
              <tr>
                <td><%= song.get("id") %></td>
                <td><a href="/lesson02/quiz10_1.jsp?id=<%= song.get("id") %>"><%= song.get("title") %></a></td>
                <td><%= song.get("album") %></td>
              </tr>
            <%
              }
            %>
          </tbody>
        </table>
      </div>
    </section>

    <footer>
      <hr>
      <small class="text-secondary">Copyright 2025. melong All Rights Reserved.</small>
    </footer>
  </div>
</body>
</html>

2. Result page

<%@ page import="java.util.*" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>멜롱-아이유</title>
  <!-- bootstrap CDN Link -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>

  <style>
    a {
      text-decoration: none;
    }
    a:hover {
      text-decoration: none;
    }

    #wrap {
      width: 1200px;
      margin: auto;
    }

    header {
      height: 100px;
    }
    header .logo {
      width: 150px;
    }
    header .search {
      width: 1050px;
    }
    header .search .search-bar {
      width: 450px;
    }

    nav {
      height: 40px;
    }

    footer {
      height: 200px;
    }
  </style>
</head>
<body>
  <%
    // 아티스트 정보
    Map<String, Object> artistInfo = new HashMap<>();
    artistInfo.put("name", "아이유");
    artistInfo.put("debute", 2008);
    artistInfo.put("agency", "EDAM엔터테인먼트");
    artistInfo.put("photo", "https://pbs.twimg.com/profile_images/1374979417915547648/vKspl9Et_400x400.jpg");

    // 아이유 노래 리스트
    List<Map<String, Object>> musicList = new ArrayList<>();

    Map<String, Object> musicInfo = new HashMap<>();
    musicInfo.put("id", 1);
    musicInfo.put("title", "팔레트");
    musicInfo.put("album", "Palette");
    musicInfo.put("singer", "아이유");
    musicInfo.put("thumbnail", "https://upload.wikimedia.org/wikipedia/ko/b/b6/IU_Palette_final.jpg");
    musicInfo.put("time", 217);
    musicInfo.put("composer", "아이유");
    musicInfo.put("lyricist", "아이유");
    musicList.add(musicInfo);

    // 입력 생략
  %>

  <%
    // 상세 정보를 보여줄 target 세팅
    Map<String, Object> target = null;

    // 1. 목록에서 클릭한 경우 (id값)
    if (request.getParameter("id") != null) {
      Integer paramId = Integer.valueOf(request.getParameter("id"));
      for (Map<String, Object> music : musicList) {
        Integer id = (Integer) music.get("id");
        if (id.equals(paramId)) {
          target = music;
          break;
        }
      }
    }

    // 2. 상단에서 검색한 경우 (search값)
    if (request.getParameter("search") != null) {
      String paramSearch = request.getParameter("search");
      for (Map<String, Object> music : musicList) {
        String title = (String) music.get("title");
        if (title.equals(paramSearch)) {
          target = music;
          break;
        }
      }
    }
  %>

  <div id="wrap" class="container">
    <header class="d-flex align-items-center">
      <div class="col-2">
        <h3 class="text-success">Melong</h3>
      </div>
      <div class="col-10">
        <form method="get" action="/lesson02/quiz10_1.jsp">
          <div class="input-group">
            <input type="text" name="search" class="form-control col-6">
            <div class="input-group-append">
              <button class="btn btn-info" type="submit">검색</button>
            </div>
          </div>
        </form>
      </div>
    </header>

    <nav>
      <ul class="nav">
        <li class="nav-item"><a href="#" class="nav-link text-dark font-weight-bold">멜롱차트</a></li>
        <li class="nav-item"><a href="#" class="nav-link text-dark font-weight-bold">최신음악</a></li>
        <li class="nav-item"><a href="#" class="nav-link text-dark font-weight-bold">장르음악</a></li>
        <li class="nav-item"><a href="#" class="nav-link text-dark font-weight-bold">멜롱DJ</a></li>
        <li class="nav-item"><a href="#" class="nav-link text-dark font-weight-bold">뮤직어워드</a></li>
      </ul>
    </nav>

    <section class="contents">
      <%
        if (target != null) { // -- if문 시작
      %>

      <h4 class="mt-4">곡 정보</h4>
      <div class="d-flex border border-success p-3">
        <div class="music-info">
          <img class="album-size" src="<%= target.get("thumbnail") %>">
        </div>
        <div class="ml-4">
          <div class="display-4"><%= target.get("title") %></div>
          <div class="font-weight-bold text-success"><%= target.get("singer") %></div>
          <div class="d-flex mt-3 music-info">
            <div class="text-dark">
              <div>앨범</div>
              <div>재생시간</div>
              <div>작곡가</div>
              <div>작사가</div>
            </div>
            <div class="ml-4">
              <div><%= target.get("album") %></div>
              <div><%= (Integer) target.get("time") / 60 %>:<%= (Integer) target.get("time") % 60 %></div>
              <div><%= target.get("composer") %></div>
              <div><%= target.get("lyricist") %></div>
            </div>
          </div>
        </div>
      </div>

      <h4 class="mt-4">가사</h4>
      <hr>
      <div>가사 정보 없음</div>

    </section>

    <%
      } else { // -- if문 종료, else문 시작 => target이 없는 경우
    %>
    <section>
      <h1>정보 없음</h1>
    </section>
    <%
      }
    %>

    <hr>
    <footer>
      <small class="text-secondary">Copyright 2024. melong All Rights Reserved.</small>
    </footer>
  </div>
</body>
</html>

3. 내가 푼 방법

1. Result page

공개된 정답 코드와 다른 부분만 보자면

<%
  String search = request.getParameter("search");
  Integer id = null;
  if (request.getParameter("id") != null) {
    id = Integer.parseInt(request.getParameter("id"));
  }

  for (Map<String, Object> albumInfo : musicList) {
    boolean match = false;

    if (id != null) {
      match = id == albumInfo.get("id");
    } else if (search != null) {
      match = search.equals(albumInfo.get("title"));
    }

    if (match) {
%>
  <div>
    <img src="<%= albumInfo.get("thumbnail") %>" alt="표지" width="150">
  </div>
  <div class="ml-3">
    <div class="display-4"><%= albumInfo.get("title") %></div>
    <div class="text-success"><%= albumInfo.get("singer") %></div>
    <div>앨범 <%= albumInfo.get("album") %></div>
    <div>재생시간 <%= (int) albumInfo.get("time") / 60 %>:<%= (int) albumInfo.get("time") % 60 %></div>
    <div>작곡가 <%= albumInfo.get("composer") %></div>
    <div>작사가 <%= albumInfo.get("lyricist") %></div>
  </div>
<%
    }
  }
%>

반복문을 한번만 돌리면서 검색, 클릭 둘 중 하나에서 요청된 값과 일치하는 조건으로 결과를 띄우고 싶었다.

// 정말 단순하게 아래처럼 생각할 수도 있겠지만

if (id == albumInfo.get("id") || search.equals(albumInfo.get("title")))

/*
이경우에 한쪽에 null이 들어오게 되어 NPE를 띄운다.
즉, 값이 null인지 아닌지 확인하는 조건이 선행되어야 한다는 것.
*/

if (id == null || search == null) {
  continue;
}

/*
아님 null일 경우 빠져나오게 해야하나? 싶지만, 원하는 건 일치하는 값을 띄우는 것이기에 불가하다.
이럴 때 유용하게 쓸 수 있는 게 flag변수이다.
*/

for (Map<String, Object> albumInfo : musicList) {
    boolean match = false;

    if (id != null) {
      match = id == albumInfo.get("id");
    } else if (search != null) {
      match = search.equals(albumInfo.get("title"));
    }
}

// if를 충족할 경우 true로 들어옴 -> boolean으로 저장 true일 경우 원하는 데이터 출력.

Integer id = null;
  if (request.getParameter("id") != null) {
    id = Integer.parseInt(request.getParameter("id"));
  }

/*
또한 object에 저장된 id 값도 위처럼 처리해 주지 않으면 null로 들어올 경우 타입 변환이 불가하므로 NPE가 뜨게된다.
그리고 null과 비교할 수 있도록 int가 아닌 Ineger로 저장해줘야 한다.
*/

Categories:

Updated:

Leave a comment