๐Ÿ“Œโ€œ์ง„๋„์œจ ๊ธฐ๋ฐ˜ ์ฝ˜ํ…์ธ  ๋ทฐ, ๋‹จ์ˆœํ•œ ๋ชฉ๋ก ๊ทธ ์ด์ƒ์„ ์„ค๊ณ„ํ•˜๋‹คโ€

๐Ÿ—“ 2025๋…„ 4์›” 30์ผ โœ๏ธ by ๋ฐ•์ฐฌํฌ

๐Ÿงญ ๊ธฐํš์˜ ์‹œ์ž‘: โ€˜๋‹จ์ˆœ ๋ฆฌ์ŠคํŠธโ€™๋ฅผ ๋„˜์–ด, ์‚ฌ์šฉ์ž ๋งž์ถค ์ฝ˜ํ…์ธ ๋ฅผ ๋ณด์—ฌ์ฃผ๋ ค๋ฉด

๊ฐ•์˜ ํ”Œ๋žซํผ์—์„œ โ€œ์ˆ˜๊ฐ• ์ค‘์ธ ๊ฐ•์˜ ํŽ˜์ด์ง€โ€๋Š” ๋‹จ์ˆœํ•œ ์ฝ˜ํ…์ธ  ๋ฆฌ์ŠคํŠธ๋กœ ๋๋‚˜์„  ์•ˆ ๋œ๋‹ค.

๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๋ผ๋ฉด ์ง„๋„์œจ์ด, ๋น„๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž๋ผ๋ฉด ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ •๋ณด๋งŒ ๋ณด์ด๋„๋ก ๊ตฌ์„ฑํ•ด์•ผ,

ํ•™์Šต ๋™๊ธฐ ๋ถ€์—ฌ์™€ ์ ‘๊ทผ ํ๋ฆ„ ์ œ์–ด๊ฐ€ ๋™์‹œ์— ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

์ด๋ฒˆ ๊ตฌํ˜„์€ ์ด ์ฒ ํ•™์—์„œ ์ถœ๋ฐœํ–ˆ๋‹ค.

์š”๊ตฌ์‚ฌํ•ญ ๊ตฌํ˜„ ๋ฐฉํ–ฅ
โœ… ๊ฐ•์˜ ๋ฉ”ํƒ€ ์ •๋ณด ์กฐํšŒ ๊ฐ•์˜๋ช…, ๊ฐ•์‚ฌ๋ช…, ์†Œ๊ฐœ, ์ธ๋„ค์ผ ๋“ฑ์„ ์ƒ๋‹จ์— ํ‘œ์‹œ
โœ… ์ฝ˜ํ…์ธ  ๋ฆฌ์ŠคํŠธ ์ถœ๋ ฅ ์ฑ•ํ„ฐ ๋‹จ์œ„์˜ ์ฝ˜ํ…์ธ  ๋ฆฌ์ŠคํŠธ
โœ… ์‚ฌ์šฉ์ž ์ง„๋„์œจ ๋ฐ˜์˜ ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž์˜ ์ˆ˜๊ฐ• ์™„๋ฃŒ ์—ฌ๋ถ€ ๋ฐ˜์˜
โœ… ๋น„๋กœ๊ทธ์ธ ๋Œ€์‘ ๋กœ๊ทธ์ธ ์—†์ด๋„ ์ฝ˜ํ…์ธ  ์ด๋ฆ„์€ ์—ด๋žŒ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ง„๋„๋Š” ์ˆจ๊น€ ์ฒ˜๋ฆฌ

๐Ÿงฉ ๊ตฌ์กฐ ์„ค๊ณ„: Controller โ†’ Service โ†’ DAO โ†’ Mapper ํ๋ฆ„

[LecturePlayController]
      โ†“
[LecturePlayService]
      โ†“
[LecturePlayDAO (MyBatis)]
      โ†“
[Mapper XML: LectureMapper.xml]

๐Ÿ’ก ์ฃผ์š” ํด๋ž˜์Šค ์—ญํ• 

ํด๋ž˜์Šค๋ช… ์„ค๋ช…
LecturePlayController /lecture/play ์š”์ฒญ ํ•ธ๋“ค๋ง, ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ ํŒ๋‹จ
LecturePlayService ์ง„๋„ ํฌํ•จ/๋ฏธํฌํ•จ ๋กœ์ง ๋ถ„๊ธฐ
LecturePlayDAO ์ฝ˜ํ…์ธ  + ์ง„๋„ ๋ฐ์ดํ„ฐ ์กฐํšŒ SQL ์‹คํ–‰

๐Ÿ”ง ํ•ต์‹ฌ ์ฝ”๋“œ ํ๋ฆ„

1๏ธโƒฃ Controller์—์„œ ์ง„๋„ ๋ถ„๊ธฐ

int lectureId = Integer.parseInt(req.getParameter("lectureId"));
UserDTO user = (UserDTO) req.getSession().getAttribute("user");

List<ContentDTO> contents = (user != null) ?
  dao.selectContentsWithProgress(lectureId, user.getUserId()) :
  dao.selectContentsByLectureId(lectureId);

โ†’ ๋กœ๊ทธ์ธ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋‹ค๋ฅธ DAO ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

โ†’ ์ง„๋„ ํ•„๋“œ(completed or progressRatio) ํฌํ•จ ์—ฌ๋ถ€ ๋ถ„๊ธฐ


2๏ธโƒฃ JSP ์ถœ๋ ฅ: ์ง„๋„ ๋ฑƒ์ง€ ๋ Œ๋”๋ง

<c:forEach var="content" items="${contents}">
  <li>
    ${content.title}
    <c:if test="${content.completed}">
      <span class="badge">โœ” ์ˆ˜๊ฐ•์™„๋ฃŒ</span>
    </c:if>
  </li>
</c:forEach>

๐Ÿง  ์„ค๊ณ„ ๊ณ ์ฐฐ: ์‹ค๋ฌด์ ์ธ ๋ถ„๊ธฐ์™€ ํผํฌ๋จผ์Šค ๋Œ€์‘

ํฌ์ธํŠธ ์„ค๋ช…
๐Ÿ” ์„ธ์…˜ ์ธ์ฆ ์ฒ˜๋ฆฌ HttpSession.getAttribute("user")๋กœ ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ ํŒ๋‹จ
๐Ÿ“ฆ DAO๋Š” try-with-resources ์„ธ์…˜ ์ž๋™ close๋กœ ์ž์› ๋ˆ„์ˆ˜ ๋ฐฉ์ง€
๐Ÿ”„ SQL์€ LEFT JOIN ์ตœ์ ํ™” ์ฝ˜ํ…์ธ  + ์ง„๋„ ํ…Œ์ด๋ธ”์„ ์กฐ์ธํ•˜์—ฌ ํ•œ ๋ฒˆ์— ๊ฐ€์ ธ์˜ด
๐Ÿงฑ Service ๋ถ„๋ฆฌ ์ด์œ  Controller๋Š” ํ๋ฆ„ ์ œ์–ด, ๋น„์ฆˆ๋‹ˆ์Šค ํŒ๋‹จ์€ Service๋กœ ๋ถ„๋ฆฌ
๐ŸŽฏ ๋น„๋กœ๊ทธ์ธ ๊ฒฝ๋Ÿ‰ํ™” ์ง„๋„ ์ฟผ๋ฆฌ๋ฅผ ์™„์ „ํžˆ ๊ฑด๋„ˆ๋œ€ โ†’ DB ๋ถ€ํ•˜ ๊ฐ์†Œ

๐Ÿงช ์ฃผ์š” ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค

ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ๊ธฐ๋Œ€ ๋™์ž‘
๋กœ๊ทธ์ธ ์œ ์ €๊ฐ€ ์ ‘์† ์ฝ˜ํ…์ธ  ๋ฆฌ์ŠคํŠธ + ์ง„๋„ ๋ฑƒ์ง€ ์ถœ๋ ฅ
๋น„๋กœ๊ทธ์ธ ์œ ์ €๊ฐ€ ์ ‘์† ์ฝ˜ํ…์ธ  ์ œ๋ชฉ๋งŒ ์ถœ๋ ฅ, ์ง„๋„ ์ •๋ณด ์ œ์™ธ
์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฐ•์˜ ID 404 ํ˜น์€ ์‚ฌ์šฉ์ž ์•ˆ๋‚ด ๋ฉ”์‹œ์ง€
์ค‘๋ณต ์ฝ˜ํ…์ธ  Mapper SQL์—์„œ DISTINCT ๋˜๋Š” ์ •๋ ฌ ์ฒ˜๋ฆฌ๋กœ ํ•„ํ„ฐ๋ง

๐Ÿงฑ MyBatis Mapper ๊ตฌ์กฐ ์˜ˆ์‹œ

<select id="selectContentsWithProgress" resultMap="ContentMap">
  SELECT c.*, p.is_completed
  FROM content c
  LEFT JOIN progress p ON c.content_id = p.content_id AND p.user_id = #{userId}
  WHERE c.lecture_id = #{lectureId}
  ORDER BY c.order_num
</select>

๐Ÿ’ฌ ๋ฉด์ ‘ ํฌ์ธํŠธ ์š”์•ฝ

ํ•ญ๋ชฉ ํ•ต์‹ฌ ๋ฉ”์‹œ์ง€
โœ… MVC ๋ถ„๋ฆฌ Controller๋Š” ํ๋ฆ„๋งŒ, ๋กœ์ง์€ Service, SQL์€ DAO
โœ… ํผ์Šค๋„๋ผ์ด์ง• UI ์ง„๋„์œจ ๊ธฐ๋ฐ˜ ์ฝ˜ํ…์ธ  ๋ Œ๋”๋ง
โœ… ์„ธ์…˜ ์ธ์ฆ ํ๋ฆ„ JSP์—์„œ ์ง์ ‘ ์ธ์ฆํ•˜์ง€ ์•Š๊ณ  Controller ๋‹จ์—์„œ ๋ถ„๊ธฐ
โœ… ๋ฆฌ์†Œ์Šค ๊ด€๋ฆฌ SqlSession โ†’ try-with-resources ๊ตฌ์กฐ
โœ… ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค ์™„๋น„ ์œ ์ € ์ƒํƒœ๋ณ„ ๋ทฐ ์ฐจ์ด ๊ฒ€์ฆ ๊ฐ€๋Šฅ

โœ… ํšŒ๊ณ  & ํ™•์žฅ ๋ฐฉํ–ฅ

โ€œ์ด ํŽ˜์ด์ง€๋Š” ๋‹จ์ˆœํ•œ โ€˜์ฝ˜ํ…์ธ  ๋ฆฌ์ŠคํŠธโ€™๊ฐ€ ์•„๋‹ˆ๋ผ,

์‚ฌ์šฉ์ž ํ–‰๋™์„ ๋ฐ˜์˜ํ•œ ๊ฐœ์ธํ™”๋œ ํ•™์Šต ๋ทฐ์˜ ์ฒซ๊ฑธ์Œ์ด์—ˆ๋‹ค.โ€

์ด๋ฒˆ ์„ค๊ณ„๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ ํ™•์žฅ์ด ๊ฐ€๋Šฅํ•˜๋‹ค:


โ€œ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๋ณด์—ฌ์ฃผ๋А๋ƒ๋Š” UX๊ฐ€ ์•„๋‹ˆ๋ผ โ€˜์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜์˜ ๋ฌธ์ œโ€™์˜€๋‹ค.โ€

โ€” ๋กœ๊ทธ์ธ ์—ฌ๋ถ€๋ถ€ํ„ฐ SQL ์กฐ์ธ ๊ตฌ์กฐ๊นŒ์ง€, ์ง„์งœ ๊ณ ๋ฏผ์ด ๋‹ด๊ธด ํผ์Šค๋„๋ผ์ด์ง• ์„ค๊ณ„.