<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>ki-sd 님의 블로그</title>
    <link>https://ki-sd.tistory.com/</link>
    <description>Java 웹 개발자를 목표로 공부하고 있습니다.</description>
    <language>ko</language>
    <pubDate>Thu, 21 May 2026 20:33:31 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>ki-sd</managingEditor>
    <item>
      <title>[2026-05-21] 데이터베이스 커넥션 풀(DBCP) 도입 및 HTTP 상태 관리(Session/Cookie)</title>
      <link>https://ki-sd.tistory.com/59</link>
      <description>&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 기존의 일반적인 JDBC 연동 방식이 가진 성능적 한계를 개선하기 위해 DBCP(Database Connection Pool)를 도입하고, HTTP 프로토콜의 무상태(Stateless) 특성을 보완하기 위한 &lt;b data-index-in-node=&quot;120&quot; data-path-to-node=&quot;3&quot;&gt;Session과 Cookie&lt;/b&gt;의 동작 원리 및 적용 방법을 학습했다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;1. DBCP(DataBase Connection Pool)와 JNDI 연동&lt;/b&gt; 기존에는 클라이언트의 요청이 발생할 때마다 DB 커넥션을 새로 생성하고 닫는 방식을 사용했다. 이 방식은 커넥션 생성 비용이 커서 서버 성능 저하 및 메모리 누수를 유발할 수 있음을 확인했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;DBCP 동작 원리:&lt;/b&gt; 웹 서버(Tomcat)가 시작될 때 지정된 개수만큼의 DB 커넥션을 미리 생성하여 풀(Pool)에 보관한다. 클라이언트 요청 시 풀에서 커넥션을 빌려와 사용하고, 작업이 끝나면 close()를 통해 연결을 종료하는 것이 아니라 풀에 다시 반환(재사용)하는 구조를 실습했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;JNDI(Java Naming and Directory Interface) 활용:&lt;/b&gt; EmpDAO에서 InitialContext 객체를 생성하여 디렉토리 서비스를 열고, java://comp/env 경로를 통해 톰캣이 관리하는 자원에 접근했다. 이후 DataSource ds = (DataSource)c.lookup(&quot;jdbc/oracle&quot;);를 통해 web.xml과 context.xml에 명명된 DB 설정 정보를 찾아 커넥션을 얻어오는 방식으로 코드를 개선했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;2. HTTP 상태 관리: Session과 Cookie&lt;/b&gt; HTTP 프로토콜은 이전 요청을 기억하지 못하는 무상태(Stateless) 특성이 있다. 로그인 유지나 최근 본 상품 등의 기능을 구현하기 위해 클라이언트와 서버 측에 각각 데이터를 저장하는 방식을 비교 및 실습했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;Cookie (클라이언트 측 저장):&lt;/b&gt; * 데이터가 사용자의 브라우저(로컬)에 저장되며 보안에 취약하므로, 중요하지 않은 텍스트 데이터(예: 최근 본 상품, 아이디 저장)를 보관하는 데 사용된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;setMaxAge(초)를 통해 브라우저가 종료되어도 지정된 시간만큼 데이터가 유지되는 특징을 확인했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;Session (서버 측 저장):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터가 서버의 메모리에 저장되며 브라우저당 1개씩 고유하게 생성된다. 보안이 필요한 데이터(예: 로그인 아이디, 권한 등)를 저장하는 데 적합하다.&lt;/li&gt;
&lt;li&gt;session.setAttribute()로 값을 저장하고, session.getAttribute()로 값을 읽어와 header.jsp나 main.jsp에서 로그인 상태에 따라 UI를 다르게 렌더링하는 조건부 출력을 구현했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;3. VO/Bean 패턴을 통한 데이터 캡슐화&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;EmpBean, FoodVO, GoodsVO, MemberVO 등 여러 테이블 스키마에 대응하는 데이터 전송 객체들을 작성했다.&lt;/li&gt;
&lt;li&gt;Lombok의 @Data 어노테이션을 활용하여 보일러플레이트 코드(Getter/Setter 등)를 줄이고, DB 계층에서 추출된 데이터를 View(JSP) 계층으로 안전하게 전달하는 객체 지향적 데이터 은닉화 원칙을 적용했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10&quot;&gt;4. 모듈화된 화면 레이아웃 적용&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;header.jsp, home.jsp, main.jsp 파일들을 분리하여 작성하고, &amp;lt;jsp:include&amp;gt; 액션 태그를 사용해 하나의 메인 화면으로 조립했다.&lt;/li&gt;
&lt;li&gt;이를 통해 페이지 간 중복되는 HTML 레이아웃 구조를 최소화하고, 특정 영역(예: 로그인 폼, 내비게이션 바)의 유지보수성을 높이는 템플릿 기반 렌더링 방식을 확인했다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>WebStudy</category>
      <category>WEB</category>
      <author>ki-sd</author>
      <guid isPermaLink="true">https://ki-sd.tistory.com/59</guid>
      <comments>https://ki-sd.tistory.com/59#entry59comment</comments>
      <pubDate>Thu, 21 May 2026 20:28:57 +0900</pubDate>
    </item>
    <item>
      <title>[2026-05-20] JSP 내장 객체 제어, 웹 페이지 모듈화 및 데이터 흐름 관리</title>
      <link>https://ki-sd.tistory.com/58</link>
      <description>&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 JSP의 주요 내장 객체를 활용해 서버와 클라이언트 간의 상태를 관리하고, 페이지 레이아웃을 효율적으로 조립하는 모듈화 기법을 학습했다. 데이터베이스 연동과 파일 입출력을 포함한 전반적인 웹 애플리케이션의 흐름을 정리했다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;1. JSP 내장 객체를 이용한 응답 및 상태 관리&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;response 객체:&lt;/b&gt; HTTP 응답을 제어하며, addCookie()를 통해 클라이언트에 상태 정보를 전달하거나 sendRedirect()로 브라우저의 페이지 이동을 지시한다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;application 객체:&lt;/b&gt; ServletContext를 통해 서버 전역 자원을 관리한다. getInitParameter()로 설정 값을 읽거나 getRealPath(&quot;/&quot;)로 서버 내 실제 파일 경로를 확인하는 용도로 사용했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,0&quot;&gt;out 객체:&lt;/b&gt; 생성된 HTML이 브라우저로 전송되기 전 대기하는 출력 버퍼를 제어한다. 버퍼의 크기(getBufferSize)와 잔여 공간(getRemaining)을 확인하여 서버 사이드 렌더링 과정을 이해했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,3,0&quot;&gt;쿠키(Cookie) 활용:&lt;/b&gt; 최근 본 상품 기능 등을 구현하기 위해 식별자(no)를 쿠키에 담아 저장하고, 중간 처리 페이지(detail_before.jsp)를 거쳐 상세 페이지로 이동하는 로직을 통해 데이터 처리와 뷰 렌더링을 분리했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;2. IO 스트림을 이용한 파일 다운로드&lt;/b&gt; 서버 내부의 파일을 클라이언트로 전송하기 위해 스트림 제어 기법을 적용했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;response.setHeader(&quot;Content-Disposition&quot;, ...) 설정을 통해 응답 형식을 파일 다운로드로 지정했다.&lt;/li&gt;
&lt;li&gt;FileInputStream과 BufferedOutputStream을 활용해 데이터를 바이트 단위로 클라이언트에 전송했다. 이때 JSP의 기본 출력 버퍼와 스트림 간의 충돌을 피하기 위해 out.clear()와 pageContext.pushBody()를 사용하여 버퍼를 비워주는 예외 처리 과정을 학습했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;3. JSP 레이아웃 모듈화 (정적 vs 동적 첨부)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;정적 포함 (&amp;lt;%@ include %&amp;gt;):&lt;/b&gt; 여러 영역(header.jsp, footer.jsp, aside.jsp, section.jsp)으로 분리된 컴포넌트 파일을 하나의 파일로 조립하는 기법이다. 파일 여러 개를 컴파일 시점에 하나로 합쳐 효율성을 높인다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,0&quot;&gt;동적 포함 (&amp;lt;jsp:include&amp;gt; / pageContext.include):&lt;/b&gt; 실행 시점에 다른 JSP 페이지의 결과를 포함한다. 독립적으로 컴파일되며 request 객체를 공유할 수 있다는 점이 정적 방식과의 차이점이다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,0&quot;&gt;페이지 이동 (&amp;lt;jsp:forward&amp;gt; / pageContext.forward):&lt;/b&gt; 브라우저의 URL 변경 없이 서버 내부에서 페이지만 전환한다. request 객체가 유지되므로 다음 페이지로 데이터를 안전하게 전달할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10&quot;&gt;4. 데이터 연동 및 인터페이스 구성&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FoodDAO를 통해 DB에서 데이터를 페이징 처리하여 가져오고, Bootstrap 그리드 시스템을 활용하여 텍스트 오버플로우가 적용된 반응형 카드 UI를 렌더링했다.&lt;/li&gt;
&lt;li&gt;검색 및 상세보기 기능 구현 시, URL Query String을 통해 식별자를 전달하고 이를 서버 단에서 수신하여 적절한 DB 쿼리를 실행하는 흐름을 확인했다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>WebStudy</category>
      <category>WEB</category>
      <author>ki-sd</author>
      <guid isPermaLink="true">https://ki-sd.tistory.com/58</guid>
      <comments>https://ki-sd.tistory.com/58#entry58comment</comments>
      <pubDate>Thu, 21 May 2026 19:49:20 +0900</pubDate>
    </item>
    <item>
      <title>[2026-05-19] JSP 지시자(Directive), 내장 객체(request) 및 CSS 레이아웃 실습</title>
      <link>https://ki-sd.tistory.com/57</link>
      <description>&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 JSP의 기본 설정 방식인 지시자와, 클라이언트-서버 간 데이터 전송을 다루는 내장 객체(request)의 활용법을 정리했다. 아울러 웹 페이지의 공통 영역 분리(Include)와 예외 처리(Error Page), 그리고 CSS의 요소 배치 속성들을 실습했다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;1. JSP 지시자(Directive)와 페이지 모듈화&lt;/b&gt; JSP 파일 상단에 정의되는 지시자의 종류와 세부 속성을 다루었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;page 지시자:&lt;/b&gt; * contentType: 브라우저가 응답을 어떻게 해석할지 지정한다. 일반적인 text/html 외에도 text/xml, text/plain(JSON 응답용) 형식으로 응답 타입을 변경하는 실습을 진행했다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;import: 자바 라이브러리(java.util.*, java.sql.* 등)를 로드할 때 사용한다.&lt;/li&gt;
&lt;li&gt;buffer, info: 출력 버퍼의 크기(기본 8kb)를 설정하거나 문서 정보를 기록하는 용도로 사용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;include 지시자:&lt;/b&gt; 웹 페이지를 header.jsp, footer.jsp, aside.jsp, section.jsp 등 여러 컴포넌트로 분리한 뒤, include.jsp 파일에서 &amp;lt;%@ include file=&quot;...&quot; %&amp;gt; 구문을 통해 하나의 파일로 조립하여 출력하는 모듈화 방식을 확인했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,0&quot;&gt;taglib 지시자:&lt;/b&gt; 향후 JSTL(JavaServer Pages Standard Tag Library)을 사용하기 위해 &amp;lt;c:forEach&amp;gt; 등 외부 태그를 가져오는 &amp;lt;%@ taglib %&amp;gt; 선언 방식을 확인했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;2. JSP 에러 페이지(Error Page) 처리&lt;/b&gt; 코드 실행 중 발생하는 예외(Exception)를 사용자에게 직접 노출하지 않고 지정된 화면으로 유도하는 방식을 구현했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로직이 있는 JSP 파일 상단에 errorPage=&quot;error_1.jsp&quot;를 지정하여 에러 발생 시 해당 페이지로 이동하게 한다.&lt;/li&gt;
&lt;li&gt;에러를 출력할 error_1.jsp 파일에는 isErrorPage=&quot;true&quot; 속성을 부여하여 exception 내장 객체를 활성화하고, exception.getMessage()를 통해 오류 내용을 확인하도록 구성했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;3. 내장 객체(request)와 폼 데이터 전송&lt;/b&gt; 클라이언트의 요청 정보를 담고 있는 request 내장 객체의 주요 메서드를 활용했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;클라이언트 및 서버 정보 추출:&lt;/b&gt; request.getRequestURI(), getContextPath(), getRemoteAddr() 등을 사용하여 접속한 사용자의 IP와 요청 경로를 확인하는 로직을 작성했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,0&quot;&gt;Form 데이터 수신 (input.jsp -&amp;gt; output.jsp):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;type=&quot;text&quot;, radio 등 단일 값은 request.getParameter(&quot;name&quot;)으로 수신한다.&lt;/li&gt;
&lt;li&gt;type=&quot;checkbox&quot;처럼 다수의 값이 넘어오는 요소는 request.getParameterValues(&quot;hobby&quot;)를 사용하여 String 배열 형태로 수신한 뒤 반복문으로 출력해야 함을 실습했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10&quot;&gt;4. CSS 레이아웃: float와 position&lt;/b&gt; HTML 요소를 배치하기 위한 핵심 CSS 속성들을 실습했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,0,0&quot;&gt;float 속성 (left, right):&lt;/b&gt; 블록 요소를 가로로 나란히 배치할 때 사용하며, 이미지 갤러리 썸네일(float3.jsp)이나 텍스트박스 옆에 버튼을 붙이는 UI(float2.jsp) 구현에 적용했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0&quot;&gt;position 속성:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;static: 기본값으로, HTML 소스 코드 작성 순서대로 배치된다.&lt;/li&gt;
&lt;li&gt;relative: 원래 배치될 위치를 기준점으로 삼아 좌표를 이동한다.&lt;/li&gt;
&lt;li&gt;absolute: 가장 가까운 상위 요소(주로 relative)를 기준으로 좌표를 지정한다.&lt;/li&gt;
&lt;li&gt;fixed: 스크롤과 무관하게 브라우저 창(Viewport)의 특정 위치에 요소를 고정한다.&lt;/li&gt;
&lt;li&gt;sticky: 스크롤을 내리다 특정 임계점에 도달하면 그 자리에 고정되는 방식이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;12&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12&quot;&gt;5. 실전 적용: 상품 목록 연동 및 페이징&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;13&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GoodsDAO와 GoodsVO를 사용하여 오라클 DB의 상품 데이터를 가져왔다.&lt;/li&gt;
&lt;li&gt;request.jsp에서 request.getParameter(&quot;page&quot;)로 요청된 페이지 번호를 수신한 후, 데이터 목록과 하단 블록 페이징을 구현했다.&lt;/li&gt;
&lt;li&gt;추출된 데이터를 기반으로 이미지, 상품명, 가격 등을 카드 형태의 레이아웃으로 렌더링하고, 클릭 시 상품 번호(no)를 쿼리 스트링으로 상세 페이지(detail.jsp)에 전달하는 전체 흐름을 확인했다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>WebStudy</category>
      <category>WEB</category>
      <author>ki-sd</author>
      <guid isPermaLink="true">https://ki-sd.tistory.com/57</guid>
      <comments>https://ki-sd.tistory.com/57#entry57comment</comments>
      <pubDate>Tue, 19 May 2026 20:10:39 +0900</pubDate>
    </item>
    <item>
      <title>[2026-05-18] Servlet과 JSP의 아키텍처 비교 및 CSS Position 속성 정리</title>
      <link>https://ki-sd.tistory.com/56</link>
      <description>&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 자바(Java) 코드로 웹 화면을 구성하는 &lt;b data-index-in-node=&quot;28&quot; data-path-to-node=&quot;3&quot;&gt;서블릿(Servlet)&lt;/b&gt; 방식을 실습하고, 이를 개선하기 위해 등장한 JSP(JavaServer Pages)의 구조적 차이를 확인했다. 또한, 웹 페이지 요소의 배치를 제어하는 CSS position 속성의 특징을 정리했다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;1. Servlet의 동작 원리와 JSP의 특징&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;서블릿(Servlet)의 한계:&lt;/b&gt; EmpList.java 실습을 통해 서블릿 클래스를 작성했다. DB에서 사원 정보를 가져와 브라우저에 출력할 때, out.println(&quot;&amp;lt;html&amp;gt;...&quot;);처럼 HTML 코드를 일일이 문자열로 작성해야 하므로 화면 수정과 유지보수가 까다롭다는 점을 확인했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;JSP의 도입과 동작 사이클:&lt;/b&gt; 반면 JSP는 HTML 뼈대 안에 자바 코드를 삽입하는 방식이다. 클라이언트가 .jsp 파일을 요청하면, 톰캣(WAS)이 이를 서블릿(.java -&amp;gt; .class)으로 변환하여 실행한 뒤 HTML 결과물만 브라우저로 응답하는 흐름을 파악했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;2. JSP 기본 문법 (스크립팅 요소)과 제어문&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;&amp;lt;% %&amp;gt; (스크립틀릿):&lt;/b&gt; 일반적인 자바 로직(변수 선언, 반복문, 메서드 호출 등)이 작성되는 영역이다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;&amp;lt;%= %&amp;gt; (표현식):&lt;/b&gt; 변수나 연산의 결과값을 화면에 출력할 때 사용하며, 끝에 세미콜론(;)을 붙이지 않는 특징이 있다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,2,0&quot;&gt;&amp;lt;%! %&amp;gt; (선언식):&lt;/b&gt; 멤버 변수나 메서드를 선언할 때 사용하지만, 동시성 문제와 객체 지향적 설계 원칙으로 인해 실무에서는 잘 쓰이지 않는 점을 짚고 넘어갔다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,3,0&quot;&gt;JSTL 도입:&lt;/b&gt; jsp_basic5.jsp 실습에서 &amp;lt;c:forEach&amp;gt; 태그를 사용하여, 자바의 반복문 로직을 HTML과 분리해 가독성을 높이는 방법을 실습했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;3. 백엔드 데이터 연동: EMP/DEPT 조인(JOIN)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;EmpDAO에서 사원 테이블(EMP)과 부서 테이블(DEPT)을 조인한 결과를 EmpVO에 담아 JSP로 전달했다. 이를 통해 데이터베이스의 데이터가 Java를 거쳐 웹 화면으로 출력되는 계층 간 데이터 흐름을 확인했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10&quot;&gt;4. CSS Position 속성을 이용한 공간 제어&lt;/b&gt; 문서의 기본 흐름(static)을 벗어나, 요소를 특정 위치에 배치하는 CSS 레이아웃 속성을 다루었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,0,0&quot;&gt;relative (상대 위치):&lt;/b&gt; 원래 배치되어야 할 기준점에서 top, left 등의 좌표만큼 이동한다. 주로 absolute 요소의 기준점이 되는 부모 영역을 설정할 때 사용한다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0&quot;&gt;absolute (절대 위치):&lt;/b&gt; 상위 태그 중 static이 아닌 요소(주로 relative)를 기준으로 삼아 특정 좌표에 배치된다. 문서의 기본 흐름에서 빠져나오기 때문에 다른 요소들과 공간이 겹칠 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,2,0&quot;&gt;fixed (고정 위치):&lt;/b&gt; 브라우저 창(Viewport)을 기준으로 위치가 고정되어, 스크롤을 내려도 화면의 지정된 자리에 머문다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,3,0&quot;&gt;z-index (레이어 깊이):&lt;/b&gt; 위치 속성으로 인해 요소들이 겹칠 때, 화면에 보여지는 Z축 순서를 결정한다. 숫자가 클수록 상단에 노출된다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>WebStudy</category>
      <category>WEB</category>
      <author>ki-sd</author>
      <guid isPermaLink="true">https://ki-sd.tistory.com/56</guid>
      <comments>https://ki-sd.tistory.com/56#entry56comment</comments>
      <pubDate>Mon, 18 May 2026 20:24:40 +0900</pubDate>
    </item>
    <item>
      <title>[2026-05-15] JSP 게시판(BBS) 완성과 완전한 CRUD 아키텍처 구현</title>
      <link>https://ki-sd.tistory.com/55</link>
      <description>&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;오늘은 사용자가 직접 데이터를 생성(Create), 수정(Update), 삭제(Delete)하는 게시판 시스템을 처음부터 끝까지 구현해 냈다. 웹 애플리케이션의 핵심인 &lt;b data-index-in-node=&quot;165&quot; data-path-to-node=&quot;3&quot;&gt;CRUD 아키텍처&lt;/b&gt;와 화면 이동(Redirection)의 메커니즘을 완벽히 이해한 뜻깊은 시간이었다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;1. 처리용 페이지(Process Page)의 도입과 화면 이동 로직&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;보이지 않는 백엔드 로직 (_ok.jsp):&lt;/b&gt; 사용자가 boardInsert.jsp에서 폼(Form)을 작성해 전송하면, 이를 직접 화면에 그리지 않고 insert_ok.jsp라는 중간 처리용 페이지가 데이터를 받는다. 이 페이지는 자바 로직(DAO 호출)만을 순식간에 수행한 뒤 브라우저에게 &quot;목록 페이지로 가라&quot;고 지시한다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;response.sendRedirect():&lt;/b&gt; DB에 INSERT나 UPDATE 작업이 완료된 후, 새로고침으로 인한 데이터 중복 전송을 막기 위해 브라우저의 URL을 강제로 변경하여 다른 페이지(예: boardList.jsp)로 이동시키는 웹 트랜잭션의 필수 흐름을 체득했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;2. 데이터 무결성과 비밀번호 기반의 권한 검증 (보안)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;UPDATE / DELETE 검증 로직:&lt;/b&gt; 게시글을 수정하거나 삭제할 때 가장 중요한 것은 '작성자 본인인가?'를 확인하는 것이다. update_ok.jsp와 delete_ok.jsp에서는 클라이언트가 입력한 비밀번호와 DB에 저장된 비밀번호를 먼저 비교한다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;성공과 실패의 분기 처리:&lt;/b&gt; 비밀번호가 일치하여 DAO 로직이 true를 반환하면 수정/삭제 후 목록이나 상세보기로 sendRedirect 시킨다. 만약 틀렸다면 자바스크립트의 alert()으로 경고창을 띄우고 history.back()을 호출하여 이전 화면으로 되돌려 보내는 직관적인 예외 처리 흐름을 구현했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;3. 디테일한 UI/UX 제어 (프론트엔드 연동 기법)&lt;/b&gt; 백엔드 로직이 탄탄해진 만큼, 사용자가 마주하는 프론트엔드의 디테일도 여러 기법을 통해 끌어올렸다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;pre-wrap을 통한 텍스트 보존:&lt;/b&gt; 게시글 작성 시 textarea에서 입력한 엔터(줄바꿈)나 공백은 일반 HTML에 출력하면 모두 한 줄로 무시된다. 이를 해결하기 위해 상세보기(boardDetail.jsp)의 내용 출력 영역에 CSS white-space: pre-wrap; 속성을 부여하여 사용자가 작성한 형태 그대로(있는 그대로) 렌더링되도록 처리했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,0&quot;&gt;자동 크기 조절 텍스트박스:&lt;/b&gt; 게시판 수정 폼(boardUpdate.jsp)에서 내용이 길 경우 스크롤바가 생기는 답답함을 없애기 위해, oninput 이벤트 리스너와 this.scrollHeight를 활용하여 글자 양에 따라 textarea의 높이가 동적으로 늘어나는 자바스크립트 DOM 제어 기법을 적용했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,0&quot;&gt;새 글 아이콘([NEW]) 동적 출력:&lt;/b&gt; 자바의 SimpleDateFormat을 활용해 오늘 날짜(new Date())를 구한 뒤, 게시글의 작성일(dbday)과 문자열을 비교하여 일치할 경우에만 뱃지 이미지(new.gif)를 조건부로 렌더링하는 실무적인 로직을 구현했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10&quot;&gt;4. 서버 사이드 페이징의 수학적 완성&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전체 게시글 수(rowCount)를 가져와 10으로 나눈 뒤 소수점을 올림(Math.ceil) 처리하여 총 페이지 수(totalPage)를 구하는 수학적 연산을 적용했다.&lt;/li&gt;
&lt;li&gt;특히 게시물 리스트 번호(count)를 DB의 PK(No)가 아닌 연산된 가상 번호로 내림차순 부여(rowCount - ((curPage-1) * offsetCount))하여, 중간에 게시물이 삭제되더라도 화면의 글 번호가 이빨 빠진 것처럼 보이지 않고 깔끔하게 이어지도록 출력 로직을 최적화했다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>WebStudy</category>
      <category>WEB</category>
      <author>ki-sd</author>
      <guid isPermaLink="true">https://ki-sd.tistory.com/55</guid>
      <comments>https://ki-sd.tistory.com/55#entry55comment</comments>
      <pubDate>Fri, 15 May 2026 20:45:19 +0900</pubDate>
    </item>
    <item>
      <title>[2026-05-14] JSP 검색/목록 시스템 고도화와 CSS 가시성 및 글자 속성 심화</title>
      <link>https://ki-sd.tistory.com/54</link>
      <description>&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 사용자가 입력한 조건에 따라 데이터를 동적으로 추출하는 &lt;b data-index-in-node=&quot;35&quot; data-path-to-node=&quot;3&quot;&gt;JSP 검색 시스템&lt;/b&gt;의 완성도를 높이고, 웹 페이지의 시각적 완성도를 결정짓는 &lt;b data-index-in-node=&quot;78&quot; data-path-to-node=&quot;3&quot;&gt;CSS 가시성(Visibility)&lt;/b&gt; 및 &lt;b data-index-in-node=&quot;100&quot; data-path-to-node=&quot;3&quot;&gt;타이포그래피(Typography)&lt;/b&gt; 속성들을 심도 있게 해부했다. 데이터의 흐름(Data Flow)과 화면의 표현(Presentation)이 어떻게 유기적으로 연결되는지 그 메커니즘을 확립한 시간이었다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;1. JSP Form 데이터 처리와 동적 검색 로직 (DAO/VO)&lt;/b&gt; 사용자가 선택한 검색 조건(업체명, 주소, 음식종류)과 검색어를 서버로 전송하고 처리하는 전체 프로세스를 구축했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;Form 데이터 수신 (find.jsp):&lt;/b&gt; 클라이언트가 &amp;lt;form&amp;gt; 태그를 통해 전송한 col(검색 컬럼)과 fd(검색어)를 request.getParameter()로 수신했다. 웹의 모든 데이터는 문자열(String)로 수신되므로, 페이지 번호 등은 반드시 적절한 형변환 과정이 필요함을 재확인했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;동적 SQL 설계 (FoodDAO):&lt;/b&gt; PreparedStatement는 값(?)은 바인딩할 수 있지만, 컬럼명이나 테이블명은 바인딩할 수 없다는 제약이 있다. 이를 해결하기 위해 WHERE &quot; + col + &quot; LIKE '%'||?||'%'와 같이 컬럼명은 문자열 결합으로, 검색어는 바인딩 변수로 처리하여 SQL 인젝션을 방지하면서도 유연한 동적 쿼리를 완성했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,0&quot;&gt;검색 페이징 알고리즘:&lt;/b&gt; 검색 결과에서도 페이징이 유지되어야 하므로, 전체 검색 결과 건수를 구하는 findTotalPage(col, fd) 메서드를 추가로 구현하여 사용자 경험(UX)을 최적화했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;2. CSS 가시성(Visibility) 제어의 3단계 차이점 분석&lt;/b&gt; 요소를 화면에서 숨기는 세 가지 방법의 기술적 차이와 그에 따른 레이아웃의 변화를 정밀하게 분석했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;display: none;:&lt;/b&gt; 요소를 화면에서 완전히 제거한다. 물리적인 점유 공간조차 사라지므로 뒤에 오는 요소들이 그 자리를 메우게 된다. '더보기' 버튼 클릭 전 내용을 감춰둘 때 주로 사용된다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;visibility: hidden;:&lt;/b&gt; 요소가 보이지는 않지만, 원래 차지하던 공간은 그대로 유지한다. 화면에 빈 구멍이 뚫린 듯한 효과를 주며, 레이아웃의 틀을 깨지 않고 특정 요소만 일시적으로 가릴 때 유용하다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,2,0&quot;&gt;opacity: 0.0;:&lt;/b&gt; 요소를 투명하게 만든다. 공간도 차지하고, 눈에 보이지 않지만 클릭과 같은 이벤트(Event)를 여전히 수신할 수 있다는 결정적 차이가 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;3. 레이아웃 최적화를 위한 Overflow 및 Z-Index 전략&lt;/b&gt; 요소가 지정된 영역을 벗어나거나 겹칠 때 발생하는 문제를 제어하는 고급 레이아웃 속성을 학습했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;overflow 속성:&lt;/b&gt; * hidden: 영역을 벗어나는 콘텐츠를 잘라낸다. 깔끔한 카드 UI 제작 시 필수적이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;scroll / auto: 콘텐츠가 넘칠 경우 스크롤바를 생성하여 영역 내에서 모든 내용을 확인할 수 있게 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,0&quot;&gt;z-index (레이어 우선순위):&lt;/b&gt; HTML 소스 순서와 상관없이 요소의 수직적인 깊이를 제어한다. 팝업창이나 내비게이션 바가 다른 콘텐츠 위로 떠오르게 만드는 핵심 원리이며, 반드시 position 속성이 동반되어야 함을 이해했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10&quot;&gt;4. 사용자 경험을 위한 글자 속성(Typography) 규격&lt;/b&gt; 데이터를 가독성 있게 전달하기 위한 텍스트 스타일링 가이드를 정리했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,0,0&quot;&gt;font-family:&lt;/b&gt; 시스템 폰트와 구글 폰트를 결합하여 폰트가 없는 환경에서도 대체 폰트가 작동하도록 우선순위를 부여했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0&quot;&gt;line-height와 letter-spacing:&lt;/b&gt; 줄 간격과 자간을 조절하여 장문의 텍스트 데이터(CLOB 등)가 브라우저에서 빽빽해 보이지 않도록 시각적 여유를 부여하는 기법을 실습했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,2,0&quot;&gt;text-overflow: ellipsis;:&lt;/b&gt; 목록 화면에서 제목이 너무 길 경우 영역을 깨뜨리지 않고 말줄임표(...)로 자동 변환해 주는 실무적 디테일을 적용했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;12&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12&quot;&gt;5. (Light) 비동기 통신(Ajax)과 데이터 요청의 기초&lt;/b&gt; 영화 순위 데이터를 실시간으로 가져오는 실습을 통해 프론트엔드 비동기 통신의 기초를 맛보았다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;13&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,0,0&quot;&gt;$.ajax():&lt;/b&gt; 페이지 전체를 새로고침하지 않고, 자바 서버(result.jsp)에 특정 데이터를 요청하여 결과값(JSON 등)을 받아오는 비동기 통신의 흐름을 파악했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,1,0&quot;&gt;MovieManager 연동:&lt;/b&gt; 자바에서 외부 사이트의 데이터를 긁어와(Parsing) 다시 JSP로 전달하는 백엔드 매니저 클래스의 역할을 확인하며, 향후 배울 비동기 웹 서비스의 큰 그림을 그리는 계기가 되었다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>WebStudy</category>
      <category>WEB</category>
      <author>ki-sd</author>
      <guid isPermaLink="true">https://ki-sd.tistory.com/54</guid>
      <comments>https://ki-sd.tistory.com/54#entry54comment</comments>
      <pubDate>Fri, 15 May 2026 19:44:18 +0900</pubDate>
    </item>
    <item>
      <title>[2026-05-13] JSP 동적 웹 페이지 구현과 카카오맵 API(Geocoder) 실전 연동</title>
      <link>https://ki-sd.tistory.com/53</link>
      <description>&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 그동안 단편적으로 학습해 온 자바 백엔드 로직(JDBC, DAO/VO)과 프론트엔드 화면(HTML/CSS)을 하나로 결합하는 JSP(JavaServer Pages)의 진수를 경험했다. 맛집 리스트를 페이징하여 출력하고, 특정 맛집 클릭 시 DB에 저장된 주소를 기반으로 동적 지도를 렌더링하는 풀스택(Full-stack) 웹 애플리케이션의 핵심 워크플로우를 완성했다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;1. DAO/VO 아키텍처와 서버 사이드 페이징 최적화&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;데이터 캡슐화 (FoodVO):&lt;/b&gt; 오라클 테이블 스키마에 맞춰 맛집 번호(fno), 이름, 평점, 주소, 이미지 경로 등 10여 개의 속성을 묶어내는 Value Object를 설계했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;페이징 쿼리 (FoodDAO):&lt;/b&gt; 전체 데이터를 한 번에 가져오면 서버 메모리와 네트워크에 치명적인 부하를 준다. 오라클 12c 문법인 OFFSET ? ROWS FETCH NEXT 12 ROWS ONLY를 활용하여, 한 페이지당 정확히 12개의 레코드만 잘라서 가져오는 효율적인 페이징 로직을 구현했다. 총 페이지 수 역시 CEIL(COUNT(*)/12.0) 쿼리로 DB 단에서 연산하여 가져오도록 최적화했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;2. JSP 스크립틀릿과 Bootstrap을 활용한 동적 그리드 렌더링&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;데이터 수신 (list.jsp):&lt;/b&gt; 클라이언트가 URL을 통해 넘긴 페이지 번호를 request.getParameter(&quot;page&quot;)로 수신했다. 처음 접속해 파라미터가 null인 경우 &quot;1&quot;페이지로 강제 매핑하는 방어 코드를 작성한 뒤, DAO를 호출해 List&amp;lt;FoodVO&amp;gt; 객체를 메모리에 적재했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;블록 페이징 알고리즘:&lt;/b&gt; 단순히 [이전/다음]을 넘어, 1~10페이지 묶음으로 이동하는 하단 페이징 네비게이션을 위해 수학적 연산(startPage, endPage)을 도입했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,2,0&quot;&gt;UI 렌더링:&lt;/b&gt; 순수 HTML 대신 Bootstrap 3 프레임워크의 col-md-3 그리드 시스템과 thumbnail 클래스를 적용해 1줄에 4개씩 카드가 배치되는 반응형 UI를 구축했다. 특히, CSS의 text-overflow: ellipsis와 white-space: nowrap 속성을 활용해 맛집 이름이 너무 길 경우 텍스트를 말줄임표(...)로 깔끔하게 자르는 프론트엔드 디테일을 챙겼다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;3. Query String 기반의 화면 이동과 상세 정보 출력&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;목록 화면(list.jsp)에서 특정 맛집 이미지를 클릭하면 &amp;lt;a href=&quot;detail.jsp?fno=&amp;lt;%=vo.getFno()%&amp;gt;&quot;&amp;gt; 태그를 통해 맛집의 고유 식별자(PK)인 fno를 Query String 방식으로 상세 페이지에 전달했다.&lt;/li&gt;
&lt;li&gt;detail.jsp는 이 번호를 받아 dao.foodDetailData(fno)를 호출해 단 1건의 데이터를 가져오고, HTML &amp;lt;table&amp;gt; 구조의 rowspan과 colspan을 적절히 혼합하여 맛집 포스터, 평점, 테마, 영업시간 등을 직관적인 UI로 뿌려주는 화면 간 데이터 흐름을 완성했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10&quot;&gt;4. 외부 오픈 API 연동: 카카오맵 Geocoder 시스템&lt;/b&gt; 가장 인상 깊었던 핵심 비즈니스 로직이다. 웹 서비스의 가치를 높이기 위해 외부 데이터를 내 시스템으로 끌어오는 API 연동을 실습했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;카카오 개발자 센터에서 AppKey를 발급받아 자바스크립트 라이브러리를 로드했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0&quot;&gt;동적 좌표 변환:&lt;/b&gt; 단순히 고정된 지도를 띄우는 것이 아니라, 자바스크립트 코드 내부에 &amp;lt;%=vo.getAddress() %&amp;gt;라는 JSP 출력식을 삽입했다. DB에서 가져온 &lt;b data-index-in-node=&quot;96&quot; data-path-to-node=&quot;11,1,0&quot;&gt;실제 텍스트 주소&lt;/b&gt;를 카카오맵의 Geocoder 객체(addressSearch 메서드)로 던져준 것이다.&lt;/li&gt;
&lt;li&gt;API 서버가 이 텍스트 주소를 내부적으로 분석해 위도/경도(LatLng) 좌표로 반환해주고, 결과값을 콜백 함수에서 받아 해당 좌표 위치에 마커(Marker)와 가게 이름이 적힌 인포윈도우(InfoWindow)를 동적으로 렌더링하는 완벽한 위치 기반 서비스 연동을 체득했다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>WebStudy</category>
      <category>WEB</category>
      <author>ki-sd</author>
      <guid isPermaLink="true">https://ki-sd.tistory.com/53</guid>
      <comments>https://ki-sd.tistory.com/53#entry53comment</comments>
      <pubDate>Wed, 13 May 2026 20:16:49 +0900</pubDate>
    </item>
    <item>
      <title>[2026-05-12] CSS 박스 모델 완벽 해부 및 JSP 기반 사원 관리 시스템 연동</title>
      <link>https://ki-sd.tistory.com/51</link>
      <description>&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;웹 디자인의 공간을 지배하는 'CSS 박스 모델(Box Model)'을 해부하고, 이를 기반으로 데이터베이스(오라클)에서 가져온 사원 정보를 웹 화면에 렌더링하는 실전 JSP 연동을 수행했다. 백엔드의 견고한 로직 위에 프론트엔드의 세련된 옷을 입히는 풀스택(Full-stack) 개발의 묘미를 경험한 시간이었다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;1. CSS 박스 모델: 화면 분할과 여백의 미학&lt;/b&gt; 모든 HTML 요소는 네모난 상자(Box)로 이루어져 있으며, 이를 감싸는 3겹의 보호막을 정밀하게 제어하는 기법을 실습했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;Margin (외부 여백):&lt;/b&gt; 요소와 요소 사이의 바깥 간격을 벌린다. 특히 margin: 0px auto;를 통한 화면 가운데 정렬 기법은 모든 웹사이트 레이아웃의 기본 뼈대가 됨을 확인했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;Padding (내부 여백):&lt;/b&gt; 테두리와 내부 콘텐츠(글자, 이미지) 사이의 안쪽 간격이다. 숨을 쉴 수 있는 공간을 주어 UI의 가독성을 높인다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,2,0&quot;&gt;Border (테두리):&lt;/b&gt; 두께, 선의 종류(solid, dotted, dashed, double 등), 색상을 지정한다. 딱딱한 직사각형을 부드러운 타원형으로 깎아내는 border-radius를 활용해 현대적인 웹 디자인의 디테일을 추가했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,3,0&quot;&gt;속기법 (Shorthand):&lt;/b&gt; margin: 10px 20px 30px 20px;처럼 시계 방향(Top, Right, Bottom, Left)으로 한 번에 값을 지정하여 CSS 코드를 최적화하는 작법을 몸에 익혔다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;2. JSP와 JDBC의 만남: 사원 데이터(EMP) 동적 렌더링&lt;/b&gt; 프론트엔드 스타일링을 넘어, 백엔드 데이터를 웹 화면에 출력하는 JSP(JavaServer Pages)의 본질을 다루었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;DAO와 VO의 완벽한 재사용성:&lt;/b&gt; 사원 정보(emp2)와 부서 정보(dept2)를 조인(JOIN)하여 가져오는 복잡한 쿼리를 empDAO에 캡슐화했다. 추출된 데이터는 empVO 객체에 담겨 프론트엔드로 전달된다. 자바 데스크톱(Swing) 환경에서 설계했던 아키텍처가 웹 환경에서도 단 한 줄의 수정 없이 그대로 적용된다는 점에서, 로직을 철저히 분리하는 객체 지향 설계(MVC 패턴의 기초)의 위력을 재확인했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;JSP 스크립틀릿(Scriptlet)의 활용:&lt;/b&gt; HTML 문서 상단 &amp;lt;% %&amp;gt; 영역에서 empDAO를 호출해 List를 받아오고, &amp;lt;tbody&amp;gt; 내부에서 자바의 향상된 for문을 돌려 &amp;lt;tr&amp;gt;과 &amp;lt;td&amp;gt; 태그를 동적으로 무한 생성해 내는 서버 사이드 렌더링을 구현했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;3. CSS와 데이터의 결합 (Data Visualization)&lt;/b&gt; 가져온 사원 목록 테이블에 앞서 배운 박스 모델과 선택자를 전면 적용했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;border-collapse: collapse;로 테이블의 겹치는 선을 깔끔하게 정리하고, 요소에 box-shadow를 주어 표가 화면에서 살짝 떠 있는 듯한 입체감을 부여했다.&lt;/li&gt;
&lt;li&gt;특히 어제 배운 구조 선택자 nth-child(even)을 활용해 표의 짝수 행마다 배경색(#F2F2F2)을 다르게 주어 데이터의 가독성을 극대화하는 '얼룩말 패턴(Zebra-striping)' 디자인을 완성했다. 순수 데이터가 직관적인 UI로 탈바꿈하는 순간이었다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>WebStudy</category>
      <category>WEB</category>
      <author>ki-sd</author>
      <guid isPermaLink="true">https://ki-sd.tistory.com/51</guid>
      <comments>https://ki-sd.tistory.com/51#entry51comment</comments>
      <pubDate>Tue, 12 May 2026 20:12:19 +0900</pubDate>
    </item>
    <item>
      <title>[2026-05-11] CSS의 기초와 다양한 선택자(Selector) 활용 전략</title>
      <link>https://ki-sd.tistory.com/50</link>
      <description>&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;웹 디자인의 표준인 CSS3를 학습하며 스타일 적용의 우선순위 원리와 다양한 선택자 기법을 마스터했다. 단순히 색상을 바꾸는 것을 넘어, HTML 문서의 계층 구조를 이해하고 특정 조건에 맞는 요소를 정밀하게 제어하는 능력을 길렀다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;1. CSS 개요 및 스타일 적용 방식과 우선순위 (Cascading)&lt;/b&gt; CSS는 '계단식'이라는 의미처럼 우선순위 규칙에 따라 스타일이 덮어씌워진다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,0&quot;&gt;스타일 적용 방식:&lt;/b&gt; * &lt;b data-index-in-node=&quot;13&quot; data-path-to-node=&quot;5,0,0&quot;&gt;내부 CSS:&lt;/b&gt; &amp;lt;head&amp;gt; 내부에 &amp;lt;style&amp;gt; 태그로 작성. 파일 하나를 제어할 때 사용한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,1,0,0&quot;&gt;인라인 CSS:&lt;/b&gt; 태그 내부에 style 속성으로 직접 작성. 우선순위가 매우 높지만 유지보수가 어렵다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,0,1,1,0&quot;&gt;외부 CSS:&lt;/b&gt; 별도의 .css 파일을 생성하여 &amp;lt;link&amp;gt;로 연결. 실무에서 가장 많이 쓰이며 공통 디자인 관리에 유리하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;5,1,0&quot;&gt;우선순위 (Cascading Order):&lt;/b&gt; * 전체(*) &amp;lt; 태그 &amp;lt; 클래스(.) &amp;lt; 아이디(#) &amp;lt; 인라인 &amp;lt; !important 순으로 적용된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동일한 선택자일 경우, 나중에 작성된 설정이 이전 설정을 덮어쓴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;2. 기본 선택자 (Tag, ID, Class)&lt;/b&gt; 가장 빈번하게 사용되는 요소 구분자들을 실습했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;태그 선택자:&lt;/b&gt; 해당 태그를 사용하는 모든 요소에 적용. 전체적인 레이아웃이나 기본 폰트 설정에 적합하다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;ID 선택자 (#):&lt;/b&gt; 중복 없는 고유한 구분자. 특정 파일 내에서 단 한 번만 존재하는 핵심 레이아웃(헤더, 사이드바 등) 디자인에 사용한다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,2,0&quot;&gt;클래스 선택자 (.):&lt;/b&gt; 여러 태그에 중복 적용 가능한 구분자. 동일한 디자인 테마를 가진 여러 버튼이나 목록 아이템에 활용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;3. 속성 선택자 (Attribute Selector)&lt;/b&gt; 태그의 ID나 Class가 아닌, 특정 속성값의 상태에 따라 스타일을 부여하는 정밀한 제어 기법이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[속성=값]: 속성값이 정확히 일치할 때.&lt;/li&gt;
&lt;li&gt;[속성^=값]: 특정 문자열로 시작할 때 (예: http로 시작하는 링크 추출).&lt;/li&gt;
&lt;li&gt;[속성$=값]: 특정 문자열로 끝날 때 (예: .net으로 끝나는 메일 주소).&lt;/li&gt;
&lt;li&gt;[속성*=값]: 특정 문자열을 포함할 때 (예: www를 포함하는 URL).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10&quot;&gt;4. 복합 선택자: 자손, 후손, 동위 선택자&lt;/b&gt; HTML 문서의 트리(Tree) 구조를 탐색하여 부모-자식 관계에 기반한 스타일을 적용했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,0,0&quot;&gt;자손 선택자 (&amp;gt;):&lt;/b&gt; 부모 태그의 바로 아래 단계인 자식 요소만 선택한다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0&quot;&gt;후손 선택자 (공백):&lt;/b&gt; 부모 태그 내부에 포함된 모든 하위 요소를 깊이에 상관없이 선택한다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,2,0&quot;&gt;동위 선택자 (+, ~):&lt;/b&gt; 같은 부모를 둔 형제 요소 중 바로 뒤에 오는 요소(+)나 모든 형제 요소(~)를 선택한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;12&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;12&quot;&gt;5. 반응 선택자 및 인터랙티브 UI (Pseudo-classes)&lt;/b&gt; 사용자의 동작에 반응하여 실시간으로 디자인을 변경하는 동적 스타일을 실습했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;13&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,0,0&quot;&gt;:hover:&lt;/b&gt; 마우스를 올렸을 때의 변화를 제어한다. 이미지의 투명도(opacity) 조절, 커서 모양 변경(cursor: pointer), 테이블 행(tr)의 배경색 강조 등 실무 UI 제작에 필수적이다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;13,1,0&quot;&gt;텍스트 제어:&lt;/b&gt; text-decoration: none을 통해 링크(&amp;lt;a&amp;gt;)의 기본 밑줄을 제거하고, 마우스 오버 시에만 강조하는 등 가독성 중심의 디자인을 적용했다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>WebStudy</category>
      <category>WEB</category>
      <author>ki-sd</author>
      <guid isPermaLink="true">https://ki-sd.tistory.com/50</guid>
      <comments>https://ki-sd.tistory.com/50#entry50comment</comments>
      <pubDate>Mon, 11 May 2026 19:42:58 +0900</pubDate>
    </item>
    <item>
      <title>[2026-05-08] HTML5 레이아웃 설계와 사용자 입력(Form), JQuery 연동 기초</title>
      <link>https://ki-sd.tistory.com/49</link>
      <description>&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;여러 개의 텍스트와 데이터를 정돈하는 구조적 마크업 기술과, 클라이언트가 서버로 데이터를 전송하기 위한 필수 인터페이스인 &lt;b data-index-in-node=&quot;105&quot; data-path-to-node=&quot;3&quot;&gt;폼(Form)&lt;/b&gt; 관련 태그들을 집중적으로 학습했다. 백엔드에서 처리할 데이터를 어떻게 화면에서 입력받고 제어하는지 그 연결 고리를 이해하는 핵심적인 시간이었다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;4&quot;&gt;1. 리스트와 테이블(Table) 태그의 논리적 활용&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비순서형(&amp;lt;ul&amp;gt;), 순서형(&amp;lt;ol&amp;gt;), 정의형(&amp;lt;dl&amp;gt;) 목록을 구분하여 데이터의 성격에 맞게 리스트를 구성했다.&lt;/li&gt;
&lt;li&gt;DB에서 넘어온 2차원 데이터를 표현하기 위해 &amp;lt;thead&amp;gt;, &amp;lt;tbody&amp;gt;, &amp;lt;tfoot&amp;gt;으로 구역을 나누고, colspan과 rowspan 속성을 통해 셀을 병합하여 맛집이나 영화 상세 페이지처럼 복합적인 레이아웃을 &amp;lt;table&amp;gt;로 설계하는 기법을 마스터했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;6&quot;&gt;2. Form 엘리먼트와 입력 폼의 세분화&lt;/b&gt; 클라이언트가 입력한 값을 JSP(Java) 서버로 보내기 위해 다양한 &amp;lt;input&amp;gt; 속성을 다루었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;7&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,0,0&quot;&gt;텍스트 입력:&lt;/b&gt; type=&quot;text&quot;, type=&quot;password&quot;, 긴 문장을 위한 &amp;lt;textarea&amp;gt;를 활용했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,1,0&quot;&gt;버튼 제어:&lt;/b&gt; JavaScript로 동작을 제어하는 일반 버튼(type=&quot;button&quot;), 폼 데이터를 서버로 쏘아 보내는 전송 버튼(type=&quot;submit&quot;), 리셋 버튼(type=&quot;reset&quot;)의 용도를 정확히 구분했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,2,0&quot;&gt;다양한 입력 타입 (HTML5):&lt;/b&gt; 스피너(type=&quot;number&quot;), 슬라이더(type=&quot;range&quot;), 달력(type=&quot;date&quot;), 파일 업로드(type=&quot;file&quot;) 등, 과거 자바스크립트로 복잡하게 구현해야 했던 기능들을 속성 하나로 해결하는 최신 규격을 확인했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,3,0&quot;&gt;선택형 입력:&lt;/b&gt; 단일 선택을 위한 라디오 버튼(type=&quot;radio&quot;, name 속성을 동일하게 주어 그룹화), 다중 선택을 위한 체크박스(type=&quot;checkbox&quot;), 그리고 드롭다운 목록을 만드는 &amp;lt;select&amp;gt;와 &amp;lt;option&amp;gt; 태그를 실습했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;7,4,0&quot;&gt;숨김 필드:&lt;/b&gt; 화면에는 보이지 않지만 서버로 반드시 넘겨야 하는 식별자(PK 등)를 담는 type=&quot;hidden&quot;의 실무적 중요성을 파악했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;8&quot;&gt;3. 웹 접근성을 고려한 의미론적 입력창 (fieldset, legend, label)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단순히 &amp;lt;input&amp;gt; 태그만 나열하는 것을 넘어, 관련된 입력 요소들(예: 배송 정보, 회원 정보)을 시각적, 논리적으로 그룹화하는 &amp;lt;fieldset&amp;gt; 태그와 그 그룹의 제목을 다는 &amp;lt;legend&amp;gt; 태그를 사용했다.&lt;/li&gt;
&lt;li&gt;특히, &amp;lt;label for=&quot;id&quot;&amp;gt;와 &amp;lt;input id=&quot;id&quot;&amp;gt;를 매핑하여, 사용자가 입력창이 아닌 글자(Label)만 클릭해도 포커스가 이동하도록 하는 웹 접근성(A11y) 향상 기법을 체득했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;10&quot;&gt;4. 카카오맵 API 연동과 JQuery를 이용한 동적 검색 기초&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;11&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,0,0&quot;&gt;외부 API 연동:&lt;/b&gt; &amp;lt;script&amp;gt; 태그를 통해 카카오맵 API를 로드하고, Geocoder를 이용해 주소 텍스트를 위경도 좌표로 변환하여 지도에 마커를 찍는 실전 예제를 구현했다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;11,1,0&quot;&gt;JQuery 동적 검색:&lt;/b&gt; window.onload 대신 JQuery의 $(function(){})을 사용하여 DOM 요소를 제어했다. 입력창($('#keyboard'))에 keyup 이벤트 리스너를 달아, 사용자가 검색어를 입력할 때마다 테이블의 행(&amp;lt;tr&amp;gt;)을 실시간으로 숨기거나(hide()) 보여주는(show()) 동적 클라이언트 검색 로직을 경험했다. 이는 향후 React나 Vue 등 최신 프론트엔드 프레임워크 학습의 훌륭한 밑거름이 될 것이다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>WebStudy</category>
      <category>WEB</category>
      <author>ki-sd</author>
      <guid isPermaLink="true">https://ki-sd.tistory.com/49</guid>
      <comments>https://ki-sd.tistory.com/49#entry49comment</comments>
      <pubDate>Fri, 8 May 2026 19:20:44 +0900</pubDate>
    </item>
  </channel>
</rss>