๐โ์ง๋์จ ๊ธฐ๋ฐ ์ฝํ ์ธ ๋ทฐ, ๋จ์ํ ๋ชฉ๋ก ๊ทธ ์ด์์ ์ค๊ณํ๋คโ
๐ 2025๋ 4์ 30์ผ | โ๏ธ by ๋ฐ์ฐฌํฌ |
๐งญ ๊ธฐํ์ ์์: โ๋จ์ ๋ฆฌ์คํธโ๋ฅผ ๋์ด, ์ฌ์ฉ์ ๋ง์ถค ์ฝํ ์ธ ๋ฅผ ๋ณด์ฌ์ฃผ๋ ค๋ฉด
๊ฐ์ ํ๋ซํผ์์ โ์๊ฐ ์ค์ธ ๊ฐ์ ํ์ด์งโ๋ ๋จ์ํ ์ฝํ ์ธ ๋ฆฌ์คํธ๋ก ๋๋์ ์ ๋๋ค.
๋ก๊ทธ์ธํ ์ฌ์ฉ์๋ผ๋ฉด ์ง๋์จ์ด, ๋น๋ก๊ทธ์ธ ์ฌ์ฉ์๋ผ๋ฉด ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ ๋ณด๋ง ๋ณด์ด๋๋ก ๊ตฌ์ฑํด์ผ,
ํ์ต ๋๊ธฐ ๋ถ์ฌ์ ์ ๊ทผ ํ๋ฆ ์ ์ด๊ฐ ๋์์ ๊ฐ๋ฅํด์ง๋ค.
์ด๋ฒ ๊ตฌํ์ ์ด ์ฒ ํ์์ ์ถ๋ฐํ๋ค.
์๊ตฌ์ฌํญ | ๊ตฌํ ๋ฐฉํฅ |
---|---|
โ ๊ฐ์ ๋ฉํ ์ ๋ณด ์กฐํ | ๊ฐ์๋ช , ๊ฐ์ฌ๋ช , ์๊ฐ, ์ธ๋ค์ผ ๋ฑ์ ์๋จ์ ํ์ |
โ ์ฝํ ์ธ ๋ฆฌ์คํธ ์ถ๋ ฅ | ์ฑํฐ ๋จ์์ ์ฝํ ์ธ ๋ฆฌ์คํธ |
โ ์ฌ์ฉ์ ์ง๋์จ ๋ฐ์ | ๋ก๊ทธ์ธ ์ฌ์ฉ์์ ์๊ฐ ์๋ฃ ์ฌ๋ถ ๋ฐ์ |
โ ๋น๋ก๊ทธ์ธ ๋์ | ๋ก๊ทธ์ธ ์์ด๋ ์ฝํ ์ธ ์ด๋ฆ์ ์ด๋ ๊ฐ๋ฅํ์ง๋ง ์ง๋๋ ์จ๊น ์ฒ๋ฆฌ |
๐งฉ ๊ตฌ์กฐ ์ค๊ณ: Controller โ Service โ DAO โ Mapper ํ๋ฆ
[LecturePlayController]
โ
[LecturePlayService]
โ
[LecturePlayDAO (MyBatis)]
โ
[Mapper XML: LectureMapper.xml]
Controller
: ์์ฒญ ํ์ฑ, ๋ก๊ทธ์ธ ์ธ์ ํ๋ณ, JSP ์ ๋ฌService
: ๋ก์ง ๋ถ๊ธฐ (์ง๋ ๋ฐ์ ์ฌ๋ถ ๋ฑ)DAO
: ์ค์ SQL ์คํMapper
: SQL ์ถ์ํ
๐ก ์ฃผ์ ํด๋์ค ์ญํ
ํด๋์ค๋ช | ์ค๋ช |
---|---|
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>
- ์ง๋ ์ ๋ณด๋ฅผ
LEFT JOIN
์ผ๋ก ํ ๋ฒ์ ๊ฐ์ ธ์ ํผํฌ๋จผ์ค ๊ฐ์ ContentDTO
์boolean completed
ํ๋๋ก ๋งคํ
๐ฌ ๋ฉด์ ํฌ์ธํธ ์์ฝ
ํญ๋ชฉ | ํต์ฌ ๋ฉ์์ง |
---|---|
โ MVC ๋ถ๋ฆฌ | Controller๋ ํ๋ฆ๋ง, ๋ก์ง์ Service, SQL์ DAO |
โ ํผ์ค๋๋ผ์ด์ง UI | ์ง๋์จ ๊ธฐ๋ฐ ์ฝํ ์ธ ๋ ๋๋ง |
โ ์ธ์ ์ธ์ฆ ํ๋ฆ | JSP์์ ์ง์ ์ธ์ฆํ์ง ์๊ณ Controller ๋จ์์ ๋ถ๊ธฐ |
โ ๋ฆฌ์์ค ๊ด๋ฆฌ | SqlSession โ try-with-resources ๊ตฌ์กฐ |
โ ํ ์คํธ ์๋๋ฆฌ์ค ์๋น | ์ ์ ์ํ๋ณ ๋ทฐ ์ฐจ์ด ๊ฒ์ฆ ๊ฐ๋ฅ |
โ ํ๊ณ & ํ์ฅ ๋ฐฉํฅ
โ์ด ํ์ด์ง๋ ๋จ์ํ โ์ฝํ ์ธ ๋ฆฌ์คํธโ๊ฐ ์๋๋ผ,
์ฌ์ฉ์ ํ๋์ ๋ฐ์ํ ๊ฐ์ธํ๋ ํ์ต ๋ทฐ์ ์ฒซ๊ฑธ์์ด์๋ค.โ
์ด๋ฒ ์ค๊ณ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ ํ์ฅ์ด ๊ฐ๋ฅํ๋ค:
- ๐ ์ง๋์จ์ ๋ฐ๋ผ ์ถ์ฒ ๊ฐ์ ๋ ธ์ถ
- ๐ ์ ์ฒด ์๊ฐ ์๋ฃ ์ ์๋์ผ๋ก ์ธ์ฆ์ ๋ฐ๊ธ
- ๐ ๊ด๋ฆฌ์ ๋์๋ณด๋์์ ์ ์ ๋ณ ํ์ต ํต๊ณ ์ ๊ณต
โ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ๋ณด์ฌ์ฃผ๋๋๋ UX๊ฐ ์๋๋ผ โ์์คํ ์ํคํ ์ฒ์ ๋ฌธ์ โ์๋ค.โ
โ ๋ก๊ทธ์ธ ์ฌ๋ถ๋ถํฐ SQL ์กฐ์ธ ๊ตฌ์กฐ๊น์ง, ์ง์ง ๊ณ ๋ฏผ์ด ๋ด๊ธด ํผ์ค๋๋ผ์ด์ง ์ค๊ณ.