반응형

UIImageView의 코너를 조금 둥글게 만드는 방법을 알아보자.

 

UIImageView를 그냥 사용하면 요렇게 각지게 표현이 된다.

 

cell.imgView.layer.cornerRadius = 10

UIImageView에 위와 같이 설정해주면,

위와 같이 둥글둥글해지게 된다.

 

 

반응형
반응형

UICollectionView에 대해서 공부를 하다가, 

Cell을 만들고 배치를 해봤다.

 

내가 생각한 건, 좌 / 우로 배치가 되어야 하는데,

사진처럼 위 / 아래로 배치가 되버린다..

 

셀크기를 딱 CollectionView의 절반으로 했는데.. 왜 안될까..

뭐가 문제지 진짜 길이 하나하나 다 재보면서, 하루종일 알아보다가 찾아냈다.

 

원인은 UICollectionViewDelegateFlowLayout을 사용한게 원인이었는데,

해당 델리게이트의 

https://developer.apple.com/documentation/uikit/uicollectionviewdelegateflowlayout/1617696-collectionview

요 함수 때문이었다.

뭐, 아이템들의 간격을 설정해주는 함수다.

 

해당 함수의 설명을 보면, 요런게 있는데,

만약 해당 함수가 구현되어 있지 않으면, minimumInteritemSpacing 프로퍼티 값을 사용한다는 거다..

 

developer.apple.com/documentation/uikit/uicollectionviewflowlayout/1617706-minimuminteritemspacing

 

Apple Developer Documentation

 

developer.apple.com

위 링크가 minimumInteritemSpacing에 대한 설명인데,

기본값이 10.0 이다. 그래서.. 그래서.. 위/아래로 셀이 나왔던거다.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
   return 0
}

이 함수만 딱 설정해주면, 

 

요렇게 셀 두개가 딱 붙어있는 것을 볼 수 있다.

 

MyAlbum.zip
0.04MB

코드파일이다. 보통은 깃헙에 코드를 올리지만, 뭐랄까 간단한 것 같은 코드라서 그냥 파일로..

반응형
반응형

sronsemiro.tistory.com/9

 

Ubuntu 18.04.4 LTS, Nginx에 Let's Encrypt 설치 및 HTTPS적용(SSL)

1. Certbot 설치 // add repo $ sudo add-apt-repository ppa:certbot/certbot // install certbot $ sudo apt install python-certbot-nginx 2. HTTPS(SSL)을 설정할, nginx 설정 체크 // check server_name $ su..

sronsemiro.tistory.com

기존 시스템을 유지하고 있었으므로,

Ubuntu 18.04.4 / nginx 로 운영중이다.

 

예전에 작성해두었던, 위 글을 참조해서 오랜만에 SSL을 적용하려고 아래 명령어를 입력했다.

certbot --nginx -d AAA.co.kr -d www.AAA.co.kr

 

그랬더니, 생각보다 오랜 시간이 걸린 후, 아래와 같은 에러 메시지가 나왔다.

Failed authorization procedure. AAA.co.kr (http-01): urn:ietf:params:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://AAA.co.kr/.well-known/acme-challenge/96Ot7ZF9cVMwcycFhodd96TXi97sFQ9OR7Ln2sPpwN4 [183.111.125.112]: "\n<!DOCTYPE html>\n<html class=\"html\" lang=\"ko-KR\" itemscope itemtype=\"http://schema.org/WebPage\">\n<head>\n\t<meta charset=\"UTF-8\">\n", www.AAA.co.kr (http-01): urn:ietf:params:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://AAA.co.kr/.well-known/acme-challenge/YTz6-bfcu9UWltNrFoqkYxrURdasHSTSePse7oH6zyI [183.111.125.112]: "<html>\r\n<head><title>504 Gateway Time-out</title></head>\r\n<body>\r\n<center><h1>504 Gateway Time-out</h1></center>\r\n<hr><center>ng"

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: AAA.co.kr
   Type:   unauthorized
   Detail: Invalid response from
   http://AAA.co.kr/.well-known/acme-challenge/96Ot7ZF9cVMwcycFhodd96TXi97sFQ9OR7Ln2sPpwN4
   [183.111.125.112]: "\n<!DOCTYPE html>\n<html class=\"html\"
   lang=\"ko-KR\" itemscope
   itemtype=\"http://schema.org/WebPage\">\n<head>\n\t<meta
   charset=\"UTF-8\">\n"

   Domain: www.AAA.co.kr
   Type:   unauthorized
   Detail: Invalid response from
   http://AAA.co.kr/.well-known/acme-challenge/YTz6-bfcu9UWltNrFoqkYxrURdasHSTSePse7oH6zyI
   [183.111.125.112]: "<html>\r\n<head><title>504 Gateway
   Time-out</title></head>\r\n<body>\r\n<center><h1>504 Gateway
   Time-out</h1></center>\r\n<hr><center>ng"

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address.

이전이랑 똑같이 했는데,.. 왜 안되지..?

 

이것저것 찾아보니, 발생할 수 있는 이유는 여러가지가 있었다.

1. 해당 주소가 https로 리다이렉트 되고 있는 경우.

2. 해당 URL의 .well-known/acme-challenge/ <=== 이 경로로 접근이 안되는경우

3. 위 에러코드에도 나오듯이 제대로 된 IP주소가 아니거나 DNS 설정이 잘못된 경우 

등등..

 

근데 나는 아무것도 해당되지 않았다.

그래서 어떻게 해야 할까 고민하다가.

 

인증서만 발급받고 나머지 설정은 수동으로 하는 방법을 찾았고, 시도해봤다.

 

letsencrypt certonly --webroot --webroot-path=/var/www/AAA -d AAA.co.kr -d www.AAA.co.kr

certbot은 인증서를 발급받고, 설정까지 자동으로 해주는 반면

letsencrypt 명령어를 사용하면, 수동으로 설정해줄 수 있다. 

(이게 맞나? 정확히는 모르겠다..)

 

--webroot --webroot-path

여기서 --webroot는 인증서를 발급받을 홈페이지 소스가 있는 폴더의 경로를 적어주면 된다.

 

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for AAA.co.kr
http-01 challenge for www.AAA.co.kr
Using the webroot path /var/www/1800_7058_co_kr for all unmatched domains.
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/AAA.co.kr/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/AAA.co.kr/privkey.pem
   Your cert will expire on 2020-12-18. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

 

명령어를 실행하면, 위와 같이 잘 되었다고 나온다.

그러면, /etc/letsencrypt/archive/AAA.co.kr 경로아래에 인증서들이 발급된 것을 확인할 수 있다.

 

그럼 이제, 이 인증서들을 이용해서, nginx에 설정해주면 된다.

server {
 ## 이 부분은 http로 접속하면, https로 리다이렉트 시켜주는 부분이다 ##
 listen 80;
 root /var/www/AAA;
 server_name AAA.co.kr www.AAA.co.kr;

 return       301 https://$server_name$request_uri;
}

server {
 listen 443 ssl http2;
 root /var/www/sbcompany_co_kr;
 server_name AAA.co.kr www.AAA.co.kr;
 index index.php;

 ## 아래 4줄이 아까 발급받은 인증서를 설정 하는 부분이다. ##
 ssl_certificate /etc/letsencrypt/live/AAA.co.kr/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/AAA.co.kr/privkey.pem;
 include /etc/letsencrypt/options-ssl-nginx.conf;
 ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

 modsecurity on;
 modsecurity_rules_file /etc/nginx/modsec/modsec_includes.conf;
 #modsecurity_rules_file /etc/nginx/modsec/modsecurity.conf;

 location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
     access_log        off;
     log_not_found     off;
     expires           360d;
 }

 access_log /var/log/nginx/sbcompany_co_kr/access.log;

 location / {
 try_files $uri $uri/ /index.php?q=uri&$args;
 }

 location ~ \.php$ {
 include snippets/fastcgi-php.conf;
 fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
 }

 location ~ /xmlrpc.php {
  deny all;
  return 444;
 }
}

nginx에 해당 사이트의 site설정에 위 4줄을 추가해주면 된다.

끝~~

 

반응형
반응형

서버환경

Ubuntu 18.04.4 LTS

Nginx 1.19.1

 

기존 운영 도메인

1. AAA.com

2. BBB.Com (SSL 적용완료)

3. a.CCC.com

4 b.CCC.com (SSL 적용완료)

..등등 약 30개 정도 사이트

 

위 환경의 서버에서, Letsencrypt를 이용해서, 추가로 x.CCC.com 사이트에 SSL를 설정하고 있었다.

그런데, 자꾸 인증과정에서 에러가 발생했고,

추가적으로, https://asdf.CCC.com 과 같이 현재 서버에는 설정되어 있지 않은, 주소로 접속을 시도하면, 

기존에 SSL이 설정되어 있던, https://BBB.com 으로 접속이 되는 현상이 있었다.

 

이게, 기존부터 이렇게 되었던 건지,

아니면, 어떤 이유로 발생 했는지는 모르겠다.

 

여기저기 찾아보다가, 

qastack.kr/server/578648/properly-setting-up-a-default-nginx-server-for-https

 

위의 링크를 찾게 되었고, 해결했다.

 

이유는 바로, default 파일이 없어서 발생했던거다.

또한, default 파일도, http로 접속했을때와, https로 접속했을때 둘다를 설정해주어야 한다.

 

나는 그래서 아래와 같이 설정했다.

server {
  listen 80 default_server;
  listen [::]:80 default_server;
  listen 443 default_server;
  listen [::]:443 default_server;

  root /var/www/html;
  index index.html;

  server_name _;

  ssl_certificate /etc/nginx/ssl/nginx.crt;
  ssl_certificate_key /etc/nginx/ssl/nginx.key;

  location / {
    try_files $uri $uri/ =404;
    }
}

 

이렇게 설정후, nginx를 재시작 또는 reload를 하면,

위의 설명했던 현상이 발생하지 않게 된다.

 

또, default를 설정하지 않았을 때,

없는 주소로, https 를 이용해서 접속하게 되면,

https://BBB.com이 접속되는데, 

아마 그 이유는 sites-available 안에 파일 중,

SSL이 설정된 가장 첫번째 파일의 주소로 접속되는 것 같다. (알파벳 순)

 

반응형
반응형

이상하게, 서버가 느려지는 것 같은 느낌이 들어서,

nginx 서버 튜닝을 알아보다 보니, log에 관련된 이야기가 나왔다.

그래서, 어떻게 되어있나 살펴보니.. 헉..

80만 라인이 넘어가고 있었다..

 

아아..

 

어떻게 해야 하나 찾아보다가

logrotate를 알게 되었다.

 

일단 logrotate를 설치하자.

sudo apt-get install logrotate

 

그리고, /etc/logrotate.d/nginx 파일을 만들고

아래 코드를 추가하자.

## 보통은 이 부분만 만든다.
/var/log/nginx/*.log {
        daily
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 640 nginx adm
        sharedscripts
        postrotate
                if [ -f /var/run/nginx.pid ]; then
                        kill -USR1 `cat /var/run/nginx.pid`
                fi
        endscript
}

## 나는 로그를 서브도메인별로 따로따로 저장하게 설정이 되어있어서,
## 이 부분까지 설정해 주었다.
/var/log/nginx/*/*.log {
        daily
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 640 nginx adm
        sharedscripts
        postrotate
                if [ -f /var/run/nginx.pid ]; then
                        kill -USR1 `cat /var/run/nginx.pid`
                fi
        endscript
}

각각이 뜻하는 바를 알아보면,

  • daily : 하루치를 따로따로 보관하자.
  • missingok : 로그 파일이 없어도 에러를 내지말자.
  • rotate 52 : 로그 파일을 52개까지만 보관하자. 위에 daily로 설정되어 있으니, 52일치만 보관하고, 53일째 되는 로그는 삭제.
  • compress : 로그를 압축해서 보관하자.
  • notifempty: 로그파일이 비어있으면, 로테이트 하지 않습니다.
  • create 640 nginx adm : 로그파일은 새로 생성시에, 파일 권한을 640으로 생성하고, 소유자/그룹은 nginx로 하자.
  • postrotate : 로테이트 작업이 끝난후에, 실행할 스크립트를 입력합니다.

 

위 설정 후, 정상적으로 설정되었는지, 테스트하기 위해서 아래의 명령어를 실행합니다.

logrotate -d -f /etc/logrotate.d/nginx

 

정상적으로 설정되었다면, /etc/cron.daily/logrotate 파일로 인해서, 매일 자동 실행됩니다.

 

혹시, /etc/cron.daily/logrotate 파일이 없다면,

아래와 같이 만들어 주자.

 

#!/bin/sh

# Clean non existent log file entries from status file
cd /var/lib/logrotate
test -e status || touch status
head -1 status > status.clean
sed 's/"//g' status | while read logfile date
do
    [ -e "$logfile" ] && echo "\"$logfile\" $date"
done >> status.clean
mv status.clean status

test -x /usr/sbin/logrotate || exit 0
/usr/sbin/logrotate /etc/logrotate.conf

 

 

참고 : https://www.lesstif.com/system-admin/nginx-log-rotate-logrotate-75956229.html

반응형
반응형

남의 코드를 보다 보니, 

convenience init 이라는 키워드가 나와서, 알아보기로 했다.

 

    public init(grid: Grid = Grid(), sections: [Section] = []) {
        self.grid = grid
        self.sections = sections
        
        super.init()
    }
    
    public convenience init(grid: Grid = Grid(), _ sections: [[ViewModelProtocol]]) {
        let sections = sections.map { items in
            return Section(grid: grid, header: nil, footer: nil, items: items)
        }
        self.init(grid: grid, sections: sections)  ## convenience init 함수에는 이렇게, 다른 init함수를 호출해줘야 한다.
    }

따로, 예제가 없어서, 현재 내가 보고 있는 코드를 예제로 쓴다.

저자가 마음대로 막 가져다 쓰라고 했으니... 

 

convenience init은 init함수와 똑같은데, 파라미터 중 일부를 기본값으로 가져올 수 있다.

그리고, 약간 보조적인 성경의 init이다 보니, 꼭 다른 init을 호출해줘야 한다는 규칙이 있다.

 

반응형
반응형

UICollectionView에 대해서 공부하던 중에,

https://theswiftdev.com/ultimate-uicollectionview-guide-with-ios-examples-written-in-swift/

 

위 포스트를 보게 되었고, 이분이 만든 CollectionView 프레임워크를 분석해보자고 마음 먹었다.

사실.. CollectionView 사용법이 나한테는 생각보다 어렵게 느껴져서,

이분이 만든 프레임워크와 예제를 분석하다 보면, 쉽게 이해될 수도 있을 것 같다는 조금의 희망을 가지고 시작한거다.

겸사겸사 swift 공부도 해볼겸..

 

그러다가, 아래와 같은 코드를 만나게 되었는데,

open 이라는 키워드를 처음 본 것 같아서, 이참에 알아봐야겠다 싶었다.

open class CollectionView: UICollectionView {

    open var source: Source? = nil {
        didSet {
            self.source?.register(itemsFor: self)

            self.dataSource = self.source
            self.delegate = self.source
        }
    }
}

 

https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html#//apple_ref/doc/uid/TP40014097-CH41-ID3

Swift 문서에서 이런걸 찾게 되었다.

Access Levels

Swift provides five different access levels for entities within your code. These access levels are relative to the source file in which an entity is defined, and also relative to the module that source file belongs to.

  • Open access and public access enable entities to be used within any source file from their defining module, and also in a source file from another module that imports the defining module. You typically use open or public access when specifying the public interface to a framework. The difference between open and public access is described below.
  • Internal access enables entities to be used within any source file from their defining module, but not in any source file outside of that module. You typically use internal access when defining an app’s or a framework’s internal structure.
  • File-private access restricts the use of an entity to its own defining source file. Use file-private access to hide the implementation details of a specific piece of functionality when those details are used within an entire file.
  • Private access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.

Open access is the highest (least restrictive) access level and private access is the lowest (most restrictive) access level.

Open access applies only to classes and class members, and it differs from public access by allowing code outside the module to subclass and override, as discussed below in Subclassing. Marking a class as open explicitly indicates that you’ve considered the impact of code from other modules using that class as a superclass, and that you’ve designed your class’s code accordingly.

 

----------

 

Swift에는 5가지 접근 레벨이 있다.

5가지 레벨에는 open, public, internal access, file-private, private 가 있다.

 

위의 영어로 entities라고 있는데, 엔티티프로퍼티, 타입, 함수 등등을 이야기 한다고 합니다.

모듈(Module)은 쉽게 프레임워크라고 생각하면 좋을 것 같다.

 

open

- class에와 class member에만 사용할 수 있다.

- 모든 곳에서 sub classing이 가능하다.

 

public

- 클래스에 붙어있는 경우, 모듈 내에서만 sub classing이 가능하다.

 

Internal access

- 모듈 안에서 사용 가능

 

File-private

- 소스 파일 안에서만 사용 가능

 

private

- 소스 파일 안, 해당 선언 안에서만 사용 가능

반응형
반응형

파일만 변경

find ./ -type f -exec chmod -v 권한 {} \;
예: find ./ type f -exec chmod -v 755 {} \;

 

폴더만 변경

find ./ -type d -exec chmod -v 권한 {} \;
예: find ./ type d -exec chmod -v 755 {} \;

 

해당 파일만 변경

find ./ -type f -name 파일이름 -exec chmod -v 권한 {} \;
예: find ./ type f -name text.txt -exec chmod -v 755 {} \;

 

해당 파일을 제외하고 변경

find ./ -type f \! -name 파일이름 -exec chmod -v 권한 {} \;
예: find ./ type f \! -name text.txt -exec chmod -v 755 {} \;

 

해당 폴더만 변경

find ./ -type d -name 폴더이름 -exec chmod -v 권한 {} \;
예: find ./ type d -name testFolder -exec chmod -v 755 {} \;

 

해당 폴더를 제외하고 변경

find ./ -type d \! -name 폴더이름 -exec chmod -v 권한 {} \;
예: find ./ type d \! -name testFolder -exec chmod -v 755 {} \;

 

파일과 폴더 모두 변경

chmod -R 권한 *
예: chmod -R 755 *
반응형

+ Recent posts