4. ºä ·£´õ¸µ
4.1. ¼Ò°³
À̹ø Àå¿¡¼´Â view-state ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© Ç÷ο쿡¼ ºä¸¦ ·£´õ¸µÇÏ´Â ¹æ¹ýÀ» »ìÆ캻´Ù.
4.2. ºä »óÅ Á¤ÀÇÇϱâ
view-state ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ºä¸¦ ·£´õ¸µÇÏ°í »ç¿ëÀÚ À̺¥Æ®¸¦ ´ë±âÇÏ´Â ÇÃ·Î¿ì ½ºÅÇÀ» Á¤ÀÇÇÑ´Ù.
<view-state id="enterBookingDetails">
<transition on="submit" to="reviewBooking" />
</view-state>
±Ô¾à¿¡ µû¶ó, view-state´Â ÀÚ½ÅÀÇ id¸¦ flow°¡ À§Ä¡ÇÑ µð·ºÅ͸®¿¡¼ ºä ÅÛÇø´À¸·Î ¸ÊÇÎÇÑ´Ù. ¿¹¸¦ µé¾î, ¸¸¾à¿¡ flow ÀÚü°¡ /WEB-INF/hotels/booking¿¡ ÀÖ´Ù¸é À§ÀÇ state´Â /WEB-INF/hotels/booking/enterBookingDetails.xhtmlÀ» ·£´õ¸µÇÒ °ÍÀÌ´Ù.
¾Æ·¡´Â ¿¹Á¦ µð·ºÅ͸® ±¸Á¶·Î ºä¿Í ¸Þ½ÃÁö ¹øµé °°Àº ±âŸ ¸®¼Ò½º°¡ ±×µéÀÇ Ç÷οì Á¤ÀÇ¿Í °°ÀÌ ÀÖ´Â °ÍÀ» º¸¿©ÁØ´Ù.
4.3. ºä ½Äº°ÀÚ ÀÛ¼ºÇϱâ
view ¼Ó¼ºÀ» »ç¿ëÇÏ¿© ·£´õ¸µ ÇÒ ºä¸¦ ¸í½ÃÀûÀ¸·Î ±âÀÔÇÑ´Ù.
4.3.1. ÇÃ·Î¿ì »ó´ë ºä id
ºä id´Â Ç÷ο찡 ÀÖ´Â ÀÛ¾÷ µð·ºÅ͸®¿¡ À§Ä¡ÇÑ ºä ¸®¼Ò½º¿¡ ´ëÇÑ »ó´ë °æ·Î°¡ µÉ ¼ö ÀÖ´Ù.
<view-state id="enterBookingDetails" view="bookingDetails.xhtml">
4.3.2. Àý´ë ºä id
ºä id´Â À¥ ¾ÖÇø®ÄÉÀÌ¼Ç ·çÆ® µð·ºÅ͸®¿¡ ÀÖ´Â ºäÀÇ Àý´ë °æ·Î°¡ µÉ ¼öµµ ÀÖ´Ù.
<view-state id="enterBookingDetails" view="/WEB-INF/hotels/booking/bookingDetails.xhtml">
4.3.3. ³í¸® ºä id
½ºÇÁ¸µ MVCÀÇ ºä ÇÁ·¹ÀÓ¿öÅ© °°Àº ¸î¸î ºä ÇÁ·¹ÀÓ¿öÅ©¿¡¼ ºä id´Â ÇÁ·¹ÀÓ¿öÅ©°¡ ÆÇ´ÜÇÒ ?? »ç¿ëÇÒ ³í¸®ÀûÀÎ ½Äº°ÀÚ°¡ µÉ ¼öµµ ÀÖ´Ù.
<view-state id="enterBookingDetails" view="bookingDetails">
½ºÇÁ¸µ MVC ¿¬µ¿ »Ó¿¡¼ ¾î¶»°Ô MVC ViewResolver ±â¹Ý ½Ã¼³°ú ¿¬µ¿ÇÏ´ÂÁö ´õ ¸¹Àº Á¤º¸¸¦ »ìÆ캸µµ·Ï ÇÏÀÚ.
4.4. ºä ½ºÄÚÇÁ
view-state´Â µé¾î¿Ã ¶§¸¶´Ù »õ·Î¿î viewScopeÀ» ÇÒ´çÇÑ´Ù. ÀÌ ½ºÄÚÇÁ´Â Ajax ¿äûó·³ °°Àº ºä¿¡¼ ¿©·¯ ¿äû¿¡ °ÉÃÄ °´Ã¼¸¦ Á¶ÀÛÇÒ ¶§ À¯¿ëÇÏ´Ù. view-state´Â ÇØ´ç state¸¦ ³ª°¥ ¶§ viewScopeÀ» ¼Ò¸êÇÑ´Ù.
4.4.1. ºä º¯¼ö ÇÒ´çÇϱâ
var ű׸¦ »ç¿ëÇÏ¿© ºä º¯¼ö¸¦ ¼±¾ðÇÑ´Ù. ÇÃ·Î¿ì º¯¼öó·³, ºä »óÅ°¡ ´Ù½Ã ½ÃÀÛÇÏ¸é ¸ðµç @Autowired ·¹ÆÛ·±½º¸¦ ÀÚµ¿À¸·Î º¹¿øÇÑ´Ù.
<var name="searchCriteria" class="com.mycompany.myapp.hotels.SearchCriteria" />
4.4.2. viewScope º¯¼ö ÇÒ´çÇϱâ
on-render ű׸¦ »ç¿ëÇÏ¿© ºä ·£´õ¸µÇϱâ Àü¿¡ ¾×¼Ç °á°ú¿¡ º¯¼ö¸¦ ÇÒ´çÇÑ´Ù.
<on-render>
<evaluate expression="bookingService.findHotels(searchCriteria)" result="viewScope.hotels" />
</on-render>
4.4.3. ºä ½ºÄÚÇÁ¿¡ ÀÖ´Â °´Ã¼ Á¶ÀÛÇϱâ
ºä ½ºÄÚÇÁ¿¡ ÀÖ´Â °´Ã¼´Â º¸Åë µ¿ÀÏÇÑ ºä¿¡¼ ¿©·¯ ¿äû¿¡ ÀÇÇØ Á¶À۵ȴÙ. ´ÙÀ½ ¿¹Á¦ ÆäÀÌÁö´Â °Ë»ö °á°ú ¸ñ·ÏÀ» º¸¿©ÁØ´Ù. ¸ñ·ÏÀº ¸Å¹ø ·£´õ¸µ Çϱâ Àü¿¡ ºä ½ºÄÚÇÁ¿¡¼ ¼öÁ¤µÈ´Ù. ºñµ¿±â À̺¥Æ® Çڵ鷯°¡ ÇöÀç µ¥ÀÌÅÍ ÆäÀÌÁö¸¦ ¼öÁ¤ÇÏ°í °Ë»ö °á°ú ºÎºÐ¿¡ ´ëÇÑ ¿äûÀ» ´Ù½Ã ·£´õ¸µ ÇÑ´Ù.
<view-state id="searchResults">
<on-render>
<evaluate expression="bookingService.findHotels(searchCriteria)"
result="viewScope.hotels" />
</on-render>
<transition on="next">
<evaluate expression="searchCriteria.nextPage()" />
<render fragments="searchResultsFragment" />
</transition>
<transition on="previous">
<evaluate expression="searchCriteria.previousPage()" />
<render fragments="searchResultsFragment" />
</transition>
</view-state>
4.5. render ¾×¼Ç ½ÇÇàÇϱâ
on-render ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ºä ·£´õ¸µÀ» ÇϱâÀü¿¡ ÇÑ °³ ÀÌ»óÀÇ ¾×¼ÇÀ» ½ÇÇàÇÑ´Ù. ºäÀÇ ÀϺθ¸ ´Ù½Ã ·£´õ¸µÇÏ´Â °ÍÀ» Æ÷ÇÔÇÏ¿© ·£´õ ¾×¼ÇÀº ÀÌÈÄÀÇ ¸®ÇÁ·¡½Ã¿Í ¸¶Âù°¡Áö·Î Ãʱ⠷£´õ¸µ ´Ü°è¿¡ ½ÇÇàµÈ´Ù.
<on-render>
<evaluate expression="bookingService.findHotels(searchCriteria)" result="viewScope.hotels" />
</on-render>
4.6. ¸ðµ¨·Î ¹ÙÀεùÇϱâ
model ¼Ó¼ºÀ» »ç¿ëÇÏ¿© ºä¸¦ ¹ÙÀεùÇÒ ¸ðµ¨ °´Ã¼¸¦ ¼±¾ðÇÑ´Ù. ÀÌ ¼Ó¼ºÀº º¸Åë Æû °°Àº µ¥ÀÌÅÍ ÄÁÆ®·ÑÀ» ·£´õ¸µÇÏ´Â ºä¶û °°ÀÌ »ç¿ëÇÑ´Ù. Æû µ¥ÀÌÅÍ ¹ÙÀεù°ú °ËÁõ ÀÛ¾÷À» ¸ðµ¨ °´Ã¼¿¡ ´ëÇÑ ¸ÞŸµ¥ÀÌÅÍ·Î ÁÖµµÇÒ ¼ö ÀÖ´Ù.
´ÙÀ½ ¿¹´Â booking ¸ðµ¨À» ´Ù·ç´Â enterBookingDetails State´Ù.
<view-state id="enterBookingDetails" model="booking">
¸ðµ¨Àº flowScope ¶Ç´Â viewScope °°ÀÌ Á¢±Ù °¡´ÉÇÑ ¸ðµç ½ºÄÚÇÁ¿¡ ÀÖ´Â °´Ã¼´Ù. modelÀ» Á¤ÀÇÇÏ¸é ºä À̺¥Æ®°¡ ¹ß»ýÇÒ ¶§ ´ÙÀ½ ÀÛ¾÷ÀÌ ÀÌ·ïÁø´Ù.
- ºä¿¡¼ ¸ðµ¨·Î ¹ÙÀεù. ºä Æ÷½ºÆ®¹é(postback)À» ÇÒ ¶§ »ç¿ëÀÚ ÀÔ·Â °ªÀ» ¸ðµ¨ °´Ã¼ ¼Ó¼ºÀ¸·Î ¹ÙÀεùÇÑ´Ù.
- ¸ðµ¨ °ËÁõ. ¹ÙÀεùÀ» ÇÑ ´ÙÀ½, ¸¸¾à ¸ðµ¨ °´Ã¼°¡ °ËÁõÀ» ÇÊ¿ä·Î Çϸé, °ËÁõ ·ÎÁ÷À» È£ÃâÇÑ´Ù.
ºä »óÅ ÀüÀ̸¦ ÇÒ ¼ö ÀÖ´Â Ç÷οì À̺¥Æ®°¡ ¹ß»ýÇÒ ¶§, ¸ðµ¨ ¹ÙÀεùÀº ¹Ýµå½Ã ¼º°øÀûÀ¸·Î ¿Ï·áµÇ¾î¾ß ÇÑ´Ù. ¸¸¾à ¹ÙÀεùÀÌ ½ÇÆÐÇϸé, ºä´Â ´Ù½Ã ·£´õ¸µÇÏ¿© »ç¿ëÀÚ°¡ ´Ù½Ã ÆíÁýÇÒ ¼ö ÀÖ°Ô ÇÑ´Ù.
4.7. ŸÀÔ º¯È¯ ¼öÇàÇϱâ
ºä Æ÷½ºÆ®¹éÀ» ÇÒ ¶§ ¸ðµ¨ ¹ÙÀεùÀÌ ¹ß»ýÇϸé, ¹ÙÀεù ½Ã½ºÅÛÀº ÇÊ¿äÇÏ´Ù¸é ÀÔ·Â °ªÀ» Ÿ°Ù ¸ðµ¨ ¼Ó¼º ŸÀÔÀ¸·Î º¯È¯À» ½ÃµµÇÒ °ÍÀÌ´Ù. ¼ýÀÚµé°ú ±âº»Å¸ÀÔ, À̳Ñ, ±×¸®°í Date¿¡ ´ëÇÑ ±âº» ÄÁ¹öÅÍ(Converter)´Â ÀÚµ¿À¸·Î Àû¿ëµÈ´Ù. »ç¿ëÀÚ´Â ¶ÇÇÑ ÀڽŵéÀÌ Á÷Á¢ Á¤ÀÇÇÑ Å¸ÀÔ¿¡ ´ëÇÑ ÄÁ¹öÅ͸¦ µî·ÏÇÒ ¼ö ÀÖ°í ±âº» ÄÁ¹öÅ͸¦ ÀçÁ¤ÀÇ ÇÒ ¼öµµ ÀÖ´Ù.
4.7.1. ÄÁ¹öÅÍ ±¸ÇöÇϱâ
ÄÁ¹öÅ͸¦ ±¸ÇöÇÏ·Á¸é, org.springframework.binding.convert.converters.TwoWayConverter ÀÎÅÍÆäÀ̽º¸¦ ±¸ÇöÇ϶ó. ÀԷ°ªÀ¸·Î ¹®ÀÚ¿À» ¹Þ¾Æ¼ »ç¿ëÀÚ°¡ Á¤ÀÇÇÑ °´Ã¼·Î º¯°æÇÏ´Â ÄÁ¹öÅ͸¦ ¸¸µé ¶§ ÀÌ ÀÎÅÍÆäÀ̽º ±¸ÇöÀ» Æí¸®ÇÏ°Ô ÇØÁÖ´Â ±âº» Ŭ·¡½º StringToObject¸¦ Á¦°øÇÑ´Ù. °£´ÜÇÏ°Ô ÀÌ Å¬·¡½½¸£ »ó¼ÓÇÏ°í µÎ °³ÀÇ ¸Å¼µå¸¦ ÀçÁ¤ÀÇÇÏ¸é µÈ´Ù.
protected abstract Object toObject(String string, Class targetClass) throws Exception;
protected abstract String toString(Object object) throws Exception;
toObject(String, Class)´Â ÀÔ·Â ¹®ÀÚ¿À» °´Ã¼ ŸÀÔÀ¸·Î ¹Ù²ã¾ß ÇÏ°í toString(Object)´Â ±× ¹Ý´ë ÀÏÀ» ÇØ¾ß ÇÑ´Ù.
´ÙÀ½ ¿¹Á¦´Â ¹®ÀÚ¿À» MonetaryAmount·Î º¯È¯ÇÏ´Â ÄÁ¹öÅÍ´Ù.
public class StringToMonetaryAmount extends StringToObject {
public StringToMonetaryAmount() {
super(MonetaryAmount.class);
}
@Override
protected Object toObject(String string, Class targetClass) {
return MonetaryAmount.valueOf(string);
}
@Override
protected String toString(Object object) {
MonetaryAmount amount = (MonetaryAmount) object;
return amount.toString();
}
}
´õ ¸¹Àº ÄÁ¹öÅÍ ±¸Çö ¿¹Á¦¸¦ º¸°í ½Í´Ù¸é org.springframework.binding.convert.converters ÆÐÅ°Áö¿¡ ¹Ì¸® ¸¸µé¾îµÐ ÄÁ¹öÅ͵éÀ» Âü°íÇ϶ó.
4.7.2. ÄÁ¹öÅÍ µî·ÏÇϱâ
¿©·¯ºÐÀÌ ÀÛ¼ºÇÑ ÄÁ¹öÅ͸¦ µî·ÏÇϰųª ±âº» ÄÁ¹öÅ͸¦ º¯°æÇÏ°í ½Í´Ù¸é, org.springframework.binding.convert.service.DefaultConversionService¸¦ »ó¼ÓÇÏ°í addDefaultConverters() ¸Å¼µå¸¦ ÀçÁ¤ÀÇ Ç϶ó. addConverter(Converter) ¸Å¼µå¸¦ »ç¿ëÇÏ¿© String°ú MonetaryAmount °°Àº µÎ ŸÀÔÀ» º¯È¯ÇÒ ¶§ »ç¿ëÇÒ ÁÖ¿ä ÄÁ¹öÅÍ(Primary Converter)¸¦ µî·ÏÇ϶ó. ºÎ°¡ÀûÀ¸·Î addConverter(String, Converter)¸¦ »ç¿ëÇÏ¿© °°Àº ŸÀÔ¿¡ ´ëÇÑ ¿©·¯ ´ëü ÄÁ¹öÅÍ(Alternate Converter)¸¦ µî·ÏÇÒ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¾î, java.util.Date¸¦ ¿©·¯ ÇüÅÂÀÇ ¹®ÀÚ¿·Î º¯È¯ÇÒ ¼ö ÀÖ°Ú´Ù.
´ëü ÄÁ¹öÅÍ´Â À¯ÀÏÇÑ converterId·Î À妽ÌÀ» Çϴµ¥ ¸ðµ¨ ¹ÙÀεùÀ» ¼³Á¤ÇÒ ¶§ ÂüÁ¶ÇÒ ¼ö ÀÖ´Ù. converterId¸¦ ÁöÁ¤ÇÏÁö ¾ÊÀ¸¸é ÁÖ¿ä ÄÁ¹öÅ͸¦ »ç¿ëÇÑ´Ù.
ConversionService´Â À¥ Ç÷ο찡 ·±Å¸ÀÓ¿¡ ¾î¶² ŸÀÔÀ» ´Ù¸¥ ŸÀÔÀ¸·Î º¯È¯ ÇØÁÖ´Â º¯È¯ ½ÇÇà±â¸¦ ·è¾÷ÇÒ ¶§ »ç¿ëÇÏ´Â °´Ã¼´Ù. ¾ÖÇø®ÄÉÀÌ¼Ç ´ç ÇϳªÀÇ ConversionService°¡ ÀÖ´Ù.
System Setup ÀýÀ» ÂüÁ¶ÇÏ¿© ¾ÖÇø®ÄÉÀÌ¼Ç Àü¹Ý¿¡ °ÉÃÄ Ä¿½ºÅÒ ÄÁ¹öÅ͸¦ µî·ÏÇÏ´Â ConversionService ±¸Çöü¸¦ ¼³Á¤ÇÏ´Â ¹æ¹ýÀ» »ìÆ캸¶ó. ¶ÇÇÑ ÀÚ¼¼ÇÑ ³»¿ëÀº Convert API¸¦ Âü°íÇ϶ó.
4.8. ¹ÙÀεù ¹æÁöÇϱâ
bind ¼Ó¼ºÀ» »ç¿ëÇÏ¿© ƯÁ¤ ºä À̺¥Æ®¿¡ ´ëÇÑ °ËÁõ°ú ¸ðµ¨ ¹ÙÀεùÀ» ¹æÁöÇÒ ¼ö ÀÖ´Ù. ´ÙÀ½ ¿¹´Â cancel À̺¥Æ®°¡ ¹ß»ýÇßÀ» ¶§ ¹ÙÀεùÀ» ¹æÁöÇÑ´Ù.
<view-state id="enterBookingDetails" model="booking">
<transition on="proceed" to="reviewBooking">
<transition on="cancel" to="bookingCancelled" bind="false" />
</view-state>
4.9. ¸í½ÃÀûÀ¸·Î ¹ÙÀεù ¼³Á¤Çϱâ
binder ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ºä¿¡¼ »ç¿ëÇÒ ¼ö ÀÖ´Â ¸ðµ¨ ¹ÙÀεù ÁýÇÕÀ» ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. ÀÌ°ÍÀº ƯÈ÷ ½ºÇÁ¸µ MVC ȯ°æ¿¡¼ ºä ¸¶´Ù "Çã¿ëÇÏ´Â ÀԷ°ª" ÁýÇÕÀ» Á¦ÇÑÇÒ ¶§ À¯¿ëÇÏ´Ù.
<view-state id="enterBookingDetails" model="booking">
<binder>
<binding property="creditCard" />
<binding property="creditCardName" />
<binding property="creditCardExpiryMonth" />
<binding property="creditCardExpiryYear" />
</binder>
<transition on="proceed" to="reviewBooking" />
<transition on="cancel" to="cancel" bind="false" />
</view-state>
¸¸¾à¿¡ binder ¿¤¸®¸ÕÆ®¸¦ ¼³Á¤ÇÏÁö ¾ÊÀ¸¸é ¸ðµ¨ÀÇ ¸ðµç public ¼Ó¼ºÀÌ ºä¿¡¼ ¹ÙÀεùÇÏ´Â ´ë»óÀÌ µÈ´Ù. binder ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ¿ÀÁ÷ ¸í½ÃÀûÀ¸·Î Ç¥ÇöÇÑ ¼Ó¼º¸¸ ¹ÙÀεù ÇÑ´Ù.
°¢°¢ÀÇ ¹ÙÀεùÀº ÄÁ¹öÅ͸¦ Àû¿ëÇÏ¿© ¸ðµ¨ ¼Ó¼º °ªÀ» »ç¿ëÀÚ¿¡°Ô Àͼ÷ÇÑ ÇüÅ·Πº¯°æÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù. ¸¸¾à ÄÁ¹öÅ͸¦ ¸í½ÃÇÏÁö ¾ÊÀ¸¸é ¸ðµ¨ ¼Ó¼º ŸÀÔ¿¡ µû¶ó ±âº» ÄÁ¹öÅ͸¦ »ç¿ëÇÏ°Ô µÈ´Ù.
<view-state id="enterBookingDetails" model="booking">
<binder>
<binding property="checkinDate" converter="shortDate" />
<binding property="checkoutDate" converter="shortDate" />
<binding property="creditCard" />
<binding property="creditCardName" />
<binding property="creditCardExpiryMonth" />
<binding property="creditCardExpiryYear" />
</binder>
<transition on="proceed" to="reviewBooking" />
<transition on="cancel" to="cancel" bind="false" />
</view-state>
À§ÀÇ ¿¹Á¦¿¡¼ shortDate ÄÁ¹öÅ͸¦ chekingDate¿Í checkoutDate ¼Ó¼º¿¡ Àû¿ëÇÏ°í ÀÖ´Ù. Ä¿½ºÅÒ ÄÁ¹öÅ͸¦ ¾ÖÇø®ÄÉÀ̼ÇÀÇ ConventionService·Î µî·ÏÇÒ ¼öµµ ÀÖ´Ù.
°¢°¢ÀÇ ¹ÙÀεùÀº ¶ÇÇÑ Çʼö ¿©ºÎ¸¦ È®ÀÎÇÏ¿© »ç¿ëÀÚ°¡ ÀÔ·ÂÇÑ °ªÀÌ ºñ¾îÀÖ´Ù¸é °ËÁõ ¿¡·¯¸¦ ¹ß»ý½ÃÅ°µµ·Ï ÇÒ ¼ö ÀÖ´Ù.
<view-state id="enterBookingDetails" model="booking">
<binder>
<binding property="checkinDate" converter="shortDate" required="true" />
<binding property="checkoutDate" converter="shortDate" required="true" />
<binding property="creditCard" required="true" />
<binding property="creditCardName" required="true" />
<binding property="creditCardExpiryMonth" required="true" />
<binding property="creditCardExpiryYear" required="true" />
</binder>
<transition on="proceed" to="reviewBooking">
<transition on="cancel" to="bookingCancelled" bind="false" />
</view-state>
À§ÀÇ ¿¹Á¦¿¡¼ ¸ðµç ¹ÙÀεùÀ» Çʼö·Î ¼³Á¤Çß´Ù. ¸¸¾à ¹ÙÀεù ÇÒ ÀԷ°ªÀÌ Çϳª¶óµµ ºñ¾ú´Ù¸é ¿¡·¯¸¦ ¸¸µé°í ºä¸¦ ¿¡·¯¿Í ÇÔ²² ´Ù½Ã º¸¿©ÁÙ °ÍÀÌ´Ù.
4.10. ¸ðµ¨ °ËÁõÇϱâ
¸ðµ¨ °ËÁõÀº µµµ¨ °´Ã¼¿¡ ±â¹ÝÇÏ¿© ¼³Á¤ÇÑ Á¦¾à»çÇ×À¸·Î ÁÖµµÇÑ´Ù. À¥ Ç÷οì´Â ±×·¯ÇÑ Á¦¾à »çÇ×À» ÇÁ·Î±×·¡¹ÖÀ¸·Î Á¦°øÇÑ´Ù.
4.10.1. ÇÁ·Î±×·¡¹ÖÀûÀÎ °ËÁõ
¸ðµ¨ °ËÁõÀ» ÇÁ·Î±×·¡¹ÖÀûÀ¸·Î ¼öÇàÇÏ´Â µÎ °¡Áö ¹æ¹ýÀÌ ÀÖ´Ù. Çϳª´Â °ËÁõ ·ÎÁ÷À» ¸ðµ¨ °´Ã¼ ³»ºÎ¿¡ ±¸ÇöÇÏ´Â °ÍÀÌ´Ù. µÎ ¹ø°´Â º°µµÀÇ Validator¸¦ ±¸ÇöÇÏ´Â °ÍÀÌ´Ù. µÎ °¡Áö ¹æ¹ý ¸ðµÎ ValidationContext¸¦ »ç¿ëÇÏ¿© ¿¡·¯ ¸Þ½ÃÁö¸¦ ±â·ÏÇÏ°í ÇöÀç »ç¿ëÀÚ Á¤º¸¿¡ Á¢±ÙÇÒ ¼ö ÀÖ´Ù.
4.10.1.1. ¸ðµ¨ °ËÁõ ¸Å¼µå ±¸ÇöÇϱâ
¸ðµ¨ °´Ã¼ ³»ºÎ¿¡ °ËÁõ ·ÎÁ÷À» Á¤ÀÇÇÏ´Â °ÍÀº ±× »óŸ¦ °ËÁõÇÏ´Â °¡Àå °£´ÜÇÑ ¹æ¹ýÀÌ´Ù. ÇÑ ¹ø ÀÌ·± ·ÎÁ÷À» À¥ ÇÃ·Î¿ì ±Ô¾à¿¡ ¸Â°Ô ¸¸µé¾î µÎ¸é À¥ Ç÷ο찡 ÀÚµ¿À¸·Î ±× ·ÎÁ÷À» view-state Æ÷½ºÆ®¹é ¶óÀÌÇÁ»çÀÌŬ µ¿¾È¿¡ È£ÃâÇÒ °ÍÀÌ´Ù. À¥ Ç÷α¸ ±Ô¾àÀº ºä¿¡¼ ¼öÁ¤ÇÏ´Â ¸ðµ¨ ¼Ó¼º ¼ºê¼ÂÀ» ½±°Ô °ËÁõÇÒ ¼ö ÀÖ°Ô ÇØÁØ´Ù. ÀÌ·¸°Ô ÇÏ·Á¸é °£´ÜÇÏ°Ô validate${state} ÇüÅÂÀÇ À̸§À» °¡Áø public ¸Å¼µå¸¦ ¸¸µé¸é µÈ´Ù. ${state}´Â °ËÁõÀ» ¼öÇàÇÒ view-stateÀÇ id´Ù. ¿¹¸¦ º¸ÀÚ.
public class Booking {
private Date checkinDate;
private Date checkoutDate;
...
public void validateEnterBookingDetails(ValidationContext context) {
MessageContext messages = context.getMessages();
if (checkinDate.before(today())) {
messages.addMessage(new MessageBuilder().error().source("checkinDate").
defaultText("Check in date must be a future date").build());
} else if (!checkinDate.before(checkoutDate)) {
messages.addMessage(new MessageBuilder().error().source("checkoutDate").
defaultText("Check out date must be later than check in date").build());
}
}
}
À§ ¿¹Á¦¿¡¼, Booking ¸ðµ¨À» ÆíÁýÇÏ´Â enterBookingDetails view-state·Î ÀüÀÌ°¡ ¹ß»ýÇϸé À¥ Ç÷οì´Â ÇØ´ç ÀüÀÌ¿¡ °ËÁõÀ» ¹æÁöÇÏÁö ¾Ê¾Ò´Ù¸é validateEnterBookingDetails(ValidationContext) ¸Å¼µå¸¦ ÀÚµ¿À¸·Î È£ÃâÇÑ´Ù. ±×·± view-state ¿¹Á¦´Â ¾Æ·¡¿Í °°´Ù.
<view-state id="enterBookingDetails" model="booking">
<transition on="proceed" to="reviewBooking">
</view-state>
¸ðµç °ËÁõ ¸Þ¼Òµå¸¦ Á¤ÀÇÇß´Ù. ÀϹÝÀûÀ¸·Î Ç÷οì´Â ¸ðµ¨À» ¿©·¯ ºä¿¡¼ ÆíÁýÇÑ´Ù. ÀÌ °æ¿ì¿¡ °ËÁõÀ» ¼öÇàÇÒ ÇÊ¿ä°¡ ÀÖ´Â °¢°¢ÀÇ view-state¿¡ ´ëÇÑ °ËÁõ ¸Å¼µå¸¦ Á¤ÀÇÇßÀ» °ÍÀÌ´Ù.
4.10.1.2. Validator ±¸ÇöÇϱâ
µÎ ¹ø° ¹æ¹ýÀº ¸ðµ¨ °´Ã¼¸¦ °ËÁõÇÒ Validator¶ó°í ÇÏ´Â º°µµÀÇ °´Ã¼¸¦ Á¤ÀÇÇÏ´Â °ÍÀÌ´Ù. ±×·¸°Ô ÇÏ·Á¸é ¿ì¼± ${model}Validator ÆÐÅÏÀÇ À̸§À» °¡Áø Ŭ·¡½º¸¦ ¸¸µç´Ù. ${model}Àº booking °°Àº ¸ðµ¨ Ç¥Çö½Ä ÇüŸ¦ ¶è´Ù. ±×·± ´ÙÀ½ validate${state} ÇüÅÂÀÇ À̸§À» °¡Áø ¸Å¼µå¸¦ Á¤ÀÇÇÑ´Ù. ${state}´Â enteringBookingDetails°°Àº view-state id¿¡ ÇØ´çÇÑ´Ù. Ŭ·¡½º´Â ½ºÇÁ¸µ ºóÀ¸·Î ¹èÆ÷µÉ ¼ö ÀÖ¾î¾ß ÇÑ´Ù. ¿©·¯ °ËÁõ ¸Å¼µå¸¦ Á¤ÀÇÇÒ ¼ö ÀÖ´Ù, ¿¹Á¦¸¦ º¸ÀÚ.
@Component
public class BookingValidator {
public void validateEnterBookingDetails(Booking booking, ValidationContext context) {
MessageContext messages = context.getMessages();
if (booking.getCheckinDate().before(today())) {
messages.addMessage(new MessageBuilder().error().source("checkinDate").
defaultText("Check in date must be a future date").build());
} else if (!booking.getCheckinDate().before(booking.getCheckoutDate())) {
messages.addMessage(new MessageBuilder().error().source("checkoutDate").
defaultText("Check out date must be later than check in date").build());
}
}
}
À§ ¿¹Á¦¿¡¼ Booking ¸ðµ¨À» ÆíÁýÇÏ´Â enterBookingDetilas view-state·Î ÀüÀÌ°¡ ¹ß»ýÇϸé À¥ Ç÷οì´Â validateEnterBookingDetails(Booking, ValidationContext) ¸Å¼µå¸¦ ÀÚµ¿À¸·Î È£ÃâÇÒ °ÍÀÌ´Ù. ´Ü À̶§ ÇØ´ç ÀüÀÌ¿¡ ´ëÇÑ °ËÁõÀ» ¹æÁöÇÑ »óÅ°¡ ¾Æ´Ï¾î¾ß ÇÑ´Ù.
¶ÇÇÑ Validator´Â ½ºÇÁ¸µ MVCÀÇ Errors °´Ã¼·Î ¹ÞÀ» ¼ö ÀÖ´Ù. ÀÌ °´Ã¼´Â ±âÁ¸ÀÇ ½ºÇÁ¸µ °ËÁõ±â¸¦ È£ÃâÇÒ ¶§ Çʼö´Ù.
°ËÁõ±â´Â ½ºÇÁ¸µ ºóÀ¸·Î µî·ÏµÇ¾î¾ß ÇÏ°í ${model}Validator ¶ó´Â À̸§ ±Ô¾àÀ» ÁöÄÑ¾ß ÇÑ´Ù ±×·³ ÀÚµ¿À¸·Î °¨ÁöµÇ°í È£ÃâµÈ´Ù. À§ ¿¹Á¦¿¡¼ ½ºÇÁ¸µ 2.5 Ŭ·¡½ºÆнº-½ºÄµÀ» ÇÏ°Ô µÇ¸é @Component¸¦ °¨ÁöÇÏ°í ÀÚµ¿À¸·Î bookingValidator¶ó´Â À̸§ÀÇ ºóÀ¸·Î µî·ÏÀÌ µÈ´Ù. ±×·¯¸é bokking ¸ðµ¨ °ËÁõÀÌ ÇÊ¿äÇÒ ¶§ ÀÌ bookingValidator ÀνºÅϽº°¡ È£ÃâµÉ °ÍÀÌ´Ù.
4.10.2. ValidationContext
ValidationContext´Â MessageContext¸¦ °¡Á®¿Í¼ °ËÁõÀ» ÇÏ´Â µ¿¾È ¸Þ½ÃÁö¸¦ ±â·ÏÇÑ´Ù. ¶ÇÇÑ userEvent¿Í ÇöÀç »ç¿ëÀÚÀÇ Principal °°ÀÌ ÇöÀç »ç¿ëÀÚ¿¡ ´ëÇÑ Á¤º¸¸¦ °ø°³ÇÑ´Ù. ÀÌ·¯ÇÑ Á¤º¸´Â °ËÁõ ·ÎÁ÷À» Á¢¼ÓÇÑ »ç¿ëÀÚ ¶Ç´Â UIÀÇ ¾î¶² ¹öÆ° ¶Ç´Â ¸µÅ©¿¡ ±â¹ÝÇÏ¿© Ä¿½ºÅ͸¶ÀÌ¡ ÇÒ ¼ö ÀÖµµ·Ï ÇØÁØ´Ù. ÀÚ¼¼ÇÑ Á¤º¸´Â ValidationContext API¸¦ Âü°íÇ϶ó.
4.11. °ËÁõ ¹æÁöÇϱâ
validate ¼Ó¼ºÀ» »ç¿ëÇÏ¿© ƯÁ¤ ºä À̺¥Æ®¿¡ ´ëÇÑ ¸ðµ¨ °ËÁõÀ» ¹æÁöÇÒ ¼ö ÀÖ´Ù.
<view-state id="chooseAmenities" model="booking">
<transition on="proceed" to="reviewBooking">
<transition on="back" to="enterBookingDetails" validate="false" />
</view-state>
À§ ¿¹Á¦´Â back À̺¥Æ®°¡ ¹ß»ýÇÒ °æ¿ì ¹ÙÀεùÀº ÇÏÁö¸¸ °ËÁõÀº ÇÏÁö ¾Ê´Â´Ù.
4.12. ºä ÀüÀÌ ½ÇÇàÇϱâ
Çϳª ¶Ç´Â ±× ÀÌ»óÀÇ transition ¿¤¸®¸ÕÆ®¸¦ Á¤ÀÇÇÏ¿© ºä¿¡¼ ¹ß»ýÇÏ´Â »ç¿ëÀÚ À̺¥Æ®¸¦ ´Ù·ê ¼ö ÀÖ´Ù. Æ®·£Áö¼ÇÀº »ç¿ëÀÚÇÑÅ× ´Ù¸¥ ºä¸¦ º¸¿©Áְųª ´Ü¼øÇÏ°Ô ¾×¼ÇÀ» ½ÇÇàÇϰųª ÇöÀç ºä¸¦ ´Ù½Ã º¸¿©ÁÖ´Â ÀÏÀ» ÇÑ´Ù. ¶ÇÇÑ Æ®·£Áö¼ÇÀº ¾ÖÀÌÀÛ½º(Ajax)¸¦ ´Ù·ê ¶§ ÇÁ·¹±×¸ÕÃ÷("fragments")¶ó°í ÇÏ´Â ºäÀÇ ÀϺθ¦ ´Ù½Ã º¸¿©ÁÖ±æ ¿äûÇÒ ¼öµµ ÀÖ´Ù. ¸¶Áö¸·À¸·Î ±Û·Î¹ú("global") Æ®·£Áö¼ÇÀ̶ó°í ÇÏ´Â ¿©·¯ ºä¿¡ °ÉÃļ °øÀ¯ÇÏ´Â °ÍÀ» Á¤ÀÇÇÒ ¼öµµ ÀÖ´Ù.
ºä Æ®·£Áö¼ÇÀ» Á¤ÀÇÇÏ´Â ¹æ¹ýÀ» ´ÙÀ½ Àý¿¡¼ »ìÆ캸µµ·Ï ÇÏÀÚ.
4.12.1. Æ®·£Áö¼Ç ¾×¼Ç
view-state Æ®·£Áö¼ÇÀ» ¼öÇàÇϱâ Àü¿¡ Çϳª ¶Ç´Â ±× ÀÌ»óÀÇ ¾×¼ÇÀ» ½ÇÇàÇÒ ¼ö ÀÖ´Ù. ÀÌ·¯ÇÑ ¾×¼ÇÀº ¾Æ¸¶ ÇöÀç view-state¸¦ Á¾·áÇÏÁö ¸øÇÏ°Ô ¿¡·¯ °á°ú¸¦ ¹ÝȯÇÒ ¼öµµ ÀÖ´Ù. ¸¸¾à ¿¡·¯ °á°ú°¡ ÀÖ´Ù¸é, ºä´Â ´Ù½Ã º¸¿©Áú °ÍÀÌ¸ç »ç¿ëÀÚ¿¡°Ô ÀûÀýÇÑ ¸Þ½ÃÁö¸¦ º¸¿©ÁÙ °ÍÀÌ´Ù.
¸¸¾à Æ®·£Áö¼Ç ¾×¼ÇÀÌ ÀÏ¹Ý ÀÚ¹Ù ¸Å¼µå¸¦ È£ÃâÇϸé, È£ÃâµÈ ¸Å¼µå´Â false¸¦ ¹ÝȯÇÏ¿© Æ®·£Áö¼Ç ½ÇÇàÀ» ¹æÁöÇÒ ¼ö ÀÖ´Ù. ÀÌ·± ±â¼úÀº ¼ºñ½º-°èÃþ ¸Å¼µå¿¡¼ ¹ß»ýÇÑ ¿¹¿Ü¸¦ ´Ù·ê ¶§ »ç¿ëÇÒ ¼ö ÀÖ°Ú´Ù. ¾Æ·¡ ¿¹Á¦´Â ¼ºñ½º¸¦ È£ÃâÇÏ´Â ¾×¼ÇÀ» È£ÃâÇÏ°í ¿¹¿Ü »óȲÀ» ´Ù·é´Ù.
<transition on="submit" to="bookingConfirmed">
<evaluate expression="bookingAction.makeBooking(booking, messageContext)" />
</transition>
public class BookingAction {
public boolean makeBooking(Booking booking, MessageContext context) {
try {
bookingService.make(booking);
return true;
} catch (RoomNotAvailableException e) {
context.addMessage(builder.error().
.defaultText("No room is available at this hotel").build());
return false;
}
}
}
4.12.2. Global Æ®·£Áö¼Ç
Ç÷οìÀÇ global-transitions ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© ¿©·¯ ºä¿¡ °ÉÃÄ Àû¿ëÇÒ Æ®·£Áö¼ÇÀ» »ý¼ºÇÑ´Ù, Global-transitionÀº Á¾Á¾ ·¹À̾ƿôÀ» ±¸¼ºÇÏ´Â ¸Þ´º ¸µÅ© °°Àº °ÍÀ» ´Ù·ê ¶§ »ç¿ëÇÑ´Ù.
<global-transitions>
<transition on="login" to="login">
<transition on="logout" to="logout">
</global-transitions>
4.12.3. À̺¥Æ® Çڵ鷯
view-state¿¡¼ Ÿ°ÙÀÌ ¾ø´Â Æ®·£Áö¼ÇÀ» Á¤ÀÇÇÒ ¼öµµ ÀÖ´Ù. ÀÌ·¯ÇÑ Æ®·£Áö¼ÇÀ» "À̺¥Æ® Çڵ鷯"¶ó°í ÇÑ´Ù.
<transition on="event">
<!-- Handle event -->
</transition>
ÀÌ·± À̺¥Æ® Çڵ鷯´Â Ç÷οìÀÇ »óŸ¦ º¯°æÇÏÁö ¾Ê´Â´Ù. ´ÜÁö ±×µéÀÇ ¾×¼ÇÀ» ½ÇÇàÇÏ°í ÇöÀç ºä ¶Ç´Â Çϳª ÀÌ»óÀÇ ÇÁ·¹±×¸ÕÆ®¸¦ ´Ù½Ã º¸¿©ÁØ´Ù.
4.12.4. ÇÁ·¹±×¸ÕÆ® ´Ù½Ã º¸¿©ÁÖ±â
Æ®·£Áö¼Ç¿¡¼ render ¿¤¸®¸ÕÆ®¸¦ »ç¿ëÇÏ¿© À̺¥Æ®¸¦ ó¸®ÇÑ ´ÙÀ½ ÇöÀç ºä¿¡¼ ÀϺκи¸ ´Ù½Ã º¸¿©ÁÖµµ·Ï ¿äûÇÒ ¼ö ÀÖ´Ù.
<transition on="next">
<evaluate expression="searchCriteria.nextPage()" />
<render fragments="searchResultsFragment" />
</transition>
fragments ¼Ó¼ºÀº ´Ù½Ã º¸¿©ÁÖ±æ ¿øÇÏ´Â ºä ¿¤¸®¸ÕÆ®(µé)ÀÇ id(¿©·¯°³)°¡ µÉ °ÍÀÌ´Ù. ¿©·¯ ¿¤¸®¸ÕÆ®¸¦ ´Ù½Ã º¸¿©ÁÖµµ·Ï ¼³Á¤ÇÏ·Á¸é ÄÞ¸¶·Î ±¸ºÐÇÏ¿© ÀûÀ¸¸é µÈ´Ù.
ÀÌ·¸°Ô ÀϺθ¦ ´Ù½Ã º¸¿©ÁÖ´Â ±â¹ýÀºÈ¸éÀÇ Æ¯Á¤ ºÎÀ§¸¦ ¾÷µ¥ÀÌÆ®ÇÏ´Â Ajax¿¡ ÀÇÇÑ À̺¥·Î »ç¿ëµÈ´Ù.
4.13. ¸Þ½ÃÁö ´Ù·ç±â
½ºÇÁ¸µ À¥ Ç÷οìÀÇ MessageContext´Â ÇÃ·Î¿ì ½ÇÇà µµÁß¿¡ ¸Þ½ÃÁö¸¦ ±â·ÏÇϱâ À§ÇÑ API´Ù. ÀÏ¹Ý ÅؽºÆ® ¸Þ½ÃÁö´Â ¹°·ÐÀÌ°í ½ºÇÁ¸µ MessageSource¸¦ »ç¿ëÇÏ´Â ±¹Á¦È ¸Þ½ÃÁöµµ Ãß°¡ÇÒ ¼ö ÀÖ´Ù. ¸Þ½ÃÁö´Â ºä¿¡¼ º¸¿©Áö¸ç ÀÚµ¿À¸·Î ÇÃ·Î¿ì ½ÇÇà ¸®´ÙÀÌ·ºÆ®¿¡µµ »ì¾Æ³²À» °ÍÀÌ´Ù. ¼¼ Á¾·ùÀÇ ¸Þ½ÃÁö¸¦ Á¦°øÇÑ´Ù. info, warning, error´Ù. ¶ÇÇÑ, Æí¸®ÇÑ MessageBuilder¸¦ Á¦°øÇÏ¿© ¸Þ½ÃÁö ÀÛ¼ºÀ» µ½°í ÀÖ´Ù.
4.13.1. ÀÏ¹Ý ÅؽºÆ® ¸Þ½ÃÁö Ãß°¡Çϱâ
MessageContext context = ...
MessageBuilder builder = new MessageBuilder();
context.addMessage(builder.error().source("checkinDate")
.defaultText("Check in date must be a future date").build());
context.addMessage(builder.warn().source("smoking")
.defaultText("Smoking is bad for your health").build());
context.addMessage(builder.info()
.defaultText("We have processed your reservation - thank you and enjoy your stay").build());
4.13.2. ±¹Ã¼È ¸Þ½ÃÁö Ãß°¡Çϱâ
MessageContext context = ...
MessageBuilder builder = new MessageBuilder();
context.addMessage(builder.error().source("checkinDate").code("checkinDate.notFuture").build());
context.addMessage(builder.warn().source("smoking").code("notHealthy")
.resolvableArg("smoking").build());
context.addMessage(builder.info().code("reservationConfirmation").build());
4.13.3. ¸Þ½ÃÁö ¹øµé »ç¿ëÇϱâ
±¹Á¦È ¸Þ½ÃÁö´Â ½ºÇÁ¸µ MessageSource·Î Á¢±ÙÇÏ´Â ¸Þ½ÃÁö ¹øµé¿¡ Á¤ÀÇÇÑ´Ù. Ç÷οì-°ü·Ã ¸Þ½ÃÁö ¹øµéÀ» ¸¸µé·Á¸é, °£´ÜÇÏ°Ô message.properties ÆÄÀÏÀ» ÇÃ·Î¿ì µð·ºÅ͸®¿¡ ¸¸µç´Ù. messages.properties ÆÄÀÏÀ» ¸¸µé°í Áö¿øÇÏ°íÀÚ ÇÏÇÏ´Â Áö¿ª Locale¿¡ ÇØ´çÇÏ´Â .properties ÆÄÀÏÀ» °¢°¢ Ãß°¡ÇÑ´Ù.
#messages.properties
checkinDate=Check in date must be a future date
notHealthy={0} is bad for your health
reservationConfirmation=We have processed your reservation - thank you and enjoy your stay
ºä ¶Ç´Â Ç÷ο쿡¼ ¿©·¯ºÐÀº resourceBundle EL º¯¼ö¸¦ »ç¿ëÇÏ¿© ¸Þ½ÃÁö ¹øµé¿¡ Á¢±ÙÇÒ ¼öµµ ÀÖ´Ù.
<h:outputText value="#{resourceBundle.reservationConfirmation}" />
4.13.4. ½Ã½ºÅÛÀÌ »ý¼ºÇÑ ¸Þ½ÃÁö ÀÌÇØÇϱâ
À¥ Ç÷οì ÀÚü°¡ »ç¿ëÀÚ¿¡°Ô º¸¿©ÁÙ ¸Þ½ÃÁö¸¦ »ý¼ºÇÏ´Â ¸î¸î ºÎºÐÀÌ ÀÖ´Ù. ÀÌ·± ÀÏÀÌ ¹ß»ýÇÏ´Â Áß¿äÇÑ ÁöÁ¡ Áß Çϳª´Â ºä¿¡¼ ¸ðµ¨·Î µ¥ÀÌÅÍ ¹ÙÀεùÀ» ÇÒ ¶§´Ù. º¯È¯ ¿¡·¯ °°Àº ¹ÙÀεù ¿¡·¯°¡ ¹ß»ýÇϸé À¥ Ç÷οì´Â ÀÚµ¿À¸·Î ¿¡·¯¸¦ ¿©·¯ºÐ ¸®¼Ò½º¹øµé¿¡¼ °¡Á®¿Â ¸Þ½ÃÁö·Î ¸ÊÇÎÇÑ´Ù. º¸¿©ÁÙ ¸Þ½ÃÁö¸¦ °¡Á®¿À·Á°í À¥ Ç÷οì´Â ¹ÙÀεù ¿¡·¯ ÄÚµå¿Í Ÿ°Ù ¼Ó¼º À̸§À» ´ã°í ÀÖ´Â ¸®¼Ò½º Å°¸¦ ½ÃµµÇÑ´Ù.
¾Æ·¡ ¿¹Á¦´Â Booking °´Ã¼ÀÇ checkinDate ¼Ó¼º¿¡ ¹ÙÀεùÀ» »ý°¢Çغ¸°í ÀÖ´Ù. »ç¿ëÀÚ°¡ ¾ËÆĺª ¹®ÀÚ¿À» ÀÔ·ÂÇß´Ù°í ÇÏÀÚ. ÀÌ·± °æ¿ì ŸÀÔ º¯È¯ ¿¡·¯°¡ ¹ß»ýÇÒ °ÍÀÌ´Ù. À¥ Ç÷οì´Â "typeMismatch' ¿¡·¯ Äڵ带 ¿©·¯ºÐ ¸®¼Ò½º ¹øµé Áß¿¡ ÀÖ´Â ¸Þ½ÃÁö¸¦ ãÀ» ¶§ ´ÙÀ½ Å°¸¦ »ç¿ëÇÒ °ÍÀÌ´Ù.
booking.checkinDate.typeMismatch
Å°ÀÇ ¾Õ ºÎºÐÀº ¸ðµ¨ Ŭ·¡½ºÀÇ ÂªÀº À̸§ÀÌ´Ù. µÎ ¹ø° ºÎºÐÀº ¼Ó¼ºÀÇ À̸§ÀÌ´Ù, ¼¼ ¹ø° ºÎºÐÀº ¿¡·¯ ÄÚµå´Ù. ¸ðµ¨ ¼Ó¼º¿¡ ¹ÙÀεùÀÌ ½ÇÆÐÇÏ¸é »ç¿ëÀÚ¿¡°Ô º¸¿©ÁÙ À¯ÀÏÇÑ ¸Þ½ÃÁö¸¦ ÀÌ·±½ÄÀ¸·Î ã´Â´Ù. ¾Æ¸¶ ´ÙÀ½°ú °°Àº ¸Þ½ÃÁöÀÏ ¼ö ÀÖ´Ù.
booking.checkinDate.typeMismatch=The check in date must be in the format yyyy-mm-dd.
¸¸¾à Àú Çü½Ä¿¡ ÇØ´çÇÏ´Â Å°¸¦ ãÁö ¸øÇϸé, º¸´Ù ÀϹÝÀûÀÎ Å°·Î ½ÃµµÇغ»´Ù. ÀÌ Å°´Â °£´ÜÇÑ ¿¡·¯ ÄÚµå ÇüÅ´Ù. ¼Ó¼ºÀÇ Çõå À̸§Àº ¸Þ½ÃÁö ÀÎÀÚ·Î Á¦°øµÈ´Ù.
typeMismatch=The {0} field is of the wrong type.
4.14. Æ˾÷ º¸¿©ÁÖ±â
popup ¼Ó¼ºÀ» »ç¿ëÇÏ¿© ¸ðµ¨ Æ˾÷ â¿¡¼ ºä¸¦ ·£´õ¸µ ÇÑ´Ù.
<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true">
½ºÇÁ¸µ ÀÚ¹Ù½ºÅ©¸³Æ®¶û °°ÀÌ À¥ Ç÷ο츦 »ç¿ëÇϸé, Æ˾÷À» º¸¿©ÁÙ ¶§ Ŭ¶óÀ̾ðÆ® ÂÊ Äڵ带 »ç¿ëÇÒ ÇÊ¿ä°¡ ¾ø´Ù. À¥ Ç÷οì´Â Æ˾÷¿¡¼ ºä·Î ¸®´ÙÀÌ·ºÆ®¸¦ ¿äûÇÏ´Â »ç¿ëÀÚ¿¡°Ô ÀÀ´äÀ» º¸³¾ °ÍÀÌ°í ±× °á°ú Ŭ¶óÀ̾ðÆ®´Â ¿äûÀº Àß Ã³¸®µÉ °ÍÀÌ´Ù.
4.15. ºä ¹éÆ®·¢Å·(backtracking)
±âº»ÀûÀ¸·Î, ºä ½ºÅ×ÀÌÆ®¸¦ Á¾·áÇÏ°í »õ·Î¿î ºä ½ºÅ×ÀÌÆ®·Î ÀüÀÌÇϸé, ¿©·¯ºÐÀº ºê¶ó¿ìÀúÀÇ µÚ·Î °¡±â ¹öÆ°À» »ç¿ëÇÏ¿© ÀÌÀü »óÅ·ΠÀ̵¿ÇÒ ¼ö ÀÖ´Ù. ÀÌ·¯ÇÑ ºä ½ºÅ×ÀÌÆ® È÷½ºÅ丮 Á¤Ã¥Àº history ¼Ó¼ºÀ» »ç¿ëÇÏ¿© Æ®·£Áö¼Ç ´ç ¼³Á¤ÇÒ ¼ö ÀÖ´Ù.
4.15.1. È÷½ºÅ丮 ¹æÁöÇϱâ
history ¼Ó¼ºÀ» discard·Î ¼³Á¤ÇÏ¿© ºä ¹éÆ®·¢Å·À» ¹æÁöÇÒ ¼ö ÀÖ´Ù.
<transition on="cancel" to="bookingCancelled" history="discard">
4.15.2. È÷½ºÅ丮 ±ÝÁöÇϱâ
history ¼Ó¼ºÀ» invalidate·Î ¼³Á¤ÇÏ¿© ºä ¹éÆ®·¢Å·À» ¹æÁöÇÏ°í ÀÌÀüÀÇ ºä·Î ÀüÀÌÇÏ´Â °Íµµ ¹æÁöÇÑ´Ù.
<transition on="confirm" to="bookingConfirmed" history="invalidate">