들어가면서 ..
프로그래밍을 하다보면 한 번 쯤은 MVC 패턴에 대하여 들어보거나 접해보았을 것이다.
더 나아가 MVVM, MVP 등등 다양한 것이 존재한다고 하는데
가장 기본이되는 MVC에 대해서 알아보려고 한다.
그리고 CSR과 SSR에 대해 정리를 해보려고 한다.
많은 회사들이 다양한 디자인 패턴에 대한 이해를 필요로 하여 나도 나름대로 정리하면 좋겠다 해서 정리를 해보려고 한다.
CSR과 SSR?
우선 MVC에 알아보기 전에 간략하게 Client Side Rendering과 Server Side Rendering에 대해서 알아보자.
SSR : Server측에서 html 파일을 렌더링하여 브라우저에게 전송
CSR : Client측에서 html 파일을 렌더링하여 브라우저에게 전송
즉, 쉽게 말해서 브라우저에게 띄워지는 html 파일을 누가 주체가 되어서 렌더링을 하냐의 차이이다.
아래는 nest의 공식문서 페이지의 개발자도구 Network 탭의 mvc에서 Server의 응답이다.
<!DOCTYPE html><html lang="en"><head><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
<title>Documentation | NestJS - A progressive Node.js framework</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta charset="utf-8">
<!-- 생략 -->
<script>
(function(i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
(i[r] =
i[r] ||
function() {
(i[r].q = i[r].q || []).push(arguments);
}),
(i[r].l = 1 * new Date());
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m);
})(
window,
document,
'script',
'https://www.google-analytics.com/analytics.js',
'ga',
);
ga('create', 'UA-30617038-5', 'auto');
ga('send', 'pageview');
</script>
<style>body{font-size:16px;font-weight:400;font-family:Source Sans Pro,Helvetica Neue,sans-serif;background-color:#fdfdfd;font-display:swap;color:#404040;margin:0;-webkit-font-smoothing:antialiased}</style><link rel="stylesheet" href="styles.51505eaca6700b74.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.51505eaca6700b74.css"></noscript></head>
<body>
<app-root></app-root>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.getRegistrations()
.then(function(registrations) {
registrations.forEach(registration => {
registration
.unregister()
.then(function(register) {})
.catch(function(error) {});
});
});
}
</script>
<script src="runtime.32cd1048b42db685.js" type="module"></script><script src="polyfills.e5039d5684e13ce2.js" type="module"></script><script src="main.8d0566d67651b61a.js" type="module"></script>
<style type="text/css">@font-face{font-family:'Inconsolata';font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/inconsolata/v21/QldgNThLqRwH-OJ1UHjlKENVzkWGVkL3GZQmAwLYxYWI2qfdm7Lpp4U8WRL2kXWdycuJDETf.woff) format('woff');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;}@font-face{font-family:'Inconsolata';font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/inconsolata/v21/QldgNThLqRwH-OJ1UHjlKENVzkWGVkL3GZQmAwLYxYWI2qfdm7Lpp4U8WRP2kXWdycuJDETf.woff) format('woff');unicode-range:U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;}@font-face{font-family:'Inconsolata';font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://fonts.gstatic.com/s/inconsolata/v21/QldgNThLqRwH-OJ1UHjlKENVzkWGVkL3GZQmAwLYxYWI2qfdm7Lpp4U8WR32kXWdycuJDA.woff) format('woff');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}</style>
</body></html>
무언가 서버에서 많은 내용을 받은 것처럼 보인다.
하지만 <body>
부분에서 <app-root>
라는 tag내부에는 아무런 html DOM 요소가 보이질 않는다.
따라서 서버로부터 html을 받은게 아니라 브라우저 내에서 즉, client side에서 서버에게 받은 script를 실행하면서 DOM 요소들을 렌더링 해주었다는 것이다.
왜 위와 같은 현상이 가능하냐면.. 기본적으로 javascript는 브라우저를 제어할 수 있기 때문..!
개발자도구의 console창에서 어떤 요소의 스타일을 변경하는게 가능하기 때문에 위와같은 것들이 가능하다.
반대로 MDN 공식문서의 렌더링 방식을 살펴보도록 하자.
<!DOCTYPE html><html lang="en-US" prefix="og: https://ogp.me/ns#"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon-48x48.cbbd161b.png"><link rel="apple-touch-icon" href="/apple-touch-icon.6803c6f0.png"><meta name="theme-color" content="#ffffff"><link rel="manifest" href="/manifest.56b1cedc.json"><link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="MDN Web Docs"><script>Array.prototype.flat&&Array.prototype.includes||document.write('<script src="https://polyfill.io/v3/polyfill.min.js?features=Array.prototype.flat%2Ces6"><\/script>')</script><title>MVC - 용어 사전 | MDN</title><link rel="alternate" title="MVC" href="https://developer.mozilla.org/ko/docs/Glossary/MVC" hreflang="ko"><link rel="alternate" title="MVC" href="https://developer.mozilla.org/zh-TW/docs/Glossary/MVC" hreflang="zh-TW"><link rel="alternate" title="MVC" href="https://developer.mozilla.org/zh-CN/docs/Glossary/MVC" hreflang="zh"><link rel="alternate" title="MVC" href="https://developer.mozilla.org/ja/docs/Glossary/MVC" hreflang="ja"><link rel="alternate" title="MVC" href="https://developer.mozilla.org/fr/docs/Glossary/MVC" hreflang="fr"><link rel="alternate" title="MVC" href="https://developer.mozilla.org/es/docs/Glossary/MVC" hreflang="es"><link rel="alternate" title="MVC" href="https://developer.mozilla.org/en-US/docs/Glossary/MVC" hreflang="en"><meta name="description" content="MVC (모델-뷰-컨트롤러) 는 사용자 인터페이스, 데이터 및 논리 제어를 구현하는데 널리 사용되는 소프트웨어 디자인 패턴입니다. 소프트웨어의 비즈니스 로직과 화면을 구분하는데 중점을 두고 있습니다. 이러한 "관심사 분리" 는 더나은 업무의 분리와 향상된 관리를 제공합니다. MVC 에 기반을 둔 몇 가지 다른 디자인 패턴으로 MVVM (모델-뷰-뷰모델), MVP (모델-뷰-프리젠터), MVW (모델-뷰-왓에버) 가 있습니다."><meta property="og:url" content="https://developer.mozilla.org/ko/docs/Glossary/MVC"><meta property="og:title" content="MVC - 용어 사전 | MDN"><meta property="og:description" content="MVC (모델-뷰-컨트롤러) 는 사용자 인터페이스, 데이터 및 논리 제어를 구현하는데 널리 사용되는 소프트웨어 디자인 패턴입니다. 소프트웨어의 비즈니스 로직과 화면을 구분하는데 중점을 두고 있습니다. 이러한 "관심사 분리" 는 더나은 업무의 분리와 향상된 관리를 제공합니다. MVC 에 기반을 둔 몇 가지 다른 디자인 패턴으로 MVVM (모델-뷰-뷰모델), MVP (모델-뷰-프리젠터), MVW (모델-뷰-왓에버) 가 있습니다."><meta property="og:locale" content="ko"><meta property="og:image" content="https://developer.mozilla.org/mdn-social-share.cd6c4a5a.png"><meta property="twitter:card" content="summary_large_image"><meta name="robots" content="index, follow"><link rel="canonical" href="https://developer.mozilla.org/ko/docs/Glossary/MVC"><style media="print">.breadcrumbs-container,.document-toc-container,.language-menu,.language-toggle,.on-github,.page-footer,.top-navigation-main,nav.sidebar,ul.prev-next{display:none!important}.main-page-content,.main-page-content pre{padding:2px}.main-page-content pre{border-left-width:2px}</style><link href="/static/css/main.6be18ab6.chunk.css" rel="stylesheet"><script>LUX=(function(){var a=("undefined"!==typeof(LUX)&&"undefined"!==typeof(LUX.gaMarks)?LUX.gaMarks:[]);var d=("undefined"!==typeof(LUX)&&"undefined"!==typeof(LUX.gaMeasures)?LUX.gaMeasures:[]);var j="LUX_start";var k=window.performance;var l=("undefined"!==typeof(LUX)&&LUX.ns?LUX.ns:(Date.now?Date.now():+(new Date())));if(k&&k.timing&&k.timing.navigationStart){l=k.timing.navigationStart}function f(){if(k&&k.now){return k.now()}var o=Date.now?Date.now():+(new Date());return o-l}function b(n){if(k){if(k.mark){return k.mark(n)}else{if(k.webkitMark){return k.webkitMark(n)}}}a.push({name:n,entryType:"mark",startTime:f(),duration:0});return}function m(p,t,n){if("undefined"===typeof(t)&&h(j)){t=j}if(k){if(k.measure){if(t){if(n){return k.measure(p,t,n)}else{return k.measure(p,t)}}else{return k.measure(p)}}else{if(k.webkitMeasure){return k.webkitMeasure(p,t,n)}}}var r=0,o=f();if(t){var s=h(t);if(s){r=s.startTime}else{if(k&&k.timing&&k.timing[t]){r=k.timing[t]-k.timing.navigationStart}else{return}}}if(n){var q=h(n);if(q){o=q.startTime}else{if(k&&k.timing&&k.timing[n]){o=k.timing[n]-k.timing.navigationStart}else{return}}}d.push({name:p,entryType:"measure",startTime:r,duration:(o-r)});return}function h(n){return c(n,g())}function c(p,o){for(i=o.length-1;i>=0;i--){var n=o[i];if(p===n.name){return n}}return undefined}function g(){if(k){if(k.getEntriesByType){return k.getEntriesByType("mark")}else{if(k.webkitGetEntriesByType){return k.webkitGetEntriesByType("mark")}}}return a}return{mark:b,measure:m,gaMarks:a,gaMeasures:d}})();LUX.ns=(Date.now?Date.now():+(new Date()));LUX.ac=[];LUX.cmd=function(a){LUX.ac.push(a)};LUX.init=function(){LUX.cmd(["init"])};LUX.send=function(){LUX.cmd(["send"])};LUX.addData=function(a,b){LUX.cmd(["addData",a,b])};LUX_ae=[];window.addEventListener("error",function(a){LUX_ae.push(a)});LUX_al=[];if("function"===typeof(PerformanceObserver)&&"function"===typeof(PerformanceLongTaskTiming)){var LongTaskObserver=new PerformanceObserver(function(c){var b=c.getEntries();for(var a=0;a<b.length;a++){var d=b[a];LUX_al.push(d)}});try{LongTaskObserver.observe({type:["longtask"]})}catch(e){}};</script><script src="https://cdn.speedcurve.com/js/lux.js?id=108906238" async="" defer="" crossorigin="anonymous"></script><script defer="" src="/static/js/ga.js"></script><script src="/static/js/runtime-main.459b6847.js" defer=""></script><script src="/static/js/4.b3124a68.chunk.js" defer=""></script><script src="/static/js/main.f6c5c98d.chunk.js" defer=""></script></head><body><script>const c={light:"#ffffff",dark:"#15141a"};if(window&&document.body){const o=window.localStorage.getItem("theme");o&&(document.body.className=o,document.body.style.backgroundColor=c[o])}</script><div id="root"><ul id="nav-access" class="a11y-nav"><li><a id="skip-main" href="#content">Skip to main content</a></li><li><a id="skip-select-language" href="#select-language">Skip to select language</a></li></ul><div class="page-wrapper document-page"><header class="top-navigation
"><div class="container "><div class="top-navigation-wrap"><a href="/ko/" class="logo" aria-label="MDN homepage"><svg id="mdn-docs-logo_svg__mdn-docs-logo" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 694.9 104.4" xml:space="preserve"><style>.mdn-docs-logo_svg__logo-m{fill:var(--text-link)}</style><path d="M40.3 0L11.7 92.1H0L28.5 0h11.8zm10.4 0v92.1H40.3V0h10.4zM91 0L62.5 92.1H50.8L79.3 0H91zm10.4 0v92.1H91V0h10.4z"></path><path class="mdn-docs-logo_svg__logo-m" d="M627.9 95.6h67v8.8h-67v-8.8z"></path><path d="M367 42h-4l-10.7 30.8h-5.5l-10.8-26h-.4l-10.5 26h-5.2L308.7 42h-3.8v-5.6H323V42h-6.5l6.8 20.4h.4l10.3-26h4.7l11.2 26h.5l5.7-20.3h-6.2v-5.6H367V42zm34.9 20c-.4 3.2-2 5.9-4.7 8.2-2.8 2.3-6.5 3.4-11.3 3.4-5.4 0-9.7-1.6-13.1-4.7-3.3-3.2-5-7.7-5-13.7 0-5.7 1.6-10.3 4.7-14s7.4-5.5 12.9-5.5c5.1 0 9.1 1.6 11.9 4.7s4.3 6.9 4.3 11.3c0 1.5-.2 3-.5 4.7h-25.6c.3 7.7 4 11.6 10.9 11.6 2.9 0 5.1-.7 6.5-2 1.5-1.4 2.5-3 3-4.9l6 .9zM394 51.3c.2-2.4-.4-4.7-1.8-6.9s-3.8-3.3-7-3.3c-3.1 0-5.3 1-6.9 3-1.5 2-2.5 4.4-2.8 7.2H394zm51 2.4c0 5-1.3 9.5-4 13.7s-6.9 6.2-12.7 6.2c-6 0-10.3-2.2-12.7-6.7-.1.4-.2 1.4-.4 2.9s-.3 2.5-.4 2.9h-7.3c.3-1.7.6-3.5.8-5.3.3-1.8.4-3.7.4-5.5V22.3h-6v-5.6H416v27c1.1-2.2 2.7-4.1 4.7-5.7 2-1.6 4.8-2.4 8.4-2.4 4.6 0 8.4 1.6 11.4 4.7 3 3.2 4.5 7.6 4.5 13.4zm-7.7.6c0-4.2-1-7.4-3-9.5-2-2.2-4.4-3.3-7.4-3.3-3.4 0-6 1.2-8 3.7-1.9 2.4-2.9 5-3 7.7V57c0 3 1 5.6 3 7.7s4.5 3.1 7.6 3.1c3.6 0 6.3-1.3 8.1-3.9 1.8-2.7 2.7-5.9 2.7-9.6zm69.2 18.5h-13.2v-7.2c-1.2 2.2-2.8 4.1-4.9 5.6-2.1 1.6-4.8 2.4-8.3 2.4-4.8 0-8.7-1.6-11.6-4.9-2.9-3.2-4.3-7.7-4.3-13.3 0-5 1.3-9.6 4-13.7 2.6-4.1 6.9-6.2 12.8-6.2 5.7 0 9.8 2.2 12.3 6.5V22.3h-8.6v-5.6h15.8v50.6h6v5.5zM493.2 56v-4.4c-.1-3-1.2-5.5-3.2-7.3s-4.4-2.8-7.2-2.8c-3.6 0-6.3 1.3-8.2 3.9-1.9 2.6-2.8 5.8-2.8 9.6 0 4.1 1 7.3 3 9.5s4.5 3.3 7.4 3.3c3.2 0 5.8-1.3 7.8-3.8 2.1-2.6 3.1-5.3 3.2-8zm53.1-1.4c0 5.6-1.8 10.2-5.3 13.7s-8.2 5.3-13.9 5.3-10.1-1.7-13.4-5.1c-3.3-3.4-5-7.9-5-13.5 0-5.3 1.6-9.9 4.7-13.7 3.2-3.8 7.9-5.7 14.2-5.7s11 1.9 14.1 5.7c3 3.7 4.6 8.1 4.6 13.3zm-7.7-.2c0-4-1-7.2-3-9.5s-4.8-3.5-8.2-3.5c-3.6 0-6.4 1.2-8.3 3.7s-2.9 5.6-2.9 9.5c0 3.7.9 6.8 2.8 9.4 1.9 2.6 4.6 3.9 8.3 3.9 3.6 0 6.4-1.3 8.4-3.8 1.9-2.6 2.9-5.8 2.9-9.7zm45 5.8c-.4 3.2-1.9 6.3-4.4 9.1-2.5 2.9-6.4 4.3-11.8 4.3-5.2 0-9.4-1.6-12.6-4.8-3.2-3.2-4.8-7.7-4.8-13.7 0-5.5 1.6-10.1 4.7-13.9 3.2-3.8 7.6-5.7 13.2-5.7 2.3 0 4.6.3 6.7.8 2.2.5 4.2 1.5 6.2 2.9l1.5 9.5-5.9.7-1.3-6.1c-2.1-1.2-4.5-1.8-7.2-1.8-3.5 0-6.1 1.2-7.7 3.7-1.7 2.5-2.5 5.7-2.5 9.6 0 4.1.9 7.3 2.7 9.5 1.8 2.3 4.4 3.4 7.8 3.4 5.2 0 8.2-2.9 9.2-8.8l6.2 1.3zm34.7 1.9c0 3.6-1.5 6.5-4.6 8.5s-7 3-11.7 3c-5.7 0-10.6-1.2-14.6-3.6l1.2-8.8 5.7.6-.2 4.7c1.1.5 2.3.9 3.6 1.1s2.6.3 3.9.3c2.4 0 4.5-.4 6.5-1.3 1.9-.9 2.9-2.2 2.9-4.1 0-1.8-.8-3.1-2.3-3.8s-3.5-1.3-5.8-1.7-4.6-.9-6.9-1.4c-2.3-.6-4.2-1.6-5.7-2.9-1.6-1.4-2.3-3.5-2.3-6.3 0-4.1 1.5-6.9 4.6-8.5s6.4-2.4 9.9-2.4c2.6 0 5 .3 7.2.9 2.2.6 4.3 1.4 6.1 2.4l.8 8.8-5.8.7-.8-5.7c-2.3-1-4.7-1.6-7.2-1.6-2.1 0-3.7.4-5.1 1.1-1.3.8-2 2-2 3.8 0 1.7.8 2.9 2.3 3.6 1.5.7 3.4 1.2 5.7 1.6 2.2.4 4.5.8 6.7 1.4 2.2.6 4.1 1.6 5.7 3 1.4 1.6 2.2 3.7 2.2 6.6zM197.6 73.2h-17.1v-5.5h3.8V51.9c0-3.7-.7-6.3-2.1-7.9-1.4-1.6-3.3-2.3-5.7-2.3-3.2 0-5.6 1.1-7.2 3.4s-2.4 4.6-2.5 6.9v15.6h6v5.5h-17.1v-5.5h3.8V51.9c0-3.8-.7-6.4-2.1-7.9-1.4-1.5-3.3-2.3-5.6-2.3-3.2 0-5.5 1.1-7.2 3.3-1.6 2.2-2.4 4.5-2.5 6.9v15.8h6.9v5.5h-20.2v-5.5h6V42.4h-6.1v-5.6h13.4v6.4c1.2-2.1 2.7-3.8 4.7-5.2 2-1.3 4.4-2 7.3-2s5.3.7 7.5 2.1c2.2 1.4 3.7 3.5 4.5 6.4 1.1-2.5 2.7-4.5 4.9-6.1s4.8-2.4 7.9-2.4c3.5 0 6.5 1.1 8.9 3.3s3.7 5.6 3.7 10.2v18.2h6.1v5.5zm42.5 0h-13.2V66c-1.2 2.2-2.8 4.1-4.9 5.6-2.1 1.6-4.8 2.4-8.3 2.4-4.8 0-8.7-1.6-11.6-4.9-2.9-3.2-4.3-7.7-4.3-13.3 0-5 1.3-9.6 4-13.7 2.6-4.1 6.9-6.2 12.8-6.2s9.8 2.2 12.3 6.5V22.7h-8.6v-5.6h15.8v50.6h6v5.5zm-13.3-16.8V52c-.1-3-1.2-5.5-3.2-7.3s-4.4-2.8-7.2-2.8c-3.6 0-6.3 1.3-8.2 3.9-1.9 2.6-2.8 5.8-2.8 9.6 0 4.1 1 7.3 3 9.5s4.5 3.3 7.4 3.3c3.2 0 5.8-1.3 7.8-3.8 2.1-2.6 3.1-5.3 3.2-8zm61.5 16.8H269v-5.5h6V51.9c0-3.7-.7-6.3-2.2-7.9-1.4-1.6-3.4-2.3-5.7-2.3-3.1 0-5.6 1-7.4 3s-2.8 4.4-2.9 7v15.9h6v5.5h-19.3v-5.5h6V42.4h-6.2v-5.6h13.6V43c2.6-4.6 6.8-6.9 12.7-6.9 3.6 0 6.7 1.1 9.2 3.3s3.7 5.6 3.7 10.2v18.2h6v5.4h-.2z" fill="var(--text-primary)"></path></svg></a><button aria-expanded="false" aria-haspopup="menu" aria-label="Open main menu" title="Open main menu" type="button" class="button action has-icon main-menu-toggle"><span class="button-wrap"><span class="icon icon-menu "></span><span class="visually-hidden">Open main menu</span></span></button></div><div class="top-navigation-main"><nav class="main-nav" aria-label="Main menu"><ul class="main-menu nojs"><li class="top-level-entry-container"><button type="button" id="references-button" class="top-level-entry menu-toggle" aria-haspopup="menu">References</button><a class="top-level-entry" href="/ko/docs/Web">References</a><ul class="submenu references hidden" role="menu" aria-labelledby="references-button"><li role="none" class="apis-link-container mobile-only "><a href="/ko/docs/Web" class="submenu-item " role="menuitem"><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Overview / Web Technology</div><p class="submenu-item-description">Web technology reference for developers</p></div></a></li><li role="none" class="html-link-container "><a href="/ko/docs/Web/HTML" class="submenu-item " role="menuitem"><div class="submenu-icon html"></div><div class="submenu-content-container"><div class="submenu-item-heading">HTML</div><p class="submenu-item-description">Structure of content on the web</p></div></a></li><li role="none" class="css-link-container "><a href="/ko/docs/Web/CSS" class="submenu-item " role="menuitem"><div class="submenu-icon css"></div><div class="submenu-content-container"><div class="submenu-item-heading">CSS</div><p class="submenu-item-description">Code used to describe document style</p></div></a></li><li role="none" class="javascript-link-container "><a href="/ko/docs/Web/JavaScript" class="submenu-item " role="menuitem"><div class="submenu-icon javascript"></div><div class="submenu-content-container"><div class="submenu-item-heading">JavaScript</div><p class="submenu-item-description">General-purpose scripting language</p></div></a></li><li role="none" class="http-link-container "><a href="/ko/docs/Web/HTTP" class="submenu-item " role="menuitem"><div class="submenu-icon http"></div><div class="submenu-content-container"><div class="submenu-item-heading">HTTP</div><p class="submenu-item-description">Protocol for transmitting web resources</p></div></a></li><li role="none" class="apis-link-container "><a href="/ko/docs/Web/API" class="submenu-item " role="menuitem"><div class="submenu-icon apis"></div><div class="submenu-content-container"><div class="submenu-item-heading">Web APIs</div><p class="submenu-item-description">Interfaces for building web applications</p></div></a></li><li role="none" class="apis-link-container desktop-only "><a href="/ko/docs/Web" class="submenu-item " role="menuitem"><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Web Technology</div><p class="submenu-item-description">Web technology reference for developers</p></div></a></li></ul></li><li class="top-level-entry-container"><button type="button" id="guides-button" class="top-level-entry menu-toggle" aria-haspopup="menu">Guides</button><a class="top-level-entry" href="/ko/docs/Learn">Guides</a><ul class="submenu guides hidden" role="menu" aria-labelledby="guides-button"><li role="none" class="apis-link-container mobile-only "><a href="/ko/docs/Learn" class="submenu-item " role="menuitem"><div class="submenu-icon learn"></div><div class="submenu-content-container"><div class="submenu-item-heading">Overview / MDN Learning Area</div><p class="submenu-item-description">Learn web development</p></div></a></li><li role="none" class="apis-link-container desktop-only "><a href="/ko/docs/Learn" class="submenu-item " role="menuitem"><div class="submenu-icon learn"></div><div class="submenu-content-container"><div class="submenu-item-heading">MDN Learning Area</div><p class="submenu-item-description">Learn web development</p></div></a></li><li role="none" class="html-link-container "><a href="/ko/docs/Learn/HTML" class="submenu-item " role="menuitem"><div class="submenu-icon html"></div><div class="submenu-content-container"><div class="submenu-item-heading">HTML</div><p class="submenu-item-description">Learn to structure web content with HTML</p></div></a></li><li role="none" class="css-link-container "><a href="/ko/docs/Learn/CSS" class="submenu-item " role="menuitem"><div class="submenu-icon css"></div><div class="submenu-content-container"><div class="submenu-item-heading">CSS</div><p class="submenu-item-description">Learn to style content using CSS</p></div></a></li><li role="none" class="javascript-link-container "><a href="/ko/docs/Learn/JavaScript" class="submenu-item " role="menuitem"><div class="submenu-icon javascript"></div><div class="submenu-content-container"><div class="submenu-item-heading">JavaScript</div><p class="submenu-item-description">Learn to run scripts in the browser</p></div></a></li><li role="none" class=" "><a href="/ko/docs/Web/Accessibility" class="submenu-item " role="menuitem"><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Accessibility</div><p class="submenu-item-description">Learn to make the web accessible to all</p></div></a></li></ul></li><li class="top-level-entry-container"><button id="mdn-plus-button" class="top-level-entry menu-toggle" aria-haspopup="menu">MDN Plus</button><a class="top-level-entry" href="/ko/plus">MDN Plus</a><ul class="submenu mdn-plus hidden" role="menu" aria-labelledby="mdn-plus-button"><li role="none" class="mobile-only "><a href="/ko/plus" class="submenu-item " role="menuitem"><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">Overview</div><p class="submenu-item-description">More MDN. Your MDN.</p></div></a></li><li role="none" class=" "><a href="/en-US/plus/docs/faq" class="submenu-item " role="menuitem"><div class="submenu-icon"></div><div class="submenu-content-container"><div class="submenu-item-heading">FAQ</div><p class="submenu-item-description">Frequently asked questions about MDN Plus</p></div></a></li></ul></li></ul></nav><div class="header-search"><form action="/ko/search" role="search" aria-haspopup="listbox" aria-owns="downshift-4333-menu" aria-expanded="false" class="search-form search-widget" id="top-nav-search-form"><label for="top-nav-search-q" class="visually-hidden">Search MDN</label><input type="search" id="top-nav-search-q" aria-autocomplete="list" aria-controls="downshift-4333-menu" aria-labelledby="downshift-4333-label" autocomplete="off" value="" class="search-input-field" name="q" placeholder=" " required=""><button type="button" class="button action has-icon clear-search-button"><span class="button-wrap"><span class="icon icon-cancel "></span><span class="visually-hidden">Clear search input</span></span></button><button type="submit" class="button action has-icon search-button"><span class="button-wrap"><span class="icon icon-search "></span><span class="visually-hidden">Search</span></span></button><div id="downshift-4333-menu" role="listbox" aria-labelledby="downshift-4333-label"></div></form></div><div class="theme-switcher-menu"><button aria-controls="themes-menu" aria-haspopup="menu" type="button" class="button action has-icon theme-switcher-menu small"><span class="button-wrap"><span class="icon icon-theme-os-default "></span>Theme</span></button></div></div></div></header><div class="article-actions-container"><div class="container"><button type="button" class="button action has-icon sidebar-button"><span class="button-wrap"><span class="icon icon-sidebar "></span></span></button><nav class="breadcrumbs-container" aria-label="Breadcrumb navigation"><ol typeof="BreadcrumbList" vocab="https://schema.org/" aria-label="breadcrumbs"><li property="itemListElement" typeof="ListItem"><a class="breadcrumb" property="item" typeof="WebPage" href="/ko/docs/Glossary"><span property="name">용어 사전</span></a><meta property="position" content="1"></li><li property="itemListElement" typeof="ListItem"><a class="breadcrumb-current-page" property="item" typeof="WebPage" href="/ko/docs/Glossary/MVC"><span property="name">MVC</span></a><meta property="position" content="2"></li></ol></nav><div class="article-actions"><button type="button" class="button action has-icon article-actions-toggle"><span class="button-wrap"><span class="icon icon-ellipses "></span><span class="article-actions-dialog-heading">Article Actions</span></span></button><ul class="article-actions-entries"><li class="article-actions-entry"><div class="languages-switcher-menu open-on-focus-within"><button aria-controls="language-menu" aria-haspopup="menu" type="button" class="button action small has-icon languages-switcher-menu"><span class="button-wrap"><span class="icon icon-language "></span>한국어</span></button></div></li></ul></div></div></div><div class="container"><div class="notecard localized-content-note inline neutral"><p><a href="/en-US/docs/MDN/Contribute/Localize#active_locales">이 페이지는 영어로부터 커뮤니티에 의하여 번역되었습니다. MDN Web Docs에서 한국 커뮤니티에 가입하여 자세히 알아보세요.</a></p></div></div><div class="article-wrapper"><nav id="sidebar-quicklinks" class="sidebar"><button type="button" class="button action backdrop"><span class="button-wrap"></span></button><div class="sidebar-inner"><div class="in-nav-toc"><aside class="document-toc-container"><section class="document-toc"><header><h2 class="document-toc-heading">In this article</h2></header><ul class="document-toc-list" id="toc-entries"><li class="document-toc-item "><a class="document-toc-link" href="#모델_뷰_컨트롤러_예시">모델 뷰 컨트롤러 예시</a></li><li class="document-toc-item "><a class="document-toc-link" href="#웹에서의_mvc">웹에서의 MVC</a></li><li class="document-toc-item "><a class="document-toc-link" href="#더_알아보기">더 알아보기</a></li></ul></section></aside></div></div></nav><div class="toc"><aside class="document-toc-container"><section class="document-toc"><header><h2 class="document-toc-heading">In this article</h2></header><ul class="document-toc-list" id="toc-entries"><li class="document-toc-item "><a class="document-toc-link" href="#모델_뷰_컨트롤러_예시">모델 뷰 컨트롤러 예시</a></li><li class="document-toc-item "><a class="document-toc-link" href="#웹에서의_mvc">웹에서의 MVC</a></li><li class="document-toc-item "><a class="document-toc-link" href="#더_알아보기">더 알아보기</a></li></ul></section></aside></div><main id="content" class="main-content" role="main"><article class="main-page-content" lang="ko"><h1>MVC</h1><div><p><strong>MVC</strong> (모델-뷰-컨트롤러) 는 사용자 인터페이스, 데이터 및 논리 제어를 구현하는데 널리 사용되는 소프트웨어 디자인 패턴입니다. 소프트웨어의 비즈니스 로직과 화면을 구분하는데 중점을 두고 있습니다. 이러한 "관심사 분리" 는 더나은 업무의 분리와 향상된 관리를 제공합니다. MVC 에 기반을 둔 몇 가지 다른 디자인 패턴으로 MVVM (모델-뷰-뷰모델), MVP (모델-뷰-프리젠터), MVW (모델-뷰-왓에버) 가 있습니다.</p>
<p>MVC 소프트웨어 디자인 패턴의 세 가지 부분은 다음과 같이 설명할 수 있습니다.</p>
<ol>
<li>모델: 데이터와 비즈니스 로직을 관리합니다.</li>
<li>뷰: 레이아웃과 화면을 처리합니다.</li>
<li>컨트롤러: 명령을 모델과 뷰 부분으로 라우팅합니다.</li>
</ol></div><h2 id="모델_뷰_컨트롤러_예시"><a href="#모델_뷰_컨트롤러_예시" title="Permalink to 모델 뷰 컨트롤러 예시">모델 뷰 컨트롤러 예시</a></h2><div><p>간단한 쇼핑 리스트 앱이 있다고 상상해봅시다. 우리가 원하는 것은 이번 주에 사야할 각 항목의 이름, 개수, 가격의 목록입니다. MVC 를 사용해 이 기능의 일부를 구현하는 방법을 아래에서 설명할 것입니다.</p>
<p><img alt="Diagram to show the different parts of the mvc architecture." src="https://mdn.mozillademos.org/files/16042/model-view-controller-light-blue.png" loading="lazy"></p></div><h3 id="모델"><a href="#모델" title="Permalink to 모델">모델</a></h3><div><p>모델은 앱이 포함해야할 데이터가 무엇인지를 정의합니다. 데이터의 상태가 변경되면 모델을 일반적으로 뷰에게 알리며(따라서 필요한대로 화면을 변경할 수 있습니다) 가끔 컨트롤러에게 알리기도 합니다(업데이트된 뷰를 제거하기 위해 다른 로직이 필요한 경우).</p>
<p>다시 쇼핑 리스트 앱으로 돌아가서, 모델은 리스트 항목이 포함해야 하는 데이터 — 품목, 가격, 등. — 와 이미 존재하는 리스트 항목이 무엇인지를 지정합니다.</p></div><h3 id="뷰"><a href="#뷰" title="Permalink to 뷰">뷰</a></h3><div><p>뷰는 앱의 데이터를 보여주는 방식을 정의합니다.</p>
<p>쇼핑 리스트 앱에서, 뷰는 항목이 사용자에게 보여지는 방식을 정의하며, 표시할 데이터를 모델로부터 받습니다.</p></div><h3 id="컨트롤러"><a href="#컨트롤러" title="Permalink to 컨트롤러">컨트롤러</a></h3><div><p>컨트롤러는 앱의 사용자로부터의 입력에 대한 응답으로 모델 및/또는 뷰를 업데이트하는 로직을 포함합니다.</p>
<p>예를 들어보면, 쇼핑 리스트는 항목을 추가하거나 제거할 수 있게 해주는 입력 폼과 버튼을 갖습니다. 이러한 액션들은 모델이 업데이트되는 것이므로 입력이 컨트롤러에게 전송되고, 모델을 적당하게 처리한다음, 업데이트된 데이터를 뷰로 전송합니다.</p>
<p>단순히 데이터를 다른 형태로 나타내기 위해 뷰를 업데이트하고 싶을 수도 있습니다(예를 들면, 항목을 알파벳순서로 정렬한다거나, 가격이 낮은 순서 또는 높은 순서로 정렬). 이런 경우에 컨트롤러는 모델을 업데이트할 필요 없이 바로 처리할 수 있습니다.</p></div><h2 id="웹에서의_mvc"><a href="#웹에서의_mvc" title="Permalink to 웹에서의 MVC">웹에서의 MVC</a></h2><div><p>웹 개발자로써, 여러분이 이 패턴을 이전에 의식적으로 사용한 적이 없더라도 아마 상당히 친숙할것입니다. 여러분의 데이터 모델은 아마 어떤 종류의 데이터베이스에 포함되어있었을 것입니다(MySQL 과 같은 전통적인 서버 사이드 데이터베이스, 또는 <a href="/ko/docs/Web/API/IndexedDB_API">IndexedDB</a> 같은 클라이언트 사이드 솔루션). 여러분의 앱의 제어 코드는 아마 HTML/JavaScript 로 작성되었을 것이고, 사용자 인터페이스는 HTML/CSS 등 여러분이 선호하는 것들로 작성되었을 것입니다. 이는 MVC 와 아주 유사하게 들리지만, MVC 는 이러한 컴포넌트들이 더 엄격한 패턴을 따르도록합니다.</p>
<p>웹의 초창기에, MVC 구조는 클라이언트가 폼이나 링크를 통해 업데이트를 요청하거나 업데이트된 뷰를 받아 다시 브라우저에 표시하기 위해 대부분 서버 사이드에서 구현되었습니다. 반면, 요즘에는, 클라이언트 사이드 데이터 저장소의 출현과 필요에 따라 페이지의 일부만 업데이트를 허용하는 XMLHttpRequest 를 포함해 더 많은 로직이 클라이언트 사이드에 추가되었습니다.</p>
<p><a href="http://en.wikipedia.org/wiki/AngularJS" title="AngularJS" class="external" rel=" noopener">AngularJS</a> 및 <a href="http://en.wikipedia.org/wiki/Ember.js" title="Ember.js" class="external" rel=" noopener">Ember.js</a> 와 같은 웹 프레임워크들은 약간씩은 방식이 다르지만, 모두 MVC 구조를 구현합니다.</p></div><h2 id="더_알아보기"><a href="#더_알아보기" title="Permalink to 더 알아보기">더 알아보기</a></h2><div></div><h3 id="일반_지식"><a href="#일반_지식" title="Permalink to 일반 지식">일반 지식</a></h3><div><ul>
<li><a title="Model–view–controller" href="https://ko.wikipedia.org/wiki/Model–view–controller" class="external" rel=" noopener">Model–view–controller</a> on Wikipedia</li>
</ul></div><aside class="metadata"><div class="metadata-content-container"><div id="on-github" class="on-github"><h4>Found a problem with this page?</h4><ul><li><a href="https://github.com/mdn/translated-content/edit/main/files/ko/glossary/mvc/index.html" title="You're going to need to sign in to GitHub first (Opens in a new tab)" target="_blank" rel="noopener noreferrer">Edit on <b>GitHub</b></a></li><li><a href="https://github.com/mdn/translated-content/blob/main/files/ko/glossary/mvc/index.html?plain=1" title="Folder: ko/glossary/mvc (Opens in a new tab)" target="_blank" rel="noopener noreferrer">Source on <b>GitHub</b></a></li><li><a href="https://github.com/mdn/translated-content/issues/new?body=MDN+URL%3A+https%3A%2F%2Fdeveloper.mozilla.org%2Fko%2Fdocs%2FGlossary%2FMVC%0A%0A%23%23%23%23+What+information+was+incorrect%2C+unhelpful%2C+or+incomplete%3F%0A%0A%0A%23%23%23%23+Specific+section+or+headline%3F%0A%0A%0A%23%23%23%23+What+did+you+expect+to+see%3F%0A%0A%0A%23%23%23%23+Did+you+test+this%3F+If+so%2C+how%3F%0A%0A%0A%3C%21--+Do+not+make+changes+below+this+line+--%3E%0A%3Cdetails%3E%0A%3Csummary%3EMDN+Content+page+report+details%3C%2Fsummary%3E%0A%0A*+Folder%3A+%60ko%2Fglossary%2Fmvc%60%0A*+MDN+URL%3A+https%3A%2F%2Fdeveloper.mozilla.org%2Fko%2Fdocs%2FGlossary%2FMVC%0A*+GitHub+URL%3A+https%3A%2F%2Fgithub.com%2Fmdn%2Ftranslated-content%2Fblob%2Fmain%2Ffiles%2Fko%2Fglossary%2Fmvc%2Findex.html%0A*+Last+commit%3A+https%3A%2F%2Fgithub.com%2Fmdn%2Ftranslated-content%2Fcommit%2F2c5fad84705a32a9773a8d9dcf13b033ff1ca2f2%0A*+Document+last+modified%3A+2022-02-26T01%3A12%3A32.000Z%0A%0A%3C%2Fdetails%3E&title=Issue+with+%22MVC%22%3A+%28short+summary+here+please%29&labels=needs-triage%2Cl10n-ko" title="This will take you to https://github.com/mdn/content to file a new issue" target="_blank" rel="noopener noreferrer">Report a problem with this content on <b>GitHub</b></a></li><li>Want to fix the problem yourself? See<!-- --> <a href="https://github.com/mdn/content/blob/main/README.md" target="_blank" rel="noopener noreferrer">our Contribution guide</a>.</li></ul></div><p class="last-modified-date"><b>Last modified:</b> <time datetime="2022-02-26T01:12:32.000Z">Feb 26, 2022</time>,<!-- --> <a href="/ko/docs/Glossary/MVC/contributors.txt">by MDN contributors</a></p></div></aside></article></main></div></div><footer id="nav-footer" class="page-footer"><div class="page-footer-grid"><div class="page-footer-logo-col"><a href="/" class="mdn-footer-logo" aria-label="MDN homepage"><svg width="48" height="17" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M20.04 16.512h-4.536v-6.096c0-.928-.16-1.592-.48-1.992-.304-.4-.76-.6-1.368-.6-.736 0-1.272.24-1.608.72-.32.48-.48 1.096-.48 1.848v3.792h1.44v2.328H8.472v-6.096c0-.928-.16-1.592-.48-1.992-.304-.4-.76-.6-1.368-.6-.752 0-1.288.24-1.608.72-.32.48-.48 1.096-.48 1.848v3.792H6.6v2.328H0v-2.328h1.44V8.04H.024V5.688h4.512V7.32c.688-1.232 1.784-1.848 3.288-1.848.784 0 1.504.192 2.16.576.656.384 1.112.968 1.368 1.752.64-1.552 1.816-2.328 3.528-2.328.976 0 1.84.304 2.592.912.752.608 1.128 1.552 1.128 2.832v4.968h1.44v2.328zM33.671 16.512h-4.536v-2.016a4.446 4.446 0 01-1.344 1.608c-.592.432-1.376.648-2.352.648-1.424 0-2.544-.488-3.36-1.464-.816-.976-1.224-2.304-1.224-3.984 0-1.616.4-2.992 1.2-4.128.8-1.136 2.008-1.704 3.624-1.704.88 0 1.6.176 2.16.528.56.352.992.8 1.296 1.344V2.352h-2.16V0h5.256v14.184h1.44v2.328zm-4.536-5.472v-.264c0-.896-.24-1.592-.72-2.088-.464-.512-1.048-.768-1.752-.768-.688 0-1.296.256-1.824.768-.512.512-.768 1.32-.768 2.424 0 1.04.24 1.832.72 2.376.48.544 1.048.816 1.704.816.816 0 1.456-.344 1.92-1.032.48-.688.72-1.432.72-2.232zM47.959 16.512h-5.976v-2.328h1.44v-3.768c0-.928-.16-1.592-.48-1.992-.304-.4-.76-.6-1.368-.6-.736 0-1.304.232-1.704.696-.4.448-.608 1.04-.624 1.776v3.888h1.44v2.328H34.71v-2.328h1.44V8.04h-1.56V5.688h4.656v1.656c.72-1.248 1.88-1.872 3.48-1.872 1.024 0 1.912.304 2.664.912.752.608 1.128 1.552 1.128 2.832v4.968h1.44v2.328z" fill="currentColor"></path></svg></a><p>Your blueprint for a better internet.</p><ul class="social-icons"><li><a class="icon icon-twitter" href="https://twitter.com/mozdevnet" target="_blank" rel="noopener noreferrer"><span class="visually-hidden">MDN on Twitter</span></a></li><li><a class="icon icon-github-mark-small" href="https://github.com/mdn/" target="_blank" rel="noopener noreferrer"><span class="visually-hidden">MDN on Github</span></a></li></ul></div><div class="page-footer-nav-col-1"><h2 class="footer-nav-heading">MDN</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a href="/en-US/about">About</a></li><li class="footer-nav-item"><a href="https://hacks.mozilla.org/" target="_blank" rel="noopener noreferrer">Hacks Blog</a></li><li class="footer-nav-item"><a href="https://www.mozilla.org/en-US/careers/listings/?team=Marketing" target="_blank" rel="noopener noreferrer">Careers</a></li></ul></div><div class="page-footer-nav-col-2"><h2 class="footer-nav-heading">Support</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a class="footer-nav-link" href="https://support.mozilla.org/products/mdn-plus">Product help</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/ko/docs/MDN/Contribute/Feedback#documentation_issues">Report a page issue</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/ko/docs/MDN/Contribute/Feedback#site_issues">Report a site issue</a></li></ul></div><div class="page-footer-nav-col-3"><h2 class="footer-nav-heading">Our communities</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a class="footer-nav-link" href="/en-US/community">MDN Community</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="https://discourse.mozilla.org/c/mdn/236" target="_blank" rel="noopener noreferrer">MDN Forum</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="https://wiki.mozilla.org/Matrix" target="_blank" rel="noopener noreferrer">MDN Chat</a></li></ul></div><div class="page-footer-nav-col-4"><h2 class="footer-nav-heading">Developers</h2><ul class="footer-nav-list"><li class="footer-nav-item"><a class="footer-nav-link" href="/ko/docs/Web">Web Technologies</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/ko/docs/Learn">Learn Web Development</a></li><li class="footer-nav-item"><a class="footer-nav-link" href="/ko/plus">MDN Plus</a></li></ul></div><div class="page-footer-moz"><a href="https://www.mozilla.org/" class="footer-moz-logo-link" target="_blank" rel="noopener noreferrer"><svg width="112" height="32" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M41.753 14.218c-2.048 0-3.324 1.522-3.324 4.157 0 2.423 1.119 4.286 3.29 4.286 2.082 0 3.447-1.678 3.447-4.347 0-2.826-1.522-4.096-3.413-4.096zm54.89 7.044c0 .901.437 1.618 1.645 1.618 1.427 0 2.949-1.024 3.044-3.352-.649-.095-1.365-.185-2.02-.185-1.426-.005-2.668.397-2.668 1.92z" fill="currentColor"></path><path d="M0 0v32h111.908V0H0zm32.56 25.426h-5.87v-7.884c0-2.423-.806-3.352-2.39-3.352-1.924 0-2.702 1.365-2.702 3.324v4.868h1.864v3.044h-5.864v-7.884c0-2.423-.806-3.352-2.39-3.352-1.924 0-2.702 1.365-2.702 3.324v4.868h2.669v3.044H6.642v-3.044h1.863v-7.918H6.642V11.42h5.864v2.11c.839-1.489 2.3-2.39 4.252-2.39 2.02 0 3.878.963 4.566 3.01.778-1.862 2.361-3.01 4.566-3.01 2.512 0 4.812 1.522 4.812 4.84v6.402h1.863v3.044h-.005zm9.036.307c-4.314 0-7.296-2.635-7.296-7.106 0-4.096 2.484-7.481 7.514-7.481s7.481 3.38 7.481 7.29c0 4.472-3.228 7.297-7.699 7.297zm22.578-.307H51.942l-.403-2.11 7.7-8.846h-4.376l-.621 2.17-2.888-.313.498-4.907h12.294l.313 2.11-7.767 8.852h4.533l.654-2.172 3.167.308-.872 4.908zm7.99 0h-4.191v-5.03h4.19v5.03zm0-8.976h-4.191v-5.03h4.19v5.03zm2.618 8.976l6.054-21.358h3.945l-6.054 21.358h-3.945zm8.136 0l6.048-21.358h3.945l-6.054 21.358h-3.939zm21.486.307c-1.863 0-2.887-1.085-3.072-2.792-.805 1.427-2.232 2.792-4.498 2.792-2.02 0-4.314-1.085-4.314-4.006 0-3.447 3.323-4.253 6.518-4.253.778 0 1.584.034 2.3.124v-.465c0-1.427-.034-3.133-2.3-3.133-.84 0-1.488.061-2.143.402l-.453 1.578-3.195-.34.549-3.224c2.45-.996 3.692-1.27 5.992-1.27 3.01 0 5.556 1.55 5.556 4.75v6.083c0 .805.314 1.085.963 1.085.184 0 .375-.034.587-.095l.034 2.11a5.432 5.432 0 01-2.524.654z" fill="currentColor"></path></svg></a><ul class="footer-moz-list"><li class="footer-moz-item"><a href="https://www.mozilla.org/privacy/websites/" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Website Privacy Notice</a></li><li class="footer-moz-item"><a href="https://www.mozilla.org/privacy/websites/#cookies" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Cookies</a></li><li class="footer-moz-item"><a href="https://www.mozilla.org/about/legal/terms/mozilla" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Legal</a></li><li class="footer-moz-item"><a href="https://www.mozilla.org/about/governance/policies/participation/" class="footer-moz-link" target="_blank" rel="noopener noreferrer">Community Participation Guidelines</a></li></ul></div><div class="page-footer-legal"><p id="license" class="page-footer-legal-text">Visit<!-- --> <a href="https://www.mozilla.org" target="_blank" rel="noopener noreferrer">Mozilla Corporation’s</a> <!-- -->not-for-profit parent, the<!-- --> <a target="_blank" rel="noopener noreferrer" href="https://foundation.mozilla.org/">Mozilla Foundation</a>.<br>Portions of this content are ©1998–<!-- -->2022<!-- --> by individual mozilla.org contributors. Content available under<!-- --> <a href="/docs/MDN/About#Copyrights_and_licenses">a Creative Commons license</a>.</p></div></div></footer></div><script type="application/json" id="hydration">{"doc":{"isMarkdown":false,"isTranslated":true,"isActive":true,"flaws":{},"title":"MVC","mdn_url":"/ko/docs/Glossary/MVC","locale":"ko","native":"한국어","sidebarHTML":"","body":[{"type":"prose","value":{"id":null,"title":null,"isH3":false,"content":"<p><strong>MVC</strong> (모델-뷰-컨트롤러) 는 사용자 인터페이스, 데이터 및 논리 제어를 구현하는데 널리 사용되는 소프트웨어 디자인 패턴입니다. 소프트웨어의 비즈니스 로직과 화면을 구분하는데 중점을 두고 있습니다. 이러한 \"관심사 분리\" 는 더나은 업무의 분리와 향상된 관리를 제공합니다. MVC 에 기반을 둔 몇 가지 다른 디자인 패턴으로 MVVM (모델-뷰-뷰모델), MVP (모델-뷰-프리젠터), MVW (모델-뷰-왓에버) 가 있습니다.</p>\n\n<p>MVC 소프트웨어 디자인 패턴의 세 가지 부분은 다음과 같이 설명할 수 있습니다.</p>\n\n<ol>\n <li>모델: 데이터와 비즈니스 로직을 관리합니다.</li>\n <li>뷰: 레이아웃과 화면을 처리합니다.</li>\n <li>컨트롤러: 명령을 모델과 뷰 부분으로 라우팅합니다.</li>\n</ol>"}},{"type":"prose","value":{"id":"모델_뷰_컨트롤러_예시","title":"모델 뷰 컨트롤러 예시","isH3":false,"content":"<p>간단한 쇼핑 리스트 앱이 있다고 상상해봅시다. 우리가 원하는 것은 이번 주에 사야할 각 항목의 이름, 개수, 가격의 목록입니다. MVC 를 사용해 이 기능의 일부를 구현하는 방법을 아래에서 설명할 것입니다.</p>\n\n<p><img alt=\"Diagram to show the different parts of the mvc architecture.\" src=\"https://mdn.mozillademos.org/files/16042/model-view-controller-light-blue.png\" loading=\"lazy\"></p>"}},{"type":"prose","value":{"id":"모델","title":"모델","isH3":true,"content":"<p>모델은 앱이 포함해야할 데이터가 무엇인지를 정의합니다. 데이터의 상태가 변경되면 모델을 일반적으로 뷰에게 알리며(따라서 필요한대로 화면을 변경할 수 있습니다) 가끔 컨트롤러에게 알리기도 합니다(업데이트된 뷰를 제거하기 위해 다른 로직이 필요한 경우).</p>\n\n<p>다시 쇼핑 리스트 앱으로 돌아가서, 모델은 리스트 항목이 포함해야 하는 데이터 — 품목, 가격, 등. — 와 이미 존재하는 리스트 항목이 무엇인지를 지정합니다.</p>"}},{"type":"prose","value":{"id":"뷰","title":"뷰","isH3":true,"content":"<p>뷰는 앱의 데이터를 보여주는 방식을 정의합니다.</p>\n\n<p>쇼핑 리스트 앱에서, 뷰는 항목이 사용자에게 보여지는 방식을 정의하며, 표시할 데이터를 모델로부터 받습니다.</p>"}},{"type":"prose","value":{"id":"컨트롤러","title":"컨트롤러","isH3":true,"content":"<p>컨트롤러는 앱의 사용자로부터의 입력에 대한 응답으로 모델 및/또는 뷰를 업데이트하는 로직을 포함합니다.</p>\n\n<p>예를 들어보면, 쇼핑 리스트는 항목을 추가하거나 제거할 수 있게 해주는 입력 폼과 버튼을 갖습니다. 이러한 액션들은 모델이 업데이트되는 것이므로 입력이 컨트롤러에게 전송되고, 모델을 적당하게 처리한다음, 업데이트된 데이터를 뷰로 전송합니다.</p>\n\n<p>단순히 데이터를 다른 형태로 나타내기 위해 뷰를 업데이트하고 싶을 수도 있습니다(예를 들면, 항목을 알파벳순서로 정렬한다거나, 가격이 낮은 순서 또는 높은 순서로 정렬). 이런 경우에 컨트롤러는 모델을 업데이트할 필요 없이 바로 처리할 수 있습니다.</p>"}},{"type":"prose","value":{"id":"웹에서의_mvc","title":"웹에서의 MVC","isH3":false,"content":"<p>웹 개발자로써, 여러분이 이 패턴을 이전에 의식적으로 사용한 적이 없더라도 아마 상당히 친숙할것입니다. 여러분의 데이터 모델은 아마 어떤 종류의 데이터베이스에 포함되어있었을 것입니다(MySQL 과 같은 전통적인 서버 사이드 데이터베이스, 또는 <a href=\"/ko/docs/Web/API/IndexedDB_API\">IndexedDB</a> 같은 클라이언트 사이드 솔루션). 여러분의 앱의 제어 코드는 아마 HTML/JavaScript 로 작성되었을 것이고, 사용자 인터페이스는 HTML/CSS 등 여러분이 선호하는 것들로 작성되었을 것입니다. 이는 MVC 와 아주 유사하게 들리지만, MVC 는 이러한 컴포넌트들이 더 엄격한 패턴을 따르도록합니다.</p>\n\n<p>웹의 초창기에, MVC 구조는 클라이언트가 폼이나 링크를 통해 업데이트를 요청하거나 업데이트된 뷰를 받아 다시 브라우저에 표시하기 위해 대부분 서버 사이드에서 구현되었습니다. 반면, 요즘에는, 클라이언트 사이드 데이터 저장소의 출현과 필요에 따라 페이지의 일부만 업데이트를 허용하는 XMLHttpRequest 를 포함해 더 많은 로직이 클라이언트 사이드에 추가되었습니다.</p>\n\n<p><a href=\"http://en.wikipedia.org/wiki/AngularJS\" title=\"AngularJS\" class=\"external\" rel=\" noopener\">AngularJS</a> 및 <a href=\"http://en.wikipedia.org/wiki/Ember.js\" title=\"Ember.js\" class=\"external\" rel=\" noopener\">Ember.js</a> 와 같은 웹 프레임워크들은 약간씩은 방식이 다르지만, 모두 MVC 구조를 구현합니다.</p>"}},{"type":"prose","value":{"id":"더_알아보기","title":"더 알아보기","isH3":false,"content":""}},{"type":"prose","value":{"id":"일반_지식","title":"일반 지식","isH3":true,"content":"<ul>\n <li><a title=\"Model–view–controller\" href=\"https://ko.wikipedia.org/wiki/Model–view–controller\" class=\"external\" rel=\" noopener\">Model–view–controller</a> on Wikipedia</li>\n</ul>"}}],"toc":[{"text":"모델 뷰 컨트롤러 예시","id":"모델_뷰_컨트롤러_예시"},{"text":"웹에서의 MVC","id":"웹에서의_mvc"},{"text":"더 알아보기","id":"더_알아보기"}],"summary":"MVC (모델-뷰-컨트롤러) 는 사용자 인터페이스, 데이터 및 논리 제어를 구현하는데 널리 사용되는 소프트웨어 디자인 패턴입니다. 소프트웨어의 비즈니스 로직과 화면을 구분하는데 중점을 두고 있습니다. 이러한 \"관심사 분리\" 는 더나은 업무의 분리와 향상된 관리를 제공합니다. MVC 에 기반을 둔 몇 가지 다른 디자인 패턴으로 MVVM (모델-뷰-뷰모델), MVP (모델-뷰-프리젠터), MVW (모델-뷰-왓에버) 가 있습니다.","popularity":0.0011,"modified":"2022-02-26T01:12:32.000Z","other_translations":[{"title":"MVC","locale":"en-US","native":"English (US)"},{"title":"MVC","locale":"es","native":"Español"},{"title":"MVC","locale":"fr","native":"Français"},{"title":"MVC","locale":"ja","native":"日本語"},{"title":"MVC","locale":"zh-CN","native":"中文 (简体)"},{"title":"MVC","locale":"zh-TW","native":"正體中文 (繁體)"}],"source":{"folder":"ko/glossary/mvc","github_url":"https://github.com/mdn/translated-content/blob/main/files/ko/glossary/mvc/index.html","last_commit_url":"https://github.com/mdn/translated-content/commit/2c5fad84705a32a9773a8d9dcf13b033ff1ca2f2","filename":"index.html"},"short_title":"MVC","parents":[{"uri":"/ko/docs/Glossary","title":"용어 사전"},{"uri":"/ko/docs/Glossary/MVC","title":"MVC"}],"pageTitle":"MVC - 용어 사전 | MDN","noIndexing":false}}</script></body></html>
위의 Nest 공식문서를 렌더링 했을 때와는 많이 다른 모습이다.
서버에서 받은 응답으로 사용자에게 보여질 뷰(view)부분을 모두 가지고 있는 것을 볼 수 있다.
따라서, MDN 공식문서에서는 렌더링 방식으로 SSR을 사용하고 있고,
Nest 공식문서에서는 렌더링 방식으로 CSR을 사용하는 것을 알 수 있었다.
그렇다면 언제 CSR .. 언제 SSR ?
그렇다면 어떤 상황일때 CSR을 혹은 SSR을 사용하는 것이 적합할까?
사용자와의 상호작용이 많고, javascript로 많은 일들을 해야한다면.. CSR을 사용하는 것이 좋다.
하지만!
CSR의 단점이 있다. 그것은 바로 렌더링 시간이 불규칙적일 수가 있다.
왜냐하면 client측에서 모든 html(or DOM) 요소들을 렌더링하는데 걸리는 시간이 있기 때문에 만약 렌더링할게 무지하게 많다면 좋지 않을 것 같다.
그치만 결론으로는 한 프로젝트 내에서 CSR만 사용하거나 SSR을 사용하거나 그러지는 않는다고 한다.
상황에따라 적절하게 조화를 이루면서 사용한다고 함!
MVC 패턴의 핵심?
핵심 키워드는 관심사의 분리이다.
즉, 하나의 소프트웨어 프로그램을 각각의 영역으로 관심사를 분리시켜 놓는다는 의미.
Model 쪽에서는 View와 Controller가 어떤 방식으로 동작하는지
반대로 View와 Controller도 Model쪽에선 어떤 방식으로 동작하는지 알 필요가 없다는 것이다.
그러므로 협업 시 완벽하게 분리되어 진행할 수 있고 서로 데이터를 주고받으면서 개발을 하는 방식이라고 생각하면 된다.
그렇다면 각각의 요소는 어떤것을 의미하는지 살펴보자.
https://developer.mozilla.org/ko/docs/Glossary/MVC
Model
우리가 어떤 앱을 개발하려고 한다면, 필수로 포함해야 할 데이터가 존재한다. 그 데이터에 대한 정보가 바로 모델이다.
데이터의 상태가 바뀌면 뷰에게 알려주고 가끔은 컨트롤러에도 알려주기도 한다.
만약 쇼핑몰 앱이라고 가정한다면 여기서 모델은 품목, 가격, 재고 등등의 항목일 것이다.
View
뷰는 클라이언트가 직접적으로 보는 모든 것이라고 생각하면 된다.
즉, 디자인 영역이며 html 파일이다.
Controller
컨트롤러는 앞서 자주 언급했던 그 컨트롤러가 맞다.
사용자가 특정 URL로 접속했을 때, 해당 경로는 어떤 뷰를 보여주어야 하는지에 대한 분기를 처리해주는 역할을 담당한다.
MVC design pattern in Nest
Nest에서도 MVC 패턴을 지원해주기 때문에
위의 MDN 공식문서처럼 SSR(Server Side Rendering)방식을 사용해서 풀스택으로 개발을 할 수 있다
새로운 프로젝트를 만들어보자.
nest new mvc_project
그리고 View를 담당할 template engine
이 필요하다. 아래와 같이 hbs
를 설치!
npm install --save hbs
그런 뒤, 프로젝트의 main.ts
로 이동하여 아래와 같이 사용할 view engine을 정의해주자.
main.ts
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(
AppModule,
);
// 현재 dir의 상위로 가면 public 폴더가 있다. 그걸 views를 꾸미기 위한 정적 자원(css, js)으로 쓰겠다고 명시
app.useStaticAssets(join(__dirname, '..', 'public'));
app.setBaseViewsDir(join(__dirname, '..', 'views')); // 위와 마찬가지로 views 폴더의 경로를 명시
app.setViewEngine('hbs');
await app.listen(3000);
}
bootstrap();
위에서 설치한 hbs
엔진은 프로젝트 내의 views
디렉터리의 .hbs
파일들을 렌더링 시켜주는 것이다.
main.ts
에서는 사용할 엔진과 View 파일들이 어디에 있는지에 대한 정의를 해줌
views/index.hbs
다음으로는 렌더링할 views
폴더를 만들고 그 안에 index.hbs
파일을 만들어 아래와 같이 타이핑
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>App</title>
</head>
<body>
{{ message }}
</body>
</html>
여기서 보여질 message라는 data는 다음 아래의 controller에서 오게 된다!
app.controller.ts
import { Get, Controller, Render } from '@nestjs/common';
@Controller()
export class AppController {
@Get()
@Render('index')
root() {
return { message: 'Hello world!' };
}
}
마지막으로 이제 컨트롤러와 연결시켜주도록 하자.
>npm run start:dev
명령으로 서버를 실행시키고, 접속하면 controller에서 보낸 message가 출력되어지면 성공이다.
이상으로 CSR과 SSR에 대한 내용에 대해서 간략하게 정리해보았고,
MVC 패턴에 대해서 알아보았으며 기본적인 컨트롤러와 뷰가 어떻게 소통하는지 알아보았다.
마지막으로 Nest에서 제공하는 MVC 패턴에 대한 프로젝트 설정까지 해보았다.
그렇지만 항상 MV*와 같은 패턴이 필요하라는 법은 없다! 끝!
'🌈 프로그래밍 > Nest JS' 카테고리의 다른 글
[ NestJS ] Interceptor와 AOP 패턴에 대해서 알아보자 (0) | 2022.03.22 |
---|---|
[ NestJS ] 파이프 디자인 패턴에 대해서 알아보자 (0) | 2022.03.14 |
[ NestJS ] Repository Pattern에 대하여 알아보자 (1) | 2022.02.09 |
[ NestJS + mongoose ] virtual field에 대하여 알아보자 (0) | 2022.02.08 |
[ Nest ] postgresDB를 이용한 CRUD 앱 만들기 (3) (0) | 2021.12.23 |