2019년 2월 26일 화요일

API를 사용하여 Datasource를 생성하고 페이지 레이아웃 업데이트하기 [Part 1]

이번 포스트에서는 Non-Technical 사이트코어 Author 또는 Contributor를 타켓으로 하여 어떻게 xEditor에서 아이템을 생성하고 페이지에 적용을 시키는지에 알아보도록 하자. 필자는 새로운 API를 생성하여 XMLHttpRequest를 통하여 아이템을 생성하는 방법을 택하였다.

새로운 API를 생성하기 전, 페이지 아이템 및 데이터소스 구조를 정하여야 한다. 각 컴퍼니 또는 비지니스의 컨셉, 그리고 웹사이트의 수에 따라 아이템 스트럭쳐는 다양하게 변경되어있을 수 있으므로 이번 예제에서는 어떻게 사이크코어의 사용자가 렌더링 아이템을 적용 시키고 그에 맞는 데이타소스를 손쉽게(?) 적용할수 있도록 포커스를 두었다. 이는 경우에 따라 언제든지 확장 및 수정이 가능할수 있다.

아래는 기본적으로 유저가 렌더링 아이템을 적용하고 데이타소스를 생성하여 페이지 레이아웃에 적용하는 순서이다.
  1. 업데이트를 하고자 하는 페이지 아이템으로 이동
  2. Content Editor에 원하는 경로에 컴포넌트의 데이터소스 생성한다.
  3. xEditor로 이동 후, 적용되어진 Placeholder에 컴포넌트를 Insert한다.
  4. 적용 되어진 컴포넌트의 속성을 열어, 데이터소스 아이템을 Datasource 필드에 적용을 시킨다.
아래의 API를 통하여 컴포넌트와 관련된 아이템을 페이지에 적용하는 방법이다.
  1. 업데이트 하고자 하는 아이템의 xEditor 오픈
  2. Placeholder에 원하는 컴포넌트 Insert
  3. 생성되어진 Input 버튼 (One-Click)을 통하여 컴포넌트의 데이터소소를 정해진 경로에 생성
필자의 방법처럼 API를 사용하여 아이템을 생성과 동시에 Layout에 데이터소스를 적용하면 Content Editor 와 xEditor의 변경 없이 손쉽게 누구나 페이지에 컴포넌트 및 그에 맞는 데이터소스를 적용시킬수가 있다. 좀 더 자세히 알아보기 위하여 필자는 아래의 샘플 소스를 작성하였다.  

먼저 새로운 Route을 적용 시키고 "CreateItem" 이라는 API 액션을 생성하도록 하자.


필자는 API라는 새로운 프로젝트를 만든 후, RouteMap을 "{controller}/{action}/{id}" 으로 설정하고 CustomApiController와 Api 모델을 생성하였다. Controller에는 새로운 아이템을 생성하는  ActionResult와 페이지 아이템 하위의 데이터소스폴더 및 생성되어진 데이타소스의 키를 업데이트할수 있는 레이아웃 업데이트 Method도 같이 생성하였다.

CustomApiController.cs


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
using System.Web.Mvc;
using Sitecore.Data.Items;
using Sitecore.Data;
using Sitecore.Globalization;
using Sitecore.SecurityModel;
using Sitecore.Layouts;

namespace Sitecore.Custom.Component.API.Controllers
{
    public class CustomApiController : Controller
    {
        Database masterDb = Configuration.Factory.GetDatabase("master");
        Database webDb = Configuration.Factory.GetDatabase("web");

        /// <summary>
        /// 새로운 ResourceFolder 페이지 아이템 하위에 생성한다.
        /// 해당 페이지 아이템과 관련된 모든 컴포넌트의 데이타소스는 
        /// 페이지 하위 ResourceFolder에 모두 생성된다.
        /// </summary>
        /// <param name="api">api</param>
        /// <param name="parentItem">ResouceFolder가 만들어진 상위의 페이지 아이템</param>
        /// <returns></returns>
        public Item CreateResourceFolder(Models.Api api, Item parentItem)
        {
            var localResourceFolder = parentItem.Database.GetItem(parentItem.Paths.FullPath + "/" + api.localResourceFolderName);
            using (new SecurityDisabler())
            {
                TemplateItem template = parentItem.Database.GetTemplate("User Defined/Local Resource Folder");
                if (localResourceFolder == null)
                {
                    localResourceFolder = parentItem.Add(api.localResourceFolderName, template);
                }
            }
            return localResourceFolder;
        }

        /// <summary>
        /// 생성되어진 Datasource Item의 ID아이디를 페이지 레이아웃에 업데이트한다.
        /// </summary>
        /// <param name="pageItem">현재 페이지 아이템</param>
        /// <param name="datasourceItem">새로운 데이타소스 아이템</param>
        /// <param name="renderingUid">렌더링 아이템의 유니크 아이디</param>
        public void UpdateDatasourceKey(Item pageItem, Item datasourceItem, string renderingUid)
        {
            using (new SecurityDisabler())
            {
                // Get the layout definitions and the device
                string deviceId = Context.Device.ID.ToString();
                DeviceItem device = pageItem.Database.Resources.Devices[deviceId];
                Data.Fields.LayoutField layoutField = new Sitecore.Data.Fields.LayoutField(pageItem.Fields[Sitecore.FieldIDs.FinalLayoutField]);
                LayoutDefinition layoutDefinition = LayoutDefinition.Parse(layoutField.Value);
                DeviceDefinition deviceDefinition = layoutDefinition.GetDevice(device.ID.ToString());
                foreach (RenderingDefinition rd in deviceDefinition.Renderings)
                {
                    // Update the renderings datasource value accordingly 
                    if (rd.UniqueId == "{" + renderingUid.ToUpper() + "}")
                    {
                        rd.Datasource = datasourceItem.ID.ToString();
                        // Save the layout changes
                        pageItem.Editing.BeginEdit();
                        layoutField.Value = layoutDefinition.ToXml();
                        pageItem.Editing.EndEdit();
                    }
                }
            }
        }

        /// <summary>
        /// 새로운 아이템을 정해진 템플릿에 맞게 생성한다
        /// </summary>
        /// <param name="itemName">새로운 아이템을 이름</param>
        /// <param name="id">{id}에 생성될 다이나믹 아이디</param>
        /// <param name="templateGuid">새로운 아이템의 템플릿 Guid</param>
        /// <param name="isDatasourceItem">현재 생성될 아이템이 데이타소스인지 확인 (Default: false)</param>
        /// <param name="renderingUid">레이아웃에 업데이트 되어진 렌더링 아이템의 유니크 아이디</param>
        /// <returns></returns>
        public ActionResult CreateItem(string itemName, string id, string templateGuid, string isDatasourceItem = "0", string renderingUid = null)
        {
            Models.Api api = new Models.Api();

            using (new LanguageSwitcher("en"))
            {
                Item pageItem = masterDb.GetItem(ID.Parse(id));
                // 새로운 데이타소스가 생성되었다면, 레이아웃을 업데이트한다

                if (isDatasourceItem == "1")
                {
                    api.item = CreateResourceFolder(api, pageItem);
                }
                api.templateItem = masterDb.GetTemplate(ID.Parse(templateGuid));
                Item newDatasource = api.item.Add(itemName, api.templateItem);

                // 새로운 데이타소스가 생성되었다면, 레이아웃을 업데이트한다
                if (isDatasourceItem == "1" && newDatasource != null)
                {
                    UpdateDatasourceKey(pageItem, newDatasource, renderingUid);
                }
            }
            return new EmptyResult();
        }
    }
}


Api.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
using Sitecore.Data.Items;
using Sitecore.Data;

namespace Sitecore.Custom.Component.API.Models
{
    public class Api
    {
        public string actionType { get; set; }
        public Item item { get; set; }
        public Database sourceDb { get; set; }
        public Database targetDb { get; set; }
        public TemplateItem templateItem { get; set; }
        public string localResourceFolderName {
            get
            {
                return "Local Resource";
            }
        }
    }
}


API는 준비되었으므로 다음 포스트에서 심플한 컴포넌트를 만들어 API를 xEditor에서호출하여 보자.



2019년 1월 15일 화요일

사이트코어 Federated Authentication - Azure AD Workflow

이전 포스트에서는 Sitecore Federated Authentication을 사용하여 어떻게 Azure AD를 컨넥하고 유저정보를 인증하는지 그리고 어떻게 Customize한 코드를 적용하는지에 대하여 알아보았다.
이번에는 조금 더 디테일하게 접근하기위하여 필자는 유저의 이벤트 Request부터 시작하여 어떻게 Azure AD를 통하여 사이트코어 로그인을 성공하는지에 대하여 Workflow를 그려보았다.

순서부터 설명하자면,

  1. 유저는 Authentication 버튼이 생성되어진 로그인 페이지로 이동한다.
  2. 개발자의 의해 Customize되어진 사이트코어 Pipleline을 통하여 등록되어진 Microsoft Identity Server로 이동한다.
  3. MS 로그인페이지에서 유저 이메일 및 암호를 입력하고 로그인을 시도한다.
  4. MS Identity Server는 사이트코어 Pipeline를 통하여 받은 정보와 유저의 로그인 정보를 통하여 Azure AD로 이동한다.
  5. 유저정보가 Azure AD에 등록 또는 이용가능한 정보인지 검증한다.
  6. 검증이 확인되면 다시 MS Identity Server로 이동 후, 유정정보를 이용하여 Unique한 Token을 생성한다.
  7. 사이트코어는 생성된 Token과 함께 유저정보를 사이트코어 Pipeline에 보낸다.
  8. 사이트코어 Pipeline 및 설정에 등록된 Claims에 따라 유저정보 및 프로파일을 업데이트 한다.
  9. 유저는 사이트코어 Dashboard로 이동하여 사이트코어 CMS를 이용한다.




2018년 12월 4일 화요일

사이트코어 퍼블리쉬 서비스 (Sitecore Publishing Service) 설치하기

사이트코어 퍼블리슁 서비스 (Sitecore Publishing Service)는 대량의 아이템 퍼브리쉬를 실행할때, 사이트코어의 웹서버를 이용하지 않고 별개의 퍼브리쉬용 웹서버를 만들어 High Performance의 퍼블리쉬를 실행한다.
이는 사이트를 퍼브리슁하는데 속도를 높일뿐 아니라 퍼블리쉬 상태 및 결과를 Dashboard를 통하여 쉽게 확인할수가 있다.

이번에는 어떻게 퍼블리슁 서비스를 설치하고 사용하는지 알아보자.
필자는 사이트코어를 Azure PaaS로 사용하므로 퍼블리쉬 서비스의 웹호스팅을 Azure에 새로운 VM를 만들어 IIS를 설치하고 Publishing Service Provider를 생성하였다.
  1. Sitecore Publishing Service (SPS) 다운로드
  2. SPS를 설치할 서버로 이동 후, .NET Core 프레임웍을 설치하고 Window Server Hosting을 설치한다.
  3. SPS를 설치할 컴퓨터 또는 환경으로 이동 후, IIS를 설치하고 다운받은 SPS를 "C:\inetpub\wwwroot\sitecorepublishing" 경로에 압출을 푼다.
  4. IIS의 Application Pools에서 새로운 Application Pool를 생성한다.
    *필자는 SitecorePublishProd라고 이름을 지었다.

  5. IIS의 Sites 트리에서 새로운 사이트를 추가하고, 등록한 Application Pool을 사이트에 적용한다.

  6. 등록되어진 사이트에 "IIS AppPool\SitecorePublishProd"에 READ, EXECUTE, WRITE의 권환을 준다.

  7. 만약 다른 로컬 사이트가 적용중이라면 사이트 Binding을 업데이트하고 정상적으로 사이트가 작동되는지 그리고 다른 등록되어지 도메인이름이 있는지 "C:\Windows\System32\drivers\etc\"에서 확인한다.
    *필자의 경우 해당 VM에는 SPS만 존재하므로, 로컬호스트 기본 경로를 사용한다.
  8. "C:\inetpub\wwwroot\SitecorePublishingProd\config\global" 의 경로로 이동하여 아래의 설정처럼 해당 Master, Web, Core 데이타베이스의 정보를 입력하고 반드시 "MultipleActiveResultSets=True" Attribute을 추가한다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    <Settings>
        <Sitecore>
            <Publishing>
                <ConnectionStrings>
                    <Master>user id={userId};Password={Password};Data Source={Datasource};Database={my-sitecore-master-db;MultipleActiveResultSets=True;</Master>
                    <Web>user id={userId};Password={Password};Data Source={Datasource};Database={my-sitecore-web-db;MultipleActiveResultSets=True;</Web>
                    <Core>user id={userId};Password={Password};Data Source={Datasource};Database={my-sitecore-core-db;MultipleActiveResultSets=True;</Core>
                </ConnectionStrings>
            </Publishing>
        </Sitecore>
    </Settings>
    


  9. 사이트 설정을 마쳤으면 Host Service의 데이타베이스 엑세스가 필요하고 SPS의 필요한 데이타베이스를 추가적으로 설치하여야 하므로, "C:\inetpub\wwwroot\sitecorepublishing" 경로로 이동 후 아래의 커맨드를 Command Prompt를 통하여 실행한다.

    1
    2
    3
    4
    Microsoft Windows [Version 10.0.14393]
    (c) 2016 Microsoft Corporation. All rights reserved.
    
    C:\inetpub\wwwroot\SitecorePublishingProd>Sitecore.Framework.Publishing.Host schema upgrade --force
    


  10. Schema 업데이트가 끝나고, 사이트코어의 데이타베이스를 확인하면 추가적으로 생성된 테이블을 확인할수가 있다.

  11. IIS 세팅과 Schema 업데이트를 마친 후, 브라우저를 열고 "http://localhost/api/publishing/operations/status"로 이동하여 결과가 "{"Status" : 0}" 나오면 SPS설치는 성공적으로 완료된것이다.

  12. SPS 웹호스트 설치는 마쳤으므로, 이젠 사이트코어 CMS로 이동 후 Sitecore Publishing Service Module를 다운받고 Installation Widzard를 통하여 설치한다.
  13. 설치가 완료되면 사이트코어와 SPS 웹호스팅을 연결하기 위하여 아래의 Patch 파일을 만들고, "App_Config/Include/" 폴더에 파일(예, z.PublishingService.config) 파일을 추가한다.
    *필자의 경우 SPS 웹호스팅을 사이트코어 서버가 아닌 다른 서버에 설치하였으므로 localhost 대신 서버의 아이피 주소를 입력하였다.

    1
    2
    3
    4
    5
    6
    <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
        <sitecore>
            <settings>
                <setting name="PublishingServiceUrlRoot">http://123.123.123.123/</setting>
    
      </settings>
        </sitecore>
    </configuration>
    


  14. 모든 설치가 완료되었으며 이젠 사이트코어에 접속하여 대시보드의 Sitecore Publishing Service 버튼을 클릭하여 실행하여 본다.








2018년 11월 19일 월요일

사이트코어의 새로운 MVC Route 적용하기

이번 블로그에서는 새로운 MVC Route를 사이트코어에 적용하는 방법을 알아보자.
사이트코어의 기본 MVC Route는 "/api/sitecore/{controller}/{action}"으로써 Sitecore 9 이상의 버전에서는 Sitecore.Mvc.config, 그리고 Sitecore 9 하위 버전에서는 Sitecore.Speak.Mvc.Config 파일에서 확인할 수가 있다.
Sitecore의 자체적인 MVC Application의 컨트롤는 "/sitecore/layout/controllers" 아이템 트리에 등록되어진 Application 렌더링 아이템을 작동시키지만, 간혹 아이템의 등록없이 새로운 API를 만들어 외부 소스를 Ajax Call로 불러들여 원하는 기능을 작동시킬수가 있다.

이를 위하여, 새로운 MVC Route를 만듬으로써 기본 API 경로에 구애받지 않고 사이트코어 내에 다른 어플리케이션을 독립적으로 수행할수가 있다. 지금부터 어플리케이션을 만들고 적용시키는 방법을 알아보자.

  1. Visual Studio에서 새로운 Empty MVC 프로젝트를 만든다.

  2. App_Start 폴더에 RouteConfig.cs을 새로운 Route를 레지스터하기 위하여 수정한다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    using System.Web.Mvc;
    using System.Web.Routing;
    
    namespace SitecoreSpaceNewRoute
    {
        public class RouteConfig
        {
            public static void RegisterRoutes(RouteCollection routes)
            {
                //// 
                //// 기본 MVC Route
                ////
                //routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
                //routes.MapRoute(
                //    name: "Default",
                //    url: "{controller}/{action}/{id}",
                //    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
                //);
    
    
                ////
                //// 사이트코어 스페이스의 새로운 MVC Route
                ////
                routes.MapRoute(
                    name: "SitecpreSpaceRouting",
                    url: "new/sitecore/space/routing/{controller}/{action}/{id}",
                    defaults: new { controller = "SitecoreSpace", action = "MyView", id = UrlParameter.Optional }
                );
            }
        }
    }
    


  3. 새로운 폴더 "CustomRouting" 이라는 폴더를 만들고, Sitecore.Kernel assembly를 Reference에 추가하고 사이트코어의 Bin 폴더의 System.Web.Mvc를 사용하도록 프로젝트에 업데이트한다. 레지스터한 Route를 Sitecore.Pipeline의 프로세스에 적용을 시킨다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    using System.Web.Routing;
    using Sitecore.Pipelines;
    
    namespace SitecoreSpaceNewRoute.CustomRouting
    {
        public class InitializeRoutes
        {
            /// <summary>
            /// 새로 등록한 Route는 Sitecore Pipeline에 적용시킨다.
            /// </summary>
            /// <param name="args"></param>
            public void Process(PipelineArgs args)
            {
                RouteConfig.RegisterRoutes(RouteTable.Routes);
            }
        }
    }
    


  4. 간단하게 새로운 Route의 레지스트를 마쳤으며, 이젠 Simple MVC을 만들자.

    Controller (SitecoreSpaceController.cs)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace SitecoreSpaceNewRoute.Controllers
    {
        public class SitecoreSpaceController : Controller
        {
            // GET: SitecoreSpace
            public ActionResult MyView()
            {
                Models.SitecoreSpace ssnr = new Models.SitecoreSpace();
    
                // Valuable 값을 다른 소스 (예, 데이타베이스)에서 불러들일수 있지만,
                // 이번은 예제이므로, Static 값을 메뉴얼로 적용하겠다.
                ssnr.Subject = "사이트코어의 새로운 MVC Routing";
                
                ssnr.Description = "사이트코어 스페이스의 새로운 MVC Routing으로써, 기존 (Default)의 Routing 제한을 받지않고, 임의의 새로운 Route를 적용시켜 독립적인 MVC 어플리케이션을 Sitecore XP내에서 작동시킬수 있다.";
                ssnr.CurrentDateTime = DateTime.UtcNow;
    
                return View(ssnr);
            }
    
            // Redirect가 아니 다른 View rendering으로 사용할수가 있다.
            public ActionResult RedirectToBlog()
            {
                Models.SitecoreSpace ssnr = new Models.SitecoreSpace();
                ssnr.BlogUrl = "https://SitecoreSpace.Blogspot.com";
    
                return Redirect(ssnr.BlogUrl);
            }
        }
    }
    


    Model (SitecoreSpace.cs)
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    using System;
    namespace SitecoreSpaceNewRoute.Models
    {
        public class SitecoreSpace
        {
            public string FullBlogName { get; set; }
            public string BlogUrl { get; set; }
            public string Subject { get; set; }
            public string Description { get; set; }
            public DateTime CurrentDateTime { get; set; }
        }
    }
    


    View (MyView.cshtml)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    @model SitecoreSpaceNewRoute.Models.SitecoreSpace
    
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>MyView</title>
    </head>
    <body>
        <div class="form-horizontal">
            <h4>SitecoreSpace</h4>
            <hr />
            <div class="col-md-10">
                @Html.DisplayTextFor(model => model.Subject)
            </div>
            <br />
            <div class="col-md-10">
                @Html.DisplayTextFor(model => model.FullBlogName)
            </div>
            <br />
            <div class="col-md-10">
                @Html.DisplayTextFor(model => model.Description)
            </div>
            <br />
            <div class="col-md-10">
                링크: @Html.ActionLink("Sitecore Space Blog", "RedirectToBlog", null, new { target = "_blank" })
            </div>
            <br />
            <div class="col-md-10">
                현재시간: @Model.CurrentDateTime.ToString("yyyy-MM-dd h:mm:ss tt")
            </div>
        </div>
    </body>
    </html>
    


    View (RedirectToBlog.cshtml)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>RedirectToBlog</title>
    </head>
    <body>
        <div> 
            추가 extra 페이지
        </div>
    </body>
    </html>
    


  5. 새로운 패치파일을 만들어 사이트코어 파일시스템의 "/App_config/Include/" 폴더에 z.Sitecore.Space.Route.config을 만든다.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    <?xml version="1.0" encoding="utf-8"?>
    <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
      <sitecore>
        <pipelines>
          <initialize>
            <processor type="SitecoreSpaceNewRoute.CustomRouting.InitializeRoutes, SitecoreSpaceNewRoute" 
                       patch:after="processor[@type='Sitecore.Pipelines.Loader.EnsureAnonymousUsers, Sitecore.Kernel']" />
          </initialize>
        </pipelines>
      </sitecore>
    </configuration>
    


이젠 브라우저에서 패치되어진 API 경로를 이동을 해본다.








2018년 10월 26일 금요일

Sitecore Symposium 2018 in Orlando FL, USA - 사이트코어 9.1 Overview

조금 늦었지만, 이번 달에 있었던 Sitecore Symposium에 대하여 이야기하도록 하겠다.
이번 Symposium은 작년에 출시된 Sitecore 9.0의 섭버전으로써, 9.1에서는 Performace 업그레이드를 중점을 두었다.

아래는 9.1에서 새로 공개된 기능들이다.
  • JSS - JavaScript Service로써, Headless CMS이다. 이는 굳이 Presentation Layer를 걸치지 않고, 자바스크립트 라이브러리를 이용하여 사이트코어 어플리케이션을 개발 및 Sitecore CMS로 퍼블리쉬할수가 있다. 참고로, JSS를 사이트코어에서 사용하기 위해서는 사이트코어 Subscription 버전의 라이센스를 사용하여야지 이용 및 개발이 가능하다. 이번에 업그레이드 되어진 버전은 xEditor 및 Personalization and Tracking 기능과 통합되었다.

  • XM Performance - 아래의 테이블처럼 컨텐츠 로딩 시간이 현저히 줄어들었고, 컨텐츠 서치 기능을 향상시켰다.

  • Forms - Forms기능은 9.0에서 새로 소개되었으며, 이번 버전에는 Form Condition기능을 추가하여 유저의 선택사항에 따라 다른 필드 옵션을 제공한다.

  • Update Center - 컨트롤 패널 또는 어드민 페이지에서 Sitecore를 업그레이드한것과 달리 Speak3 어플리케이션을 사용하여 새로운 UI에서 시스템을 업그레이드한다. 또한, 외부 소스를 쉽게 불러들일 수 있다. 업그레이드가 진행중일때는 사이트코어의 모듈 및 Enviornment 레이어가 Disable되고 사이트코어 업그레이 모드로 전환이된다.

  • Sitecore Identity - 9.0에서 소개된 Federated Authentication되었는데, 이번에는 추가적으로 SSO (Single Sign On)을 제공한다. 만약, 멀티플 사이트코어를 관리해야한다면, 굳이 추가적인 로그인없이 XM, XP, xCommerce 등 쉽게 접속할수가 있다.

  • Universal Tracker - Web/REST API를 기반으로 트래킹하는 프레임워크로 Collection(수집), Storing(저장), Process(진행)순으로 Stage가 진행된다. Website뿐만 아니라 App, AR/VR 등 다양한 플랫폼으로부터 정보받아 Sitecore xDB와 연결을한다.

  • Horizon - 이는 작년에 이미 소개되었지만, 사이트코어 CMS의 새로운 UI/UX이다. Horizon의 새로운 시뮬레이션 기능과 유저 프로파일가능들은 충분히 발전된 기능이라고 할수있다. 아직 오피셜하게 공개되어지지 않은 관계로 Performance에 대하여 말하기는 어려운것같다.

  • Sitecore Host - Sitecore .Net Core로써, 이미 Sitecore Commerce에 도입하였지만, 이번에는 Sitecore Identity, Horizon, Universal Tracker에 사용되어진다. .Net Core을 도입함으로써 다른 OS Platform과 쉽게(?) 호환이 가능하다.



  • Cortex - 머신러닝(ML)로 다양한 디바이스 및 컨텐츠를 통합, 분석 및 테스트를 하며, 결과물을 유저에 맞춤형 서비스를 제공하고 데이타를 Personalization한다.

  • Cortex Tagging - Open Calais의 솔루션을 이용하여 SEO 및 컨텐츠를 서비하는데에 도움(?)을 주며, 마케팅 오토메이션과 유용하게 사용되어질수있다.


아래는 Sitecore 9.1 Overview에 사용되어진 슬라이드이다.





2018년 9월 14일 금요일

사이트코어 9 - Solr SSL 설치하기

사이트코어 개발자들은 환경에 따라 Sitecore를 자신의 컴퓨터에 설치해야하는 경우가 있다. 로컬 사이트코어 Instance를 설치함으로써 나만의 Playground가 형성되고, VM이나 서버환경에 접속하여 디버그 하는것보다 부담감(?)을 덜어낼수가 있다.
이번에는 그 중에서도 Solr 설치 및 xConnect와 호환하기 위하여 어떻게 SSL을 적용시키는지 알아보도록하자.

사이트코어 9+ 버전부터는 사이트코어 Instance내의 Lucence보다는 Solr 자체 서비엔진을 설치하고 xConnect 프레임워크를 통하여 데이터를 다른 어플리케이션 및 디바이스와 연동 할수가 있다.
Solr 설치 및 SSL 바운드가 제되로 되지않는다면 xConnect와 연동이 되지 않을뿐더러, Sitecore 플랫폼의 키 요소인 Experience Analytics 및 마케팅 기능들을 사용할수가 없다.

  1. Solr을 설치하기전 Java JDK (현재 필자의 경우 버전 1.8.0)를 설치하고, Command Prompt를 통하여 자바가 잘 작동되는지 그리고 "keytool" 커맨드가 이용가능한지 확인한다.
  2. Solr 다운로드 링크로 이동하여 6.2.2 버전을 원하는 경우에 설치한다. (예, C:\solr-6.2.2)
  3. Command Prompt에서 압축을 푼 경로의 "C:\solr-6.2.2\server\etc\"로 이동하여 아래의 커맨드를 실행한다.

    keytool -genkeypair -alias solr-ssl -keyalg RSA -keysize 2048 -keypass secret -storepass secret -validity 9999 -keystore solr-ssl.keystore.jks -ext SAN=DNS:localhost,IP:127.0.0.1 -dname "CN=localhost, OU=Organizational Unit, O=Organization, L=Location, ST=State, C=Country"
    

  4. 다시 아래의 커맨드를 입력하고 비밀번호를 설정한다. (비밀번호 예, secret)

    keytool -importkeystore -srckeystore solr-ssl.keystore.jks -destkeystore solr-ssl.keystore.p12 -srcstoretype jks -deststoretype pkcs12
    

  5. SSL 설치는 준비가 되었으며, 이젠 JKS keystore로 만들어진 PKCS12 (.p12) 파일을 더블 클릭하여, 로컬 컴퓨터에 Self Certification을 생성한다.
  6. Store Location을 Local Machine로 적용하고 "다음" 버턴을 누른다.

  7. "server\etc\" 폴더에 있는 .p12 파일의 경로를 확인하고, "다음" 버턴을 누른다.

  8. 이전에 설정하였던 비밀번호 "secret"을 입력하고, "다음" 버턴을 누른다.

  9. Certification 저장 경로는 "Trusted Root Certification Authorities"로 설정하고, 모든 세팅을 마친다.

  10. Solr 설치 경로의 "bin/" 폴더의 "solr.in.cmd" (Window 경우)를 오픈하여, 컨맨트 되어진 설정 (REM)들은 삭제하고 아래처럼 SSL설정을 Enable 한다.

    REM Uncomment to set SSL-related system properties
    REM Be sure to update the paths to the correct keystore for your environment
    set SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.jks
    set SOLR_SSL_KEY_STORE_PASSWORD=secret
    set SOLR_SSL_KEY_STORE_TYPE=JKS
    set SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.jks
    set SOLR_SSL_TRUST_STORE_PASSWORD=secret
    set SOLR_SSL_TRUST_STORE_TYPE=JKS
    set SOLR_SSL_NEED_CLIENT_AUTH=false
    set SOLR_SSL_WANT_CLIENT_AUTH=false
    
  11. 머신에 Solr 서비스가 설치가 되어있지 않으므로, Command Prompt에서 Solr의 "bin/" 폴더로 이동하여 "solr start" 커맨드를 통하여 Solr를 실행한다.
  12. 브라우저에서 디폴트 포트 번호인 "8983"과 함께 "https://localhost:8983" 페이지를 오픈한여 Solr를 확인한다.





2018년 8월 21일 화요일

Sitecore Migration - Data Migration Assistant 사용하기

이전에 포스트 하였던 Sitecore Migration의 두번째로 필자가 경험하였던 문제에 대하여 이야기를 하고자한다.

Sitecore Migration은 사이트코어의 새로운 버전이 나올때마다, 개발자 또는 설계자들은 "어떻게 하면 가장 쉽고 안정적인 방식으로 데이타의 손실없이 Migration을 할수가 있을까?"가 첫번째의 과제이다. 그 다음으로는 기존에 사용하였던 방식 또는 설정들이 얼마나 새로운 버전에서 잘 호환되고 작동되는지를 눈여겨 봐야한다.

이번 포스트는 필자가 생각하는 데이터의 손실없이 가장 손 쉬운 방법으로 Migration하는것에 대하여 알아보도록 하겠다.

먼저, 이전에 사용해보았던, Sitecore Azure ToolKit은 Sitecore Azure Deployment의 목정으로써, Sitecore On-Prem Instance를 Azure Cloud로 Deploy를 할수가 있다. 패키지를 Powershell Script을 통하여 만드는데, 작업 시스템의 환경에 땨라 제한이 있을수 있다. (필자의 경우, 시스템에서 2GB의 패키지 제한이 있어, 기존 데이타를 포함 약 6GB에 해당되는 Sitecore Instance를 패키지하기에는 한계가 있었다.) 이로, 새로운 방법으로 Sitecore에서 추천한 SSMS (SQL Server Management Studio)을 사용하는것이다. SSMS에서 Azure SQL를 컨넥하고, 백업된 DB를 Import하는 방식인데, 이 역시 기존 Master DB의 테이블들을 백업하는데 무리가 있었다.

그래서 결론은 Data Migration Assistant (DMA).

DMA는 Microsoft에서 오피셜로 제공하며, 이는 기존 DB (Source)를 다른 DB (Target)으로 분석 및 검증과 함께 데이타베이스를 Migration할수가 있다. 아래는 필자가 DMA를 사용하여 Sitecore Migration을 한 진행과정을 나열하였다.
  1. 로컬머신에 Azure에 존재하는 같은 버전의 Sitecore Instance를 설치한다.
  2. SSMS에서 Azure SQL의 Master DB를 컨넥하고, 아래의 Statement를 적용하여 해당 테이블의 데이터를 모두 삭제한다. (반드시, 기존의 데이터는 백업을 미리해둔다.)

    truncate table AccessControl;
    truncate table Archive;
    truncate table ArchivedFields;
    truncate table ArchivedVersions;
    truncate table ArchivedItems;
    truncate table Blobs;
    truncate table ClientData;
    truncate table Descendants;
    truncate table EventQueue;
    truncate table History;
    truncate table IDTable;
    truncate table Links;
    truncate table Notifications;
    truncate table Properties;
    truncate table PublishQueue;
    truncate table SharedFields;
    truncate table Tasks;
    truncate table UnversionedFields;
    truncate table VersionedFields;
    truncate table WorkflowHistory;
    truncate table Items;
    
  3. DBA에서 소스/타켓 데이타베이스를 정하고, Migration을 시작한다.





  4. FTP를 통하여 Azure App Service에 연결하고, Custom 어플리케이션 또는 Config 파일들을 매뉴얼로 복사한다. (CMS / CDS if needs)
  5. Azure에서 App Service를 Restart한다.
  6. Sitecore CMS에 로그인하여 잘 작동(?)되는지 확인한다.
  7. Master DB만 Migration을 한 관계로, 혹 Core DB에서 Custom 업데이트가 있다면 사이트코어 CMS에서 패키지를 만들어 인스톨한다.
  8. 사이트코어 컨트롤 패널에서 "Clean up Databases"를 실행한다.
  9. 사이트코어 컨트롤 패널에서 "Rebuild Link DB"를 실행한다.
  10. 사이트코어 컨트롤 패널에서 "Rebuild Indexes"를 실행한다.
  11. 사이트코어 컨트롤 패널에서 "Deploy Marketing Definitions"을 실행한다.
  12. 사이트코어 컨트롤 패널에서 "Rebuild Link DB"를 실행한다.
  13. "Publish the site"를 통하여 Web DB로 컨텐츠를 Publish 한다.

DBA를 통하여 사이트코어 Migration을 하는데 아무런 문제없이 잘 진행될수있었다.